commit 7caedde35e017a6e0c626d36022e91ff671aac86
parent 09f7c748fe3e97f55351dad9313bb99a13573af2
Author: deurzen <m.deurzen@tum.de>
Date: Thu, 2 Sep 2021 08:24:17 +0200
adds proper leader/group handling
Diffstat:
4 files changed, 103 insertions(+), 17 deletions(-)
diff --git a/src/core/client.cc b/src/core/client.cc
@@ -31,9 +31,9 @@ Client::Client(
active_decoration(winsys::Decoration::FREE_DECORATION),
size_hints(std::nullopt),
warp_pos(std::nullopt),
+ leader(std::nullopt),
parent(nullptr),
children({}),
- leader(nullptr),
producer(nullptr),
consumers({}),
focused(false),
diff --git a/src/core/client.hh b/src/core/client.hh
@@ -96,9 +96,9 @@ typedef struct Client final
winsys::Decoration active_decoration;
std::optional<winsys::SizeHints> size_hints;
std::optional<winsys::Pos> warp_pos;
+ std::optional<winsys::Window> leader;
Client_ptr parent;
std::vector<Client_ptr> children;
- Client_ptr leader;
Client_ptr producer;
std::vector<Client_ptr> consumers;
bool focused;
diff --git a/src/core/model.cc b/src/core/model.cc
@@ -58,6 +58,7 @@ Model::Model(Connection& conn)
m_client_map({}),
m_pid_map({}),
m_fullscreen_map({}),
+ m_leader_map({}),
m_sticky_clients({}),
m_unmanaged_windows({}),
m_ignored_producers({}),
@@ -1775,12 +1776,12 @@ Model::manage(const Window window, const bool ignore, const bool may_map)
}
if (leader) {
- Client_ptr leader_client = get_client(*leader);
+ if (m_leader_map.count(*leader) > 0)
+ m_leader_map[*leader].push_back(client);
+ else
+ m_leader_map[*leader] = { client };
- if (leader_client) {
- client->leader = leader_client;
- floating = true;
- }
+ client->leader = leader;
}
Rules rules = retrieve_rules(client);
@@ -1818,6 +1819,35 @@ Model::manage(const Window window, const bool ignore, const bool may_map)
} else if (rules.to_workspace && *rules.to_workspace < m_workspaces.size())
client->workspace = *rules.to_workspace;
+ if (leader) {
+ std::vector<Client_ptr>& members = m_leader_map.at(*leader);
+ std::optional<Index> group_attachment = std::nullopt;
+
+ if (std::any_of(
+ members.begin(),
+ members.end(),
+ [&group_attachment](Client_ptr member) mutable -> bool {
+ if (member->attaching) {
+ group_attachment = member->workspace;
+ return true;
+ }
+
+ return false;
+ }) && group_attachment
+ ) {
+ client->workspace = *group_attachment;
+ }
+ }
+
+ if (parent) {
+ Client_ptr parent_client = get_client(*parent);
+
+ if (parent_client && parent_client->attaching) {
+ client->workspace = parent_client->workspace;
+ client->attaching = true;
+ }
+ }
+
if (pid)
m_pid_map[*pid] = client;
@@ -1907,6 +1937,14 @@ Model::unmanage(Client_ptr client)
m_fullscreen_map.erase(client);
+ if (client->leader) {
+ std::vector<Client_ptr>& members = m_leader_map.at(*client->leader);
+ Util::erase_remove(members, client);
+
+ if (members.empty())
+ m_leader_map.erase(*client->leader);
+ }
+
Util::erase_remove(m_sticky_clients, client);
Util::erase_remove(m_order, client->frame);
@@ -2371,22 +2409,42 @@ Model::move_focus_to_workspace(Index index)
void
Model::move_client_to_workspace(Index index, Client_ptr client)
{
- if (index >= m_workspaces.size() || index == mp_workspace->index() || client->sticky)
+ if (index >= m_workspaces.size()
+ || index == client->workspace
+ || client->sticky
+ ) {
return;
+ }
+
+ Workspace_ptr from = get_workspace(client->workspace);
+ Workspace_ptr to = get_workspace(index);
client->workspace = index;
- Workspace_ptr workspace = get_workspace(index);
- unmap_client(client);
+ if (from == mp_workspace)
+ unmap_client(client);
- workspace->add_client(client);
- apply_layout(workspace);
- apply_stack(workspace);
+ to->add_client(client);
+ apply_layout(to);
+ apply_stack(to);
- mp_workspace->remove_client(client);
- apply_layout(mp_workspace);
+ from->remove_client(client);
+ apply_layout(from);
+ apply_stack(from);
sync_focus();
+
+ if (client->leader) {
+ std::vector<Client_ptr>& members = m_leader_map.at(*client->leader);
+
+ std::for_each(
+ members.begin(),
+ members.end(),
+ [this,index](Client_ptr member) {
+ move_client_to_workspace(index, member);
+ }
+ );
+ }
}
@@ -2684,6 +2742,9 @@ Model::set_sticky_client(Toggle toggle, Client_ptr client)
if (client->sticky)
return;
+ if (client->iconified)
+ set_iconify_client(Toggle::Off, client);
+
std::for_each(
m_workspaces.begin(),
m_workspaces.end(),
@@ -2706,6 +2767,18 @@ Model::set_sticky_client(Toggle toggle, Client_ptr client)
apply_layout(workspace);
render_decoration(client);
+ if (client->leader) {
+ std::vector<Client_ptr>& members = m_leader_map.at(*client->leader);
+
+ std::for_each(
+ members.begin(),
+ members.end(),
+ [this,toggle](Client_ptr member) {
+ set_sticky_client(toggle, member);
+ }
+ );
+ }
+
return;
}
case Toggle::Off:
@@ -2717,7 +2790,7 @@ Model::set_sticky_client(Toggle toggle, Client_ptr client)
m_workspaces.begin(),
m_workspaces.end(),
[=,this](Workspace_ptr workspace) {
- if (workspace->index() != mp_workspace->index()) {
+ if (workspace != mp_workspace) {
workspace->remove_client(client);
workspace->remove_icon(client);
workspace->remove_disowned(client);
@@ -2738,6 +2811,18 @@ Model::set_sticky_client(Toggle toggle, Client_ptr client)
apply_layout(mp_workspace);
render_decoration(client);
+ if (client->leader) {
+ std::vector<Client_ptr>& members = m_leader_map.at(*client->leader);
+
+ std::for_each(
+ members.begin(),
+ members.end(),
+ [this,toggle](Client_ptr member) {
+ set_sticky_client(toggle, member);
+ }
+ );
+ }
+
return;
}
case Toggle::Reverse:
@@ -2882,7 +2967,7 @@ Model::set_iconify_client(Toggle toggle, Client_ptr client)
switch (toggle) {
case Toggle::On:
{
- if (client->iconified)
+ if (client->iconified || client->sticky)
return;
Workspace_ptr workspace = get_workspace(client->workspace);
diff --git a/src/core/model.hh b/src/core/model.hh
@@ -233,6 +233,7 @@ private:
std::unordered_map<winsys::Window, Client_ptr> m_client_map;
std::unordered_map<winsys::Pid, Client_ptr> m_pid_map;
std::unordered_map<Client_ptr, winsys::Region> m_fullscreen_map;
+ std::unordered_map<winsys::Window, std::vector<Client_ptr>> m_leader_map;
std::vector<Client_ptr> m_sticky_clients;
std::vector<winsys::Window> m_unmanaged_windows;