Merge pull request #1931 from Airblader/bug-1924

Improvements for sticky windows
This commit is contained in:
Michael Stapelberg 2015-09-24 22:34:29 +02:00
commit c82e6a87dc
6 changed files with 40 additions and 19 deletions

View File

@ -27,4 +27,4 @@ Output *get_output_from_string(Output *current_output, const char *output_str);
* workspace on that output. * workspace on that output.
* *
*/ */
void output_push_sticky_windows(void); void output_push_sticky_windows(Con *to_focus);

View File

@ -1598,7 +1598,7 @@ void cmd_sticky(I3_CMD, char *action) {
/* A window we made sticky might not be on a visible workspace right now, so we need to make /* A window we made sticky might not be on a visible workspace right now, so we need to make
* sure it gets pushed to the front now. */ * sure it gets pushed to the front now. */
output_push_sticky_windows(); output_push_sticky_windows(focused);
cmd_output->needs_tree_render = true; cmd_output->needs_tree_render = true;
ysuccess(true); ysuccess(true);

View File

@ -736,7 +736,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
con->sticky = !con->sticky; con->sticky = !con->sticky;
DLOG("New sticky status for con = %p is %i.\n", con, con->sticky); DLOG("New sticky status for con = %p is %i.\n", con, con->sticky);
output_push_sticky_windows(); output_push_sticky_windows(focused);
} }
tree_render(); tree_render();

View File

@ -52,31 +52,34 @@ Output *get_output_from_string(Output *current_output, const char *output_str) {
* workspace on that output. * workspace on that output.
* *
*/ */
void output_push_sticky_windows(void) { void output_push_sticky_windows(Con *to_focus) {
Con *output; Con *output;
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { TAILQ_FOREACH(output, &(croot->focus_head), focused) {
Con *workspace, *visible_ws = NULL; Con *workspace, *visible_ws = NULL;
GREP_FIRST(visible_ws, output_get_content(output), workspace_is_visible(child)); GREP_FIRST(visible_ws, output_get_content(output), workspace_is_visible(child));
/* We use this loop instead of TAILQ_FOREACH to avoid problems if the /* We use this loop instead of TAILQ_FOREACH to avoid problems if the
* sticky window was the last window on that workspace as moving it in * sticky window was the last window on that workspace as moving it in
* this case will close the workspace. */ * this case will close the workspace. */
for (workspace = TAILQ_FIRST(&(output_get_content(output)->nodes_head)); for (workspace = TAILQ_FIRST(&(output_get_content(output)->focus_head));
workspace != TAILQ_END(&(output_get_content(output)->nodes_head));) { workspace != TAILQ_END(&(output_get_content(output)->focus_head));) {
Con *current_ws = workspace; Con *current_ws = workspace;
workspace = TAILQ_NEXT(workspace, nodes); workspace = TAILQ_NEXT(workspace, focused);
/* Since moving the windows actually removes them from the list of /* Since moving the windows actually removes them from the list of
* floating windows on this workspace, here too we need to use * floating windows on this workspace, here too we need to use
* another loop than TAILQ_FOREACH. */ * another loop than TAILQ_FOREACH. */
Con *child; Con *child;
for (child = TAILQ_FIRST(&(current_ws->floating_head)); for (child = TAILQ_FIRST(&(current_ws->focus_head));
child != TAILQ_END(&(current_ws->floating_head));) { child != TAILQ_END(&(current_ws->focus_head));) {
Con *current = child; Con *current = child;
child = TAILQ_NEXT(child, floating_windows); child = TAILQ_NEXT(child, focused);
if (current->type != CT_FLOATING_CON)
continue;
if (con_is_sticky(current)) if (con_is_sticky(current)) {
con_move_to_workspace(current, visible_ws, true, false, true); con_move_to_workspace(current, visible_ws, true, false, current != to_focus->parent);
}
} }
} }
} }

View File

@ -363,6 +363,7 @@ static void workspace_defer_update_urgent_hint_cb(EV_P_ ev_timer *w, int revents
static void _workspace_show(Con *workspace) { static void _workspace_show(Con *workspace) {
Con *current, *old = NULL; Con *current, *old = NULL;
Con *old_focus = focused;
/* safe-guard against showing i3-internal workspaces like __i3_scratch */ /* safe-guard against showing i3-internal workspaces like __i3_scratch */
if (con_is_internal(workspace)) if (con_is_internal(workspace))
@ -478,7 +479,7 @@ static void _workspace_show(Con *workspace) {
ewmh_update_current_desktop(); ewmh_update_current_desktop();
/* Push any sticky windows to the now visible workspace. */ /* Push any sticky windows to the now visible workspace. */
output_push_sticky_windows(); output_push_sticky_windows(old_focus);
} }
/* /*

View File

@ -18,7 +18,7 @@
# Ticket: #1455 # Ticket: #1455
use i3test; use i3test;
my ($ws, $focused); my ($ws, $tmp, $focused);
############################################################################### ###############################################################################
# 1: Given a sticky tiling container, when the workspace is switched, then # 1: Given a sticky tiling container, when the workspace is switched, then
@ -62,9 +62,9 @@ is(@{get_ws($ws)->{floating_nodes}}, 2, 'multiple sticky windows can be used at
cmd '[class="findme"] kill'; cmd '[class="findme"] kill';
############################################################################### ###############################################################################
# 4: Given a sticky floating container and a tiling container on the target # 4: Given an unfocused sticky floating container and a tiling container on the
# workspace, when the workspace is switched, then the tiling container is # target workspace, when the workspace is switched, then the tiling container
# focused. # is focused.
############################################################################### ###############################################################################
$ws = fresh_workspace; $ws = fresh_workspace;
open_window; open_window;
@ -72,13 +72,30 @@ $focused = get_focused($ws);
fresh_workspace; fresh_workspace;
open_floating_window(wm_class => 'findme'); open_floating_window(wm_class => 'findme');
cmd 'sticky enable'; cmd 'sticky enable';
open_window;
cmd 'workspace ' . $ws; cmd 'workspace ' . $ws;
is(get_focused($ws), $focused, 'the tiling container has focus'); is(get_focused($ws), $focused, 'the tiling container has focus');
cmd '[class="findme"] kill'; cmd '[class="findme"] kill';
############################################################################### ###############################################################################
# 5: Given a floating container on a non-visible workspace, when the window # 5: Given a focused sticky floating container and a tiling container on the
# target workspace, when the workspace is switched, then the tiling container
# is focused.
###############################################################################
$ws = fresh_workspace;
open_window;
$tmp = fresh_workspace;
open_floating_window(wm_class => 'findme');
$focused = get_focused($tmp);
cmd 'sticky enable';
cmd 'workspace ' . $ws;
is(get_focused($ws), $focused, 'the sticky container has focus');
cmd '[class="findme"] kill';
###############################################################################
# 6: Given a floating container on a non-visible workspace, when the window
# is made sticky, then the window immediately jumps to the currently # is made sticky, then the window immediately jumps to the currently
# visible workspace. # visible workspace.
############################################################################### ###############################################################################