Implement sticky windows

The implementation works like this:
Containers can have a 'sticky-group' attribute. Imagine two different
containers (on two different workspaces) which have the same sticky-group.
Now you open a window in the first container. When you switch to the
other workspace, the window will be re-assigned to the other container.

An obvious problem which is not covered with the code at the moment is
having two containers with the same sticky-group visible at the same time.
This commit is contained in:
Michael Stapelberg
2010-09-01 18:11:01 +02:00
parent 4d12e18571
commit 0925e8b7dc
5 changed files with 174 additions and 1 deletions

View File

@ -92,6 +92,83 @@ bool workspace_is_visible(Workspace *ws) {
}
#endif
/*
* XXX: we need to clean up all this recursive walking code.
*
*/
Con *_get_sticky(Con *con, const char *sticky_group, Con *exclude) {
Con *current;
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
if (current != exclude &&
current->sticky_group != NULL &&
current->window != NULL &&
strcmp(current->sticky_group, sticky_group) == 0)
return current;
Con *recurse = _get_sticky(current, sticky_group, exclude);
if (recurse != NULL)
return recurse;
}
TAILQ_FOREACH(current, &(con->floating_head), floating_windows) {
if (current != exclude &&
current->sticky_group != NULL &&
current->window != NULL &&
strcmp(current->sticky_group, sticky_group) == 0)
return current;
Con *recurse = _get_sticky(current, sticky_group, exclude);
if (recurse != NULL)
return recurse;
}
return NULL;
}
/*
* Reassigns all child windows in sticky containers. Called when the user
* changes workspaces.
*
* XXX: what about sticky containers which contain containers?
*
*/
static void workspace_reassign_sticky(Con *con) {
Con *current;
/* 1: go through all containers */
/* handle all children and floating windows of this node */
TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
if (current->sticky_group == NULL) {
workspace_reassign_sticky(current);
continue;
}
LOG("Ah, this one is sticky: %s / %p\n", current->name, current);
/* 2: find a window which we can re-assign */
Con *output = con_get_output(current);
Con *src = _get_sticky(output, current->sticky_group, current);
if (src == NULL) {
LOG("No window found for this sticky group\n");
workspace_reassign_sticky(current);
continue;
}
x_move_win(src, current);
current->window = src->window;
current->mapped = true;
src->window = NULL;
src->mapped = false;
x_reparent_child(current, src);
LOG("re-assigned window from src %p to dest %p\n", src, current);
}
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
workspace_reassign_sticky(current);
}
/*
* Switches to the given workspace
@ -110,6 +187,8 @@ void workspace_show(const char *num) {
TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes)
current->fullscreen_mode = CF_NONE;
workspace_reassign_sticky(workspace);
LOG("switching to %p\n", workspace);
Con *next = workspace;