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 431df4ff50f93e72e06bad8b92156333c803052c
parent 313be2a14f04d877fe366d8ea212fb65aa29bd7d
Author: deurzen <m.deurzen@tum.de>
Date:   Thu,  2 Sep 2021 06:38:11 +0200

implements attach-to-workspace functionality

Diffstat:
Msrc/core/client.cc | 1+
Msrc/core/client.hh | 1+
Msrc/core/model.cc | 79++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/core/model.hh | 5+++++
4 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/src/core/client.cc b/src/core/client.cc @@ -49,6 +49,7 @@ Client::Client( iconified(false), disowned(false), producing(true), + attaching(false), pid(pid), ppid(ppid), last_focused(std::chrono::steady_clock::now()), diff --git a/src/core/client.hh b/src/core/client.hh @@ -114,6 +114,7 @@ typedef struct Client final bool iconified; bool disowned; bool producing; + bool attaching; std::optional<winsys::Pid> pid; std::optional<winsys::Pid> ppid; std::chrono::time_point<std::chrono::steady_clock> last_focused; diff --git a/src/core/model.cc b/src/core/model.cc @@ -4,6 +4,7 @@ #include "model.hh" #include <algorithm> +#include <chrono> #include <cmath> #include <cstdlib> #include <cstring> @@ -12,6 +13,7 @@ #include <iostream> #include <set> #include <sstream> +#include <thread> #include <unordered_set> #include <vector> @@ -48,6 +50,7 @@ Model::Model(Connection& conn) mp_prev_partition(nullptr), mp_prev_context(nullptr), mp_prev_workspace(nullptr), + mp_attachment(std::atomic(nullptr)), m_move_buffer(Buffer::BufferKind::Move), m_resize_buffer(Buffer::BufferKind::Resize), m_stack({}), @@ -465,6 +468,9 @@ Model::Model(Connection& conn) }, // workspace client movers + { { Key::BackSlash, { Main } }, + CALL(attach_next_client()) + }, { { Key::RightBracket, { Main, Shift } }, CALL(move_focus_to_next_workspace(Direction::Forward)) }, @@ -1302,6 +1308,7 @@ Model::focus_client(Client_ptr client) client->focus(); client->urgent = false; + client->attaching = false; mp_focus = client; @@ -1341,6 +1348,24 @@ Model::sync_focus() void +Model::attach_next_client() +{ + static std::atomic<unsigned> count = { 0 }; + static auto attachment_resetter = [&,this]() mutable { + unsigned current = ++count; + + std::this_thread::sleep_for(std::chrono::seconds(30)); + + if (current == count) + mp_attachment.exchange(nullptr); + }; + + mp_attachment.exchange(mp_workspace); + std::thread(attachment_resetter).detach(); +} + + +void Model::toggle_partition() { if (mp_prev_partition) @@ -1692,9 +1717,16 @@ Model::manage(const Window window, const bool ignore, const bool may_map) bool fullscreen = m_conn.window_is_fullscreen(window); bool sticky = m_conn.window_is_sticky(window); - Index workspace = m_conn.get_window_desktop(window).value_or(mp_workspace->index()); - Index context = workspace / m_workspaces.size(); - workspace %= m_workspaces.size(); + Index partition = mp_partition->index(); + Index context = mp_context->index(); + Index workspace = mp_workspace->index(); + + std::optional<Index> desktop = m_conn.get_window_desktop(window); + + if (desktop) { + context = *desktop / m_workspaces.size(); + workspace = *desktop % m_workspaces.size(); + } std::optional<Hints> hints = m_conn.get_icccm_window_hints(window); std::optional<SizeHints> size_hints @@ -1722,21 +1754,13 @@ Model::manage(const Window window, const bool ignore, const bool may_map) name, class_, instance, - mp_partition->index(), + partition, context, workspace, pid, ppid ); - Rules rules = retrieve_rules(client); - - if (rules.to_context && *rules.to_context <= m_contexts.size()) - client->context = *rules.to_context; - - if (rules.to_workspace && *rules.to_workspace <= m_workspaces.size()) - client->workspace = *rules.to_workspace; - if (parent) { Client_ptr parent_client = get_client(*parent); @@ -1754,11 +1778,13 @@ Model::manage(const Window window, const bool ignore, const bool may_map) Client_ptr leader_client = get_client(*leader); if (leader_client) { - client->leader = get_client(*leader); + client->leader = leader_client; floating = true; } } + Rules rules = retrieve_rules(client); + if (center || (rules.do_center && *rules.do_center)) { const Region screen_region = active_screen().placeable_region(); @@ -1771,26 +1797,25 @@ Model::manage(const Window window, const bool ignore, const bool may_map) client->set_free_region(geometry); client->floating = floating; - client->fullscreen = fullscreen; client->urgent = hints ? hints->urgent : false; - client->partition = m_partitions.active_index(); - client->context = m_contexts.active_index(); - client->workspace = m_workspaces.active_index(); client->size_hints = size_hints; if (rules.do_float) client->floating = *rules.do_float; if (rules.do_fullscreen) - client->fullscreen = *rules.do_fullscreen; + fullscreen = *rules.do_fullscreen; - if (rules.to_partition) + if (rules.to_partition && *rules.to_partition < m_partitions.size()) client->partition = *rules.to_partition; - if (rules.to_context) + if (rules.to_context && *rules.to_context < m_contexts.size()) client->context = *rules.to_context; - if (rules.to_workspace) + if (mp_attachment) { + client->workspace = mp_attachment.exchange(nullptr)->index(); + client->attaching = true; + } else if (rules.to_workspace && *rules.to_workspace < m_workspaces.size()) client->workspace = *rules.to_workspace; if (pid) @@ -1808,21 +1833,21 @@ Model::manage(const Window window, const bool ignore, const bool may_map) m_conn.init_window(window, false); m_conn.init_frame(frame, false); m_conn.set_window_border_width(window, 0); - m_conn.set_window_desktop(window, workspace); + m_conn.set_window_desktop(window, client->workspace); m_conn.set_icccm_window_state(window, IcccmWindowState::Normal); - mp_workspace->add_client(client); - if (client->size_hints) client->size_hints->apply(client->free_region.dim); client->free_region.apply_minimum_dim(Client::MIN_CLIENT_DIM); - apply_layout(client->workspace); + get_workspace(client->workspace)->add_client(client); - if (!m_move_buffer.is_occupied() + if (client->workspace == mp_workspace->index() + && !m_move_buffer.is_occupied() && !m_resize_buffer.is_occupied() ) { + apply_layout(mp_workspace); focus_client(client); } @@ -3736,7 +3761,7 @@ Model::handle_focus_request(FocusRequestEvent event) { Client_ptr client = get_client(event.window); - if (!client || event.on_root) + if (!client || client->attaching || event.on_root) return; focus_client(client); diff --git a/src/core/model.hh b/src/core/model.hh @@ -15,6 +15,7 @@ #include "stack.hh" #include "workspace.hh" +#include <atomic> #include <cstddef> #include <unordered_map> #include <vector> @@ -91,6 +92,8 @@ private: void unfocus_client(Client_ptr); void sync_focus(); + void attach_next_client(); + void toggle_partition(); void activate_next_partition(winsys::Direction); void activate_partition(Util::Change<Index>); @@ -219,6 +222,8 @@ private: Context_ptr mp_prev_context; Workspace_ptr mp_prev_workspace; + std::atomic<Workspace_ptr> mp_attachment; + Buffer m_move_buffer; Buffer m_resize_buffer;