Keep a sticky window focused if it was the focused window on the source workspace.

fixes #1924
This commit is contained in:
Ingo Bürk 2015-09-17 22:52:56 +02:00
parent d4fb17546c
commit 922afe1919
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.
*
*/
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
* sure it gets pushed to the front now. */
output_push_sticky_windows();
output_push_sticky_windows(focused);
cmd_output->needs_tree_render = true;
ysuccess(true);

View File

@ -736,7 +736,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
con->sticky = !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();

View File

@ -52,31 +52,34 @@ Output *get_output_from_string(Output *current_output, const char *output_str) {
* workspace on that output.
*
*/
void output_push_sticky_windows(void) {
void output_push_sticky_windows(Con *to_focus) {
Con *output;
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
TAILQ_FOREACH(output, &(croot->focus_head), focused) {
Con *workspace, *visible_ws = NULL;
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
* sticky window was the last window on that workspace as moving it in
* this case will close the workspace. */
for (workspace = TAILQ_FIRST(&(output_get_content(output)->nodes_head));
workspace != TAILQ_END(&(output_get_content(output)->nodes_head));) {
for (workspace = TAILQ_FIRST(&(output_get_content(output)->focus_head));
workspace != TAILQ_END(&(output_get_content(output)->focus_head));) {
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
* floating windows on this workspace, here too we need to use
* another loop than TAILQ_FOREACH. */
Con *child;
for (child = TAILQ_FIRST(&(current_ws->floating_head));
child != TAILQ_END(&(current_ws->floating_head));) {
for (child = TAILQ_FIRST(&(current_ws->focus_head));
child != TAILQ_END(&(current_ws->focus_head));) {
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))
con_move_to_workspace(current, visible_ws, true, false, true);
if (con_is_sticky(current)) {
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) {
Con *current, *old = NULL;
Con *old_focus = focused;
/* safe-guard against showing i3-internal workspaces like __i3_scratch */
if (con_is_internal(workspace))
@ -478,7 +479,7 @@ static void _workspace_show(Con *workspace) {
ewmh_update_current_desktop();
/* 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
use i3test;
my ($ws, $focused);
my ($ws, $tmp, $focused);
###############################################################################
# 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';
###############################################################################
# 4: Given a sticky floating container and a tiling container on the target
# workspace, when the workspace is switched, then the tiling container is
# focused.
# 4: Given an unfocused 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;
@ -72,13 +72,30 @@ $focused = get_focused($ws);
fresh_workspace;
open_floating_window(wm_class => 'findme');
cmd 'sticky enable';
open_window;
cmd 'workspace ' . $ws;
is(get_focused($ws), $focused, 'the tiling container has focus');
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
# visible workspace.
###############################################################################