kranewm

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in C++
git clone git clone git://git.deurzen.net/kranewm.git
Log | Files | Refs | LICENSE

commit 40cde757c5c9d758f6fb8b98da0bafe0153ed918
parent 7e4f4bda6b4bb314ef85ed9f7fa56f448f19a54d
Author: deurzen <m.deurzen@tum.de>
Date:   Thu, 30 Sep 2021 04:58:31 +0200

layout overhaul; adds deck layouts

Diffstat:
Msrc/core/client.cc | 12+++++++++++-
Msrc/core/client.hh | 2++
Msrc/core/layout.cc | 652+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/core/layout.hh | 48+++++++++++++++++++++++++-----------------------
Msrc/core/model.cc | 126++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/core/workspace.cc | 13+++++++++----
Msrc/core/workspace.hh | 3++-
7 files changed, 576 insertions(+), 280 deletions(-)

diff --git a/src/core/client.cc b/src/core/client.cc @@ -53,6 +53,7 @@ Client::Client( attaching(false), pid(pid), ppid(ppid), + last_touched(std::chrono::steady_clock::now()), last_focused(std::chrono::steady_clock::now()), managed_since(std::chrono::steady_clock::now()), expected_unmap_count(0), @@ -72,10 +73,19 @@ Client::get_outside_state() const } void +Client::touch() +{ + last_touched = std::chrono::steady_clock::now(); +} + +void Client::focus() { focused = true; - last_focused = std::chrono::steady_clock::now(); + + auto now = std::chrono::steady_clock::now(); + last_touched = now; + last_focused = now; switch (m_outside_state) { case OutsideState::Unfocused: m_outside_state = OutsideState::Focused; return; diff --git a/src/core/client.hh b/src/core/client.hh @@ -61,6 +61,7 @@ typedef struct Client final OutsideState get_outside_state() const; + void touch(); void focus(); void unfocus(); @@ -121,6 +122,7 @@ typedef struct Client final bool attaching; std::optional<winsys::Pid> pid; std::optional<winsys::Pid> ppid; + std::chrono::time_point<std::chrono::steady_clock> last_touched; std::chrono::time_point<std::chrono::steady_clock> last_focused; std::chrono::time_point<std::chrono::steady_clock> managed_since; std::size_t expected_unmap_count; diff --git a/src/core/layout.cc b/src/core/layout.cc @@ -33,22 +33,25 @@ LayoutHandler::LayoutHandler() : m_kind(LayoutKind::Float), m_prev_kind(LayoutKind::Float), m_layouts({ - { LayoutKind::Float, new Layout(LayoutKind::Float) }, - { LayoutKind::BLFloat, new Layout(LayoutKind::BLFloat) }, - { LayoutKind::SingleFloat, new Layout(LayoutKind::SingleFloat) }, - { LayoutKind::BLSingleFloat, new Layout(LayoutKind::BLSingleFloat) }, - { LayoutKind::Center, new Layout(LayoutKind::Center) }, - { LayoutKind::Monocle, new Layout(LayoutKind::Monocle) }, - { LayoutKind::Paper, new Layout(LayoutKind::Paper) }, - { LayoutKind::SPaper, new Layout(LayoutKind::SPaper) }, - { LayoutKind::Stack, new Layout(LayoutKind::Stack) }, - { LayoutKind::SStack, new Layout(LayoutKind::SStack) }, - { LayoutKind::BStack, new Layout(LayoutKind::BStack) }, - { LayoutKind::SBStack, new Layout(LayoutKind::SBStack) }, - { LayoutKind::Horz, new Layout(LayoutKind::Horz) }, - { LayoutKind::SHorz, new Layout(LayoutKind::SHorz) }, - { LayoutKind::Vert, new Layout(LayoutKind::Vert) }, - { LayoutKind::SVert, new Layout(LayoutKind::SVert) } +#define NEW_LAYOUT(layout) { layout, new Layout(layout) } + NEW_LAYOUT(LayoutKind::Float), + NEW_LAYOUT(LayoutKind::FramelessFloat), + NEW_LAYOUT(LayoutKind::SingleFloat), + NEW_LAYOUT(LayoutKind::FramelessSingleFloat), + NEW_LAYOUT(LayoutKind::Center), + NEW_LAYOUT(LayoutKind::Monocle), + NEW_LAYOUT(LayoutKind::MainDeck), + NEW_LAYOUT(LayoutKind::StackDeck), + NEW_LAYOUT(LayoutKind::DoubleDeck), + NEW_LAYOUT(LayoutKind::Paper), + NEW_LAYOUT(LayoutKind::CompactPaper), + NEW_LAYOUT(LayoutKind::DoubleStack), + NEW_LAYOUT(LayoutKind::CompactDoubleStack), + NEW_LAYOUT(LayoutKind::HorizontalStack), + NEW_LAYOUT(LayoutKind::CompactHorizontalStack), + NEW_LAYOUT(LayoutKind::VerticalStack), + NEW_LAYOUT(LayoutKind::CompactVerticalStack), +#undef NEW_LAYOUT }), mp_layout(m_layouts.at(m_kind)), mp_prev_layout(m_layouts.at(m_kind)) @@ -80,22 +83,91 @@ LayoutHandler::arrange( } switch (m_kind) { - case LayoutKind::Float: arrange_float(screen_region, placements, begin, end); break; - case LayoutKind::BLFloat: arrange_blfloat(screen_region, placements, begin, end); break; - case LayoutKind::SingleFloat: arrange_singlefloat(screen_region, placements, begin, end); break; - case LayoutKind::BLSingleFloat: arrange_blsinglefloat(screen_region, placements, begin, end); break; - case LayoutKind::Center: arrange_center(screen_region, placements, begin, end); break; - case LayoutKind::Monocle: arrange_monocle(screen_region, placements, begin, end); break; - case LayoutKind::Paper: arrange_paper(screen_region, placements, begin, end); break; - case LayoutKind::SPaper: arrange_spaper(screen_region, placements, begin, end); break; - case LayoutKind::Stack: arrange_stack(screen_region, placements, begin, end); break; - case LayoutKind::SStack: arrange_sstack(screen_region, placements, begin, end); break; - case LayoutKind::BStack: arrange_bstack(screen_region, placements, begin, end); break; - case LayoutKind::SBStack: arrange_sbstack(screen_region, placements, begin, end); break; - case LayoutKind::Horz: arrange_horz(screen_region, placements, begin, end); break; - case LayoutKind::SHorz: arrange_shorz(screen_region, placements, begin, end); break; - case LayoutKind::Vert: arrange_vert(screen_region, placements, begin, end); break; - case LayoutKind::SVert: arrange_svert(screen_region, placements, begin, end); break; + case LayoutKind::Float: + { + arrange_float(screen_region, placements, begin, end); + break; + } + case LayoutKind::FramelessFloat: + { + arrange_frameless_float(screen_region, placements, begin, end); + break; + } + case LayoutKind::SingleFloat: + { + arrange_single_float(screen_region, placements, begin, end); + break; + } + case LayoutKind::FramelessSingleFloat: + { + arrange_frameless_single_float(screen_region, placements, begin, end); + break; + } + case LayoutKind::Center: + { + arrange_center(screen_region, placements, begin, end); + break; + } + case LayoutKind::Monocle: + { + arrange_monocle(screen_region, placements, begin, end); + break; + } + case LayoutKind::MainDeck: + { + arrange_main_deck(screen_region, placements, begin, end); + break; + } + case LayoutKind::StackDeck: + { + arrange_stack_deck(screen_region, placements, begin, end); + break; + } + case LayoutKind::DoubleDeck: + { + arrange_double_deck(screen_region, placements, begin, end); + break; + } + case LayoutKind::Paper: + { + arrange_paper(screen_region, placements, begin, end); + break; + } + case LayoutKind::CompactPaper: + { + arrange_compact_paper(screen_region, placements, begin, end); + break; + } + case LayoutKind::DoubleStack: + { + arrange_double_stack(screen_region, placements, begin, end); + break; + } + case LayoutKind::CompactDoubleStack: + { + arrange_compact_double_stack(screen_region, placements, begin, end); + break; + } + case LayoutKind::HorizontalStack: + { + arrange_horizontal_stack(screen_region, placements, begin, end); + break; + } + case LayoutKind::CompactHorizontalStack: + { + arrange_compact_horizontal_stack(screen_region, placements, begin, end); + break; + } + case LayoutKind::VerticalStack: + { + arrange_vertical_stack(screen_region, placements, begin, end); + break; + } + case LayoutKind::CompactVerticalStack: + { + arrange_compact_vertical_stack(screen_region, placements, begin, end); + break; + } } if (mp_layout->config.gap) { @@ -445,7 +517,7 @@ LayoutHandler::arrange_float( } void -LayoutHandler::arrange_blfloat( +LayoutHandler::arrange_frameless_float( Region screen_region, placement_vector placements, client_iter begin, @@ -456,7 +528,7 @@ LayoutHandler::arrange_blfloat( } void -LayoutHandler::arrange_singlefloat( +LayoutHandler::arrange_single_float( Region, placement_vector placements, client_iter begin, @@ -479,14 +551,14 @@ LayoutHandler::arrange_singlefloat( } void -LayoutHandler::arrange_blsinglefloat( +LayoutHandler::arrange_frameless_single_float( Region screen_region, placement_vector placements, client_iter begin, client_iter end ) const { - arrange_singlefloat(screen_region, placements, begin, end); + arrange_single_float(screen_region, placements, begin, end); } void @@ -556,6 +628,271 @@ LayoutHandler::arrange_monocle( } void +LayoutHandler::arrange_main_deck( + Region screen_region, + placement_vector placements, + client_iter begin, + client_iter end +) const +{ + const Layout::LayoutData_ptr data = *mp_layout->data.active_element(); + std::size_t n = end - begin; + + if (n == 1) { + placements.emplace_back(Placement { + mp_layout->config.method, + *begin, + Decoration::NO_DECORATION, + screen_region + }); + + return; + } + + std::size_t n_main; + std::size_t n_stack; + + if (n <= data->main_count) { + n_main = n; + n_stack = 0; + } else { + n_main = data->main_count; + n_stack = n - n_main; + } + + int w_main + = data->main_count > 0 + ? static_cast<float>(screen_region.dim.w) * data->main_factor + : 0; + + int x_stack = screen_region.pos.x + w_main; + int w_stack = screen_region.dim.w - w_main; + int h_main = n_main > 0 ? screen_region.dim.h : 0; + int h_stack = n_stack > 0 ? screen_region.dim.h / n_stack : 0; + + std::size_t i = 0; + + std::transform( + begin, + end, + std::back_inserter(placements), + [=,this,&i](Client_ptr client) -> Placement { + if (i < data->main_count) { + ++i; + return Placement { + mp_layout->config.method, + client, + mp_layout->config.decoration, + Region { + Pos { + screen_region.pos.x, + screen_region.pos.y + }, + Dim { + n_stack == 0 ? screen_region.dim.w : w_main, + h_main + } + } + }; + } else { + return Placement { + mp_layout->config.method, + client, + mp_layout->config.decoration, + Region { + Pos { + x_stack, + screen_region.pos.y + + static_cast<int>((i++ - data->main_count) * h_stack) + }, + Dim { + w_stack, + h_stack + } + } + }; + } + } + ); +} + +void +LayoutHandler::arrange_stack_deck( + Region screen_region, + placement_vector placements, + client_iter begin, + client_iter end +) const +{ + const Layout::LayoutData_ptr data = *mp_layout->data.active_element(); + std::size_t n = end - begin; + + if (n == 1) { + placements.emplace_back(Placement { + mp_layout->config.method, + *begin, + Decoration::NO_DECORATION, + screen_region + }); + + return; + } + + std::size_t n_main; + std::size_t n_stack; + + if (n <= data->main_count) { + n_main = n; + n_stack = 0; + } else { + n_main = data->main_count; + n_stack = n - n_main; + } + + int w_main + = data->main_count > 0 + ? static_cast<float>(screen_region.dim.w) * data->main_factor + : 0; + + int x_stack = screen_region.pos.x + w_main; + int w_stack = screen_region.dim.w - w_main; + int h_main = n_main > 0 ? screen_region.dim.h / n_main : 0; + int h_stack = n_stack > 0 ? screen_region.dim.h : 0; + + std::size_t i = 0; + + std::transform( + begin, + end, + std::back_inserter(placements), + [=,this,&i](Client_ptr client) -> Placement { + if (i < data->main_count) { + return Placement { + mp_layout->config.method, + client, + mp_layout->config.decoration, + Region { + Pos { + screen_region.pos.x, + screen_region.pos.y + + static_cast<int>(i++) * h_main + }, + Dim { + n_stack == 0 ? screen_region.dim.w : w_main, + h_main + } + } + }; + } else { + ++i; + return Placement { + mp_layout->config.method, + client, + mp_layout->config.decoration, + Region { + Pos { + x_stack, + screen_region.pos.y + }, + Dim { + w_stack, + h_stack + } + } + }; + } + } + ); +} + +void +LayoutHandler::arrange_double_deck( + Region screen_region, + placement_vector placements, + client_iter begin, + client_iter end +) const +{ + const Layout::LayoutData_ptr data = *mp_layout->data.active_element(); + std::size_t n = end - begin; + + if (n == 1) { + placements.emplace_back(Placement { + mp_layout->config.method, + *begin, + Decoration::NO_DECORATION, + screen_region + }); + + return; + } + + std::size_t n_main; + std::size_t n_stack; + + if (n <= data->main_count) { + n_main = n; + n_stack = 0; + } else { + n_main = data->main_count; + n_stack = n - n_main; + } + + int w_main + = data->main_count > 0 + ? static_cast<float>(screen_region.dim.w) * data->main_factor + : 0; + + int x_stack = screen_region.pos.x + w_main; + int w_stack = screen_region.dim.w - w_main; + int h_main = n_main > 0 ? screen_region.dim.h : 0; + int h_stack = n_stack > 0 ? screen_region.dim.h : 0; + + std::size_t i = 0; + + std::transform( + begin, + end, + std::back_inserter(placements), + [=,this,&i](Client_ptr client) -> Placement { + if (i++ < data->main_count) { + return Placement { + mp_layout->config.method, + client, + mp_layout->config.decoration, + Region { + Pos { + screen_region.pos.x, + screen_region.pos.y + }, + Dim { + n_stack == 0 ? screen_region.dim.w : w_main, + h_main + } + } + }; + } else { + return Placement { + mp_layout->config.method, + client, + mp_layout->config.decoration, + Region { + Pos { + x_stack, + screen_region.pos.y + }, + Dim { + w_stack, + h_stack + } + } + }; + } + } + ); +} + +void LayoutHandler::arrange_paper( Region screen_region, placement_vector placements, @@ -659,7 +996,7 @@ LayoutHandler::arrange_paper( } void -LayoutHandler::arrange_spaper( +LayoutHandler::arrange_compact_paper( Region screen_region, placement_vector placements, client_iter begin, @@ -670,7 +1007,7 @@ LayoutHandler::arrange_spaper( } void -LayoutHandler::arrange_stack( +LayoutHandler::arrange_double_stack( Region screen_region, placement_vector placements, client_iter begin, @@ -759,40 +1096,18 @@ LayoutHandler::arrange_stack( } void -LayoutHandler::arrange_sstack( - Region screen_region, - placement_vector placements, - client_iter begin, - client_iter end -) const -{ - arrange_stack(screen_region, placements, begin, end); -} - -void -LayoutHandler::arrange_bstack( - Region screen_region, - placement_vector placements, - client_iter begin, - client_iter end -) const -{ - arrange_stack(screen_region, placements, begin, end); -} - -void -LayoutHandler::arrange_sbstack( +LayoutHandler::arrange_compact_double_stack( Region screen_region, placement_vector placements, client_iter begin, client_iter end ) const { - arrange_bstack(screen_region, placements, begin, end); + arrange_double_stack(screen_region, placements, begin, end); } void -LayoutHandler::arrange_horz( +LayoutHandler::arrange_horizontal_stack( Region screen_region, placement_vector placements, client_iter begin, @@ -840,18 +1155,18 @@ LayoutHandler::arrange_horz( } void -LayoutHandler::arrange_shorz( +LayoutHandler::arrange_compact_horizontal_stack( Region screen_region, placement_vector placements, client_iter begin, client_iter end ) const { - arrange_horz(screen_region, placements, begin, end); + arrange_horizontal_stack(screen_region, placements, begin, end); } void -LayoutHandler::arrange_vert( +LayoutHandler::arrange_vertical_stack( Region screen_region, placement_vector placements, client_iter begin, @@ -899,14 +1214,14 @@ LayoutHandler::arrange_vert( } void -LayoutHandler::arrange_svert( +LayoutHandler::arrange_compact_vertical_stack( Region screen_region, placement_vector placements, client_iter begin, client_iter end ) const { - arrange_vert(screen_region, placements, begin, end); + arrange_vertical_stack(screen_region, placements, begin, end); } @@ -926,7 +1241,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::BLFloat: + case LayoutKind::FramelessFloat: { return LayoutConfig { Placement::PlacementMethod::Free, @@ -950,7 +1265,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::BLSingleFloat: + case LayoutKind::FramelessSingleFloat: { return LayoutConfig { Placement::PlacementMethod::Free, @@ -986,43 +1301,43 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::Paper: + case LayoutKind::MainDeck: { return LayoutConfig { Placement::PlacementMethod::Tile, Decoration { std::nullopt, Frame { - Extents { 1, 1, 0, 0 }, + Extents { 0, 0, 3, 0 }, ColorScheme::DEFAULT_COLOR_SCHEME } }, true, true, - true, false, - false + false, + true }; } - case LayoutKind::SPaper: + case LayoutKind::StackDeck: { return LayoutConfig { Placement::PlacementMethod::Tile, Decoration { std::nullopt, Frame { - Extents { 1, 1, 0, 0 }, + Extents { 0, 0, 3, 0 }, ColorScheme::DEFAULT_COLOR_SCHEME } }, true, - false, true, false, - false + false, + true }; } - case LayoutKind::Stack: + case LayoutKind::DoubleDeck: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1040,25 +1355,43 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::SStack: + case LayoutKind::Paper: { return LayoutConfig { Placement::PlacementMethod::Tile, Decoration { std::nullopt, Frame { - Extents { 0, 0, 3, 0 }, + Extents { 1, 1, 0, 0 }, ColorScheme::DEFAULT_COLOR_SCHEME } }, true, + true, + true, false, + false + }; + } + case LayoutKind::CompactPaper: + { + return LayoutConfig { + Placement::PlacementMethod::Tile, + Decoration { + std::nullopt, + Frame { + Extents { 1, 1, 0, 0 }, + ColorScheme::DEFAULT_COLOR_SCHEME + } + }, + true, false, + true, false, - true + false }; } - case LayoutKind::BStack: + case LayoutKind::DoubleStack: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1076,7 +1409,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::SBStack: + case LayoutKind::CompactDoubleStack: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1094,7 +1427,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::Horz: + case LayoutKind::HorizontalStack: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1112,7 +1445,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::SHorz: + case LayoutKind::CompactHorizontalStack: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1130,7 +1463,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::Vert: + case LayoutKind::VerticalStack: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1148,7 +1481,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) true }; } - case LayoutKind::SVert: + case LayoutKind::CompactVerticalStack: { return LayoutConfig { Placement::PlacementMethod::Tile, @@ -1176,42 +1509,6 @@ LayoutHandler::Layout::LayoutData LayoutHandler::Layout::kind_to_default_data(LayoutKind kind) { switch (kind) { - case LayoutKind::Float: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::BLFloat: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::SingleFloat: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::BLSingleFloat: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } case LayoutKind::Center: { return Layout::LayoutData { @@ -1221,97 +1518,22 @@ LayoutHandler::Layout::kind_to_default_data(LayoutKind kind) .40f }; } - case LayoutKind::Monocle: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::Paper: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::SPaper: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::Stack: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::SStack: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::BStack: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::SBStack: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::Horz: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::SHorz: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::Vert: - { - return Layout::LayoutData { - Extents { 0, 0, 0, 0 }, - 0, - 1, - .50f - }; - } - case LayoutKind::SVert: + case LayoutKind::Float: // fallthrough + case LayoutKind::FramelessFloat: // fallthrough + case LayoutKind::SingleFloat: // fallthrough + case LayoutKind::FramelessSingleFloat: // fallthrough + case LayoutKind::Monocle: // fallthrough + case LayoutKind::MainDeck: // fallthrough + case LayoutKind::StackDeck: // fallthrough + case LayoutKind::DoubleDeck: // fallthrough + case LayoutKind::Paper: // fallthrough + case LayoutKind::CompactPaper: // fallthrough + case LayoutKind::DoubleStack: // fallthrough + case LayoutKind::CompactDoubleStack: // fallthrough + case LayoutKind::HorizontalStack: // fallthrough + case LayoutKind::CompactHorizontalStack: // fallthrough + case LayoutKind::VerticalStack: // fallthrough + case LayoutKind::CompactVerticalStack: { return Layout::LayoutData { Extents { 0, 0, 0, 0 }, diff --git a/src/core/layout.hh b/src/core/layout.hh @@ -20,25 +20,26 @@ public: { /// free layouts Float, - BLFloat, + FramelessFloat, SingleFloat, - BLSingleFloat, + FramelessSingleFloat, // overlapping tiled layouts Center, Monocle, + MainDeck, + StackDeck, + DoubleDeck, // non-overlapping tiled layouts Paper, - SPaper, - Stack, - SStack, - BStack, - SBStack, - Horz, - SHorz, - Vert, - SVert, + CompactPaper, + DoubleStack, + CompactDoubleStack, + HorizontalStack, + CompactHorizontalStack, + VerticalStack, + CompactVerticalStack, }; private: @@ -153,21 +154,22 @@ private: Layout_ptr mp_prev_layout; void arrange_float(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_blfloat(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_singlefloat(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_blsinglefloat(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_frameless_float(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_single_float(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_frameless_single_float(winsys::Region, placement_vector, client_iter, client_iter) const; void arrange_center(winsys::Region, placement_vector, client_iter, client_iter) const; void arrange_monocle(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_main_deck(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_stack_deck(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_double_deck(winsys::Region, placement_vector, client_iter, client_iter) const; void arrange_paper(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_spaper(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_stack(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_sstack(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_bstack(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_sbstack(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_horz(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_shorz(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_vert(winsys::Region, placement_vector, client_iter, client_iter) const; - void arrange_svert(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_compact_paper(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_double_stack(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_compact_double_stack(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_horizontal_stack(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_compact_horizontal_stack(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_vertical_stack(winsys::Region, placement_vector, client_iter, client_iter) const; + void arrange_compact_vertical_stack(winsys::Region, placement_vector, client_iter, client_iter) const; }; diff --git a/src/core/model.cc b/src/core/model.cc @@ -250,49 +250,52 @@ Model::Model(Connection& conn) CALL(set_layout(LayoutHandler::LayoutKind::Float)) }, { { Key::L, { Main, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::BLFloat)) + CALL(set_layout(LayoutHandler::LayoutKind::FramelessFloat)) }, { { Key::Z, { Main } }, CALL(set_layout(LayoutHandler::LayoutKind::SingleFloat)) }, { { Key::Z, { Main, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::BLSingleFloat)) + CALL(set_layout(LayoutHandler::LayoutKind::FramelessSingleFloat)) }, { { Key::M, { Main } }, CALL(set_layout(LayoutHandler::LayoutKind::Monocle)) }, + { { Key::D, { Main, Ctrl } }, + CALL(set_layout(LayoutHandler::LayoutKind::MainDeck)) + }, + { { Key::D, { Main, Shift } }, + CALL(set_layout(LayoutHandler::LayoutKind::StackDeck)) + }, + { { Key::D, { Main, Ctrl, Shift } }, + CALL(set_layout(LayoutHandler::LayoutKind::DoubleDeck)) + }, { { Key::G, { Main } }, CALL(set_layout(LayoutHandler::LayoutKind::Center)) }, { { Key::T, { Main } }, - CALL(set_layout(LayoutHandler::LayoutKind::Stack)) + CALL(set_layout(LayoutHandler::LayoutKind::DoubleStack)) }, { { Key::T, { Main, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::SStack)) + CALL(set_layout(LayoutHandler::LayoutKind::CompactDoubleStack)) }, { { Key::P, { Main, Ctrl, Shift } }, CALL(set_layout(LayoutHandler::LayoutKind::Paper)) }, { { Key::P, { Main, Sec, Ctrl, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::SPaper)) - }, - { { Key::B, { Main, Ctrl, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::BStack)) - }, - { { Key::B, { Main, Sec, Ctrl, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::SBStack)) + CALL(set_layout(LayoutHandler::LayoutKind::CompactPaper)) }, { { Key::Y, { Main, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::Horz)) + CALL(set_layout(LayoutHandler::LayoutKind::HorizontalStack)) }, { { Key::Y, { Main, Ctrl } }, - CALL(set_layout(LayoutHandler::LayoutKind::SHorz)) + CALL(set_layout(LayoutHandler::LayoutKind::CompactHorizontalStack)) }, { { Key::V, { Main, Shift } }, - CALL(set_layout(LayoutHandler::LayoutKind::Vert)) + CALL(set_layout(LayoutHandler::LayoutKind::VerticalStack)) }, { { Key::V, { Main, Ctrl } }, - CALL(set_layout(LayoutHandler::LayoutKind::SVert)) + CALL(set_layout(LayoutHandler::LayoutKind::CompactVerticalStack)) }, { { Key::F, { Main, Ctrl, Shift } }, CALL(set_layout_retain_region(LayoutHandler::LayoutKind::Float)) @@ -2181,10 +2184,29 @@ Model::apply_stack(Workspace_ptr workspace) { static std::vector<Window> stack; + static constexpr struct LastTouchedComparer final { + bool + operator()(const Client_ptr lhs, const Client_ptr rhs) const + { + return lhs->last_touched < rhs->last_touched; + } + } last_touched_comparer{}; + + static std::set<Client_ptr, LastTouchedComparer> last_touched_clients{{}, last_touched_comparer}; + if (workspace != mp_workspace) return; - std::vector<Client_ptr> clients = workspace->stack_after_focus(); + last_touched_clients.clear(); + std::for_each( + workspace->begin(), + workspace->end(), + [](Client_ptr client) { + last_touched_clients.insert(client); + } + ); + + std::vector<Client_ptr> clients{last_touched_clients.begin(), last_touched_clients.end()}; auto fullscreen_iter = std::stable_partition( clients.begin(), @@ -2271,7 +2293,6 @@ Model::apply_stack(Workspace_ptr workspace) } managed_since_comparer{}; static std::set<Client_ptr, ManagedSinceComparer> managed_since_clients{{}, managed_since_comparer}; - managed_since_clients.clear(); std::for_each( @@ -2297,32 +2318,21 @@ Model::apply_stack(Workspace_ptr workspace) m_conn.update_client_list(order_list); - static constexpr struct LastFocusedComparer final { - bool - operator()(const Client_ptr lhs, const Client_ptr rhs) const - { - return lhs->last_focused < rhs->last_focused; - } - } last_focused_comparer{}; - - static std::set<Client_ptr, LastFocusedComparer> last_focused_clients{{}, last_focused_comparer}; - - last_focused_clients.clear(); - + last_touched_clients.clear(); std::for_each( m_client_map.begin(), m_client_map.end(), [](auto kv) { - last_focused_clients.insert(kv.second); + last_touched_clients.insert(kv.second); } ); - order_list.reserve(last_focused_clients.size()); + order_list.reserve(last_touched_clients.size()); order_list.clear(); std::transform( - last_focused_clients.begin(), - last_focused_clients.end(), + last_touched_clients.begin(), + last_touched_clients.end(), std::back_inserter(order_list), [](Client_ptr client) -> Window { return client->window; @@ -2389,13 +2399,35 @@ Model::rotate_clients(Direction direction) void Model::shuffle_main(winsys::Direction direction) { - if (mp_workspace->size() <= 1) + std::size_t main_count + = std::min(mp_workspace->main_count(), mp_workspace->size()); + + if (main_count <= 1) return; + Index focus_index = *mp_workspace->clients().index(); + std::optional<Index> last_touched_index = std::nullopt; + + if (focus_index >= main_count) { + Client_ptr last_touched = *std::max_element( + mp_workspace->begin(), + mp_workspace->begin() + main_count, + [](Client_ptr client1, Client_ptr client2) -> bool { + return client1->last_touched < client2->last_touched; + } + ); + + last_touched_index + = mp_workspace->clients().index_of_element(last_touched); + } + mp_workspace->shuffle_main(direction); focus_client(mp_workspace->active()); sync_focus(); + if (last_touched_index) + (*mp_workspace)[*last_touched_index]->touch(); + apply_layout(mp_workspace); apply_stack(mp_workspace); } @@ -2403,13 +2435,35 @@ Model::shuffle_main(winsys::Direction direction) void Model::shuffle_stack(winsys::Direction direction) { - if (mp_workspace->size() <= 1) + std::size_t main_count + = std::min(mp_workspace->main_count(), mp_workspace->size()); + + if ((mp_workspace->size() - main_count) <= 1) return; + Index focus_index = *mp_workspace->clients().index(); + std::optional<Index> last_touched_index = std::nullopt; + + if (focus_index < main_count) { + Client_ptr last_touched = *std::max_element( + mp_workspace->begin() + main_count, + mp_workspace->end(), + [](Client_ptr client1, Client_ptr client2) -> bool { + return client1->last_touched < client2->last_touched; + } + ); + + last_touched_index + = mp_workspace->clients().index_of_element(last_touched); + } + mp_workspace->shuffle_stack(direction); focus_client(mp_workspace->active()); sync_focus(); + if (last_touched_index) + (*mp_workspace)[*last_touched_index]->touch(); + apply_layout(mp_workspace); apply_stack(mp_workspace); } @@ -2514,7 +2568,7 @@ Model::set_layout(LayoutHandler::LayoutKind layout) void Model::set_layout_retain_region(LayoutHandler::LayoutKind layout) { - std::deque<Client_ptr> const& clients = mp_workspace->clients(); + Cycle<Client_ptr> const& clients = mp_workspace->clients(); std::vector<Region> regions; bool was_tiled = !mp_workspace->layout_is_free(); diff --git a/src/core/workspace.cc b/src/core/workspace.cc @@ -131,6 +131,12 @@ Workspace::length() const return m_clients.length(); } +std::size_t +Workspace::main_count() const +{ + return m_layout_handler.main_count(); +} + Context_ptr Workspace::context() const @@ -173,10 +179,10 @@ Workspace::active() const } -std::deque<Client_ptr> const& +Cycle<Client_ptr> const& Workspace::clients() const { - return m_clients.as_deque(); + return m_clients; } std::vector<Client_ptr> @@ -548,8 +554,7 @@ Workspace::set_layout(LayoutHandler::LayoutKind layout) std::vector<Placement> Workspace::arrange(winsys::Region region) const { - std::deque<Client_ptr> clients = this->clients(); - + std::deque<Client_ptr> clients = m_clients.as_deque(); std::vector<Placement> placements; placements.reserve(clients.size()); diff --git a/src/core/workspace.hh b/src/core/workspace.hh @@ -149,6 +149,7 @@ public: std::size_t size() const; std::size_t length() const; + std::size_t main_count() const; Context_ptr context() const; @@ -157,7 +158,7 @@ public: std::string identifier() const; Client_ptr active() const; - std::deque<Client_ptr> const& clients() const; + Cycle<Client_ptr> const& clients() const; std::vector<Client_ptr> stack_after_focus() const; Client_ptr next_client() const;