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 2235bbf91db2f0c42fdeb10ef7a0785fa954a6c7
parent 14cd58224fc083fe2d0727117a3853eae2d3d09d
Author: deurzen <m.deurzen@tum.de>
Date:   Wed, 29 Sep 2021 20:44:11 +0200

implements shuffle and reverse client arrangers

Diffstat:
Msrc/core/cycle.hh | 2++
Msrc/core/cycle.t.hh | 39+++++++++++++++++++++++++++++++++++++++
Msrc/core/model.cc | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/core/model.hh | 3+++
Msrc/core/workspace.cc | 21+++++++++++++++++++++
Msrc/core/workspace.hh | 3+++
6 files changed, 147 insertions(+), 7 deletions(-)

diff --git a/src/core/cycle.hh b/src/core/cycle.hh @@ -120,7 +120,9 @@ public: void swap_elements(T, T); void swap_indices(Index, Index); + void reverse(); void rotate(winsys::Direction); + void rotate_range(winsys::Direction, Index, Index); std::optional<T> cycle_active(winsys::Direction); std::optional<T> drag_active(winsys::Direction); diff --git a/src/core/cycle.t.hh b/src/core/cycle.t.hh @@ -429,6 +429,13 @@ Cycle<T>::swap_indices(Index index1, Index index2) template <typename T> void +Cycle<T>::reverse() +{ + std::reverse(m_elements.begin(), m_elements.end()); +} + +template <typename T> +void Cycle<T>::rotate(winsys::Direction direction) { switch (direction) { @@ -457,6 +464,38 @@ Cycle<T>::rotate(winsys::Direction direction) } template <typename T> +void +Cycle<T>::rotate_range(winsys::Direction direction, Index begin, Index end) +{ + if (begin >= end || begin >= m_elements.size() || end > m_elements.size()) + return; + + switch (direction) { + case winsys::Direction::Backward: + { + std::rotate( + m_elements.begin() + begin, + std::next(m_elements.begin() + begin), + m_elements.begin() + end + ); + + return; + } + case winsys::Direction::Forward: + { + std::rotate( + m_elements.rend() - end, + std::next(m_elements.rend() - end), + m_elements.rend() - begin + ); + + return; + } + default: return; + } +} + +template <typename T> std::optional<T> Cycle<T>::cycle_active(winsys::Direction direction) { diff --git a/src/core/model.cc b/src/core/model.cc @@ -93,21 +93,49 @@ Model::Model(Connection& conn) CALL(deiconify_all()) }, - // free client arrangers + // client arrangers { { Key::Space, { Main, Ctrl } }, CALL(center_focus()) }, { { Key::H, { Main, Ctrl } }, - CALL(nudge_focus(Edge::Left, 15)) + [](Model& model) { + Client_ptr focus = model.mp_focus; + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Left, 15); + else + model.shuffle_main(Direction::Backward); + } }, { { Key::J, { Main, Ctrl } }, - CALL(nudge_focus(Edge::Bottom, 15)) + [](Model& model) { + Client_ptr focus = model.mp_focus; + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Bottom, 15); + else + model.shuffle_stack(Direction::Forward); + } }, { { Key::K, { Main, Ctrl } }, - CALL(nudge_focus(Edge::Top, 15)) + [](Model& model) { + Client_ptr focus = model.mp_focus; + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Top, 15); + else + model.shuffle_stack(Direction::Backward); + } }, { { Key::L, { Main, Ctrl } }, - CALL(nudge_focus(Edge::Right, 15)) + [](Model& model) { + Client_ptr focus = model.mp_focus; + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Right, 15); + else + model.shuffle_main(Direction::Forward); + } }, { { Key::H, { Main, Ctrl, Shift } }, CALL(stretch_focus(Edge::Left, 15)) @@ -145,8 +173,6 @@ Model::Model(Connection& conn) { { Key::Right, { Main, Ctrl } }, CALL(snap_focus(Edge::Right)) }, - - // client order modifiers { { Key::J, { Main } }, CALL(cycle_focus(Direction::Forward)) }, @@ -159,6 +185,9 @@ Model::Model(Connection& conn) { { Key::K, { Main, Shift } }, CALL(drag_focus(Direction::Backward)) }, + { { Key::R, { Main } }, + CALL(reverse_clients()) + }, { { Key::SemiColon, { Main, Shift } }, CALL(rotate_clients(Direction::Forward)) }, @@ -2330,6 +2359,20 @@ Model::drag_focus(Direction direction) void +Model::reverse_clients() +{ + if (mp_workspace->size() <= 1) + return; + + mp_workspace->reverse(); + focus_client(mp_workspace->active()); + sync_focus(); + + apply_layout(mp_workspace); + apply_stack(mp_workspace); +} + +void Model::rotate_clients(Direction direction) { if (mp_workspace->size() <= 1) @@ -2340,6 +2383,35 @@ Model::rotate_clients(Direction direction) sync_focus(); apply_layout(mp_workspace); + apply_stack(mp_workspace); +} + +void +Model::shuffle_main(winsys::Direction direction) +{ + if (mp_workspace->size() <= 1) + return; + + mp_workspace->shuffle_main(direction); + focus_client(mp_workspace->active()); + sync_focus(); + + apply_layout(mp_workspace); + apply_stack(mp_workspace); +} + +void +Model::shuffle_stack(winsys::Direction direction) +{ + if (mp_workspace->size() <= 1) + return; + + mp_workspace->shuffle_stack(direction); + focus_client(mp_workspace->active()); + sync_focus(); + + apply_layout(mp_workspace); + apply_stack(mp_workspace); } diff --git a/src/core/model.hh b/src/core/model.hh @@ -140,7 +140,10 @@ private: void cycle_focus(winsys::Direction); void drag_focus(winsys::Direction); + void reverse_clients(); void rotate_clients(winsys::Direction); + void shuffle_main(winsys::Direction); + void shuffle_stack(winsys::Direction); void move_focus_to_next_workspace(winsys::Direction); void move_client_to_next_workspace(winsys::Direction, Client_ptr); diff --git a/src/core/workspace.cc b/src/core/workspace.cc @@ -306,12 +306,33 @@ Workspace::drag(winsys::Direction direction) } void +Workspace::reverse() +{ + m_clients.reverse(); + mp_active = m_clients.active_element().value_or(nullptr); +} + +void Workspace::rotate(winsys::Direction direction) { m_clients.rotate(direction); mp_active = m_clients.active_element().value_or(nullptr); } +void +Workspace::shuffle_main(winsys::Direction direction) +{ + m_clients.rotate_range(direction, 0, m_layout_handler.main_count()); + mp_active = m_clients.active_element().value_or(nullptr); +} + +void +Workspace::shuffle_stack(winsys::Direction direction) +{ + m_clients.rotate_range(direction, m_layout_handler.main_count(), m_clients.size()); + mp_active = m_clients.active_element().value_or(nullptr); +} + void Workspace::activate_client(Client_ptr client) diff --git a/src/core/workspace.hh b/src/core/workspace.hh @@ -167,7 +167,10 @@ public: void cycle(winsys::Direction); void drag(winsys::Direction); + void reverse(); void rotate(winsys::Direction); + void shuffle_main(winsys::Direction); + void shuffle_stack(winsys::Direction); void activate_client(Client_ptr);