Bugfix: Keep focus on the current workspace when moving containers, add testcase
This commit is contained in:
parent
49add4f3e4
commit
099df7f438
|
@ -121,4 +121,12 @@ void con_move_to_workspace(Con *con, Con *workspace);
|
||||||
*/
|
*/
|
||||||
int con_orientation(Con *con);
|
int con_orientation(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the container which will be focused next when the given container
|
||||||
|
* is not available anymore. Called in tree_close and con_move_to_workspace
|
||||||
|
* to properly restore focus.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Con *con_next_focused(Con *con);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
45
src/con.c
45
src/con.c
|
@ -360,21 +360,28 @@ void con_toggle_fullscreen(Con *con) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void con_move_to_workspace(Con *con, Con *workspace) {
|
void con_move_to_workspace(Con *con, Con *workspace) {
|
||||||
/* 1: get the focused container of this workspace by going down as far as
|
/* 1: save the container which is going to be focused after the current
|
||||||
|
* container is moved away */
|
||||||
|
Con *focus_next = con_next_focused(con);
|
||||||
|
|
||||||
|
/* 2: get the focused container of this workspace by going down as far as
|
||||||
* possible */
|
* possible */
|
||||||
Con *next = workspace;
|
Con *next = workspace;
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&(next->focus_head)))
|
while (!TAILQ_EMPTY(&(next->focus_head)))
|
||||||
next = TAILQ_FIRST(&(next->focus_head));
|
next = TAILQ_FIRST(&(next->focus_head));
|
||||||
|
|
||||||
/* 2: we go up one level, but only when next is a normal container */
|
/* 3: we go up one level, but only when next is a normal container */
|
||||||
if (next->type != CT_WORKSPACE)
|
if (next->type != CT_WORKSPACE)
|
||||||
next = next->parent;
|
next = next->parent;
|
||||||
|
|
||||||
DLOG("Re-attaching container to %p / %s\n", next, next->name);
|
DLOG("Re-attaching container to %p / %s\n", next, next->name);
|
||||||
/* 3: re-attach the con to the parent of this focused container */
|
/* 4: re-attach the con to the parent of this focused container */
|
||||||
con_detach(con);
|
con_detach(con);
|
||||||
con_attach(con, next);
|
con_attach(con, next);
|
||||||
|
|
||||||
|
/* 5: keep focus on the current workspace */
|
||||||
|
con_focus(focus_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -390,3 +397,35 @@ int con_orientation(Con *con) {
|
||||||
|
|
||||||
return con->orientation;
|
return con->orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the container which will be focused next when the given container
|
||||||
|
* is not available anymore. Called in tree_close and con_move_to_workspace
|
||||||
|
* to properly restore focus.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Con *con_next_focused(Con *con) {
|
||||||
|
Con *next;
|
||||||
|
/* floating containers are attached to a workspace, so we focus either the
|
||||||
|
* next floating container (if any) or the workspace itself. */
|
||||||
|
if (con->type == CT_FLOATING_CON) {
|
||||||
|
next = TAILQ_NEXT(con, floating_windows);
|
||||||
|
if (next == TAILQ_END(&(parent->floating_head)))
|
||||||
|
next = con_get_workspace(con);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to focus the next container on the same level as this one */
|
||||||
|
next = TAILQ_NEXT(con, focused);
|
||||||
|
|
||||||
|
/* if none, go up to its parent and go down the focus stack as far as
|
||||||
|
* possible, excluding the current container */
|
||||||
|
if (next == TAILQ_END(&(parent->nodes_head))) {
|
||||||
|
next = con->parent;
|
||||||
|
while (!TAILQ_EMPTY(&(next->focus_head)) &&
|
||||||
|
TAILQ_FIRST(&(next->focus_head)) != con)
|
||||||
|
next = TAILQ_FIRST(&(next->focus_head));
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
15
src/tree.c
15
src/tree.c
|
@ -138,20 +138,7 @@ void tree_close(Con *con, bool kill_window) {
|
||||||
fix_floating_parent(croot, con);
|
fix_floating_parent(croot, con);
|
||||||
|
|
||||||
/* Get the container which is next focused */
|
/* Get the container which is next focused */
|
||||||
Con *next;
|
Con *next = con_next_focused(con);
|
||||||
if (con->type == CT_FLOATING_CON) {
|
|
||||||
next = TAILQ_NEXT(con, floating_windows);
|
|
||||||
if (next == TAILQ_END(&(parent->floating_head)))
|
|
||||||
next = con_get_workspace(con);
|
|
||||||
} else {
|
|
||||||
next = TAILQ_NEXT(con, focused);
|
|
||||||
if (next == TAILQ_END(&(parent->nodes_head))) {
|
|
||||||
next = parent;
|
|
||||||
while (!TAILQ_EMPTY(&(next->focus_head)) &&
|
|
||||||
TAILQ_FIRST(&(next->focus_head)) != con)
|
|
||||||
next = TAILQ_FIRST(&(next->focus_head));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG("closing %p, kill_window = %d\n", con, kill_window);
|
DLOG("closing %p, kill_window = %d\n", con, kill_window);
|
||||||
Con *child;
|
Con *child;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!perl
|
||||||
|
# vim:ts=4:sw=4:expandtab
|
||||||
|
#
|
||||||
|
# Checks if the 'move workspace' command works correctly
|
||||||
|
#
|
||||||
|
use i3test tests => 7;
|
||||||
|
use Time::HiRes qw(sleep);
|
||||||
|
|
||||||
|
my $i3 = i3("/tmp/nestedcons");
|
||||||
|
|
||||||
|
# We move the pointer out of our way to avoid a bug where the focus will
|
||||||
|
# be set to the window under the cursor
|
||||||
|
my $x = X11::XCB::Connection->new;
|
||||||
|
$x->root->warp_pointer(0, 0);
|
||||||
|
|
||||||
|
my $tmp = get_unused_workspace();
|
||||||
|
my $tmp2 = get_unused_workspace();
|
||||||
|
$i3->command("workspace $tmp")->recv;
|
||||||
|
|
||||||
|
ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
|
||||||
|
|
||||||
|
$i3->command('open')->recv;
|
||||||
|
my ($nodes, $focus) = get_ws_content($tmp);
|
||||||
|
my $first = $focus->[0];
|
||||||
|
$i3->command('open')->recv;
|
||||||
|
($nodes, $focus) = get_ws_content($tmp);
|
||||||
|
my $second = $focus->[0];
|
||||||
|
ok(@{get_ws_content($tmp)} == 2, 'two containers on first ws');
|
||||||
|
|
||||||
|
$i3->command("workspace $tmp2")->recv;
|
||||||
|
ok(@{get_ws_content($tmp2)} == 0, 'no containers on second ws yet');
|
||||||
|
|
||||||
|
$i3->command("workspace $tmp")->recv;
|
||||||
|
|
||||||
|
$i3->command("move workspace $tmp2")->recv;
|
||||||
|
ok(@{get_ws_content($tmp)} == 1, 'one container on first ws anymore');
|
||||||
|
ok(@{get_ws_content($tmp2)} == 1, 'one container on second ws');
|
||||||
|
($nodes, $focus) = get_ws_content($tmp2);
|
||||||
|
|
||||||
|
is($focus->[0], $second, 'same container on different ws');
|
||||||
|
|
||||||
|
($nodes, $focus) = get_ws_content($tmp);
|
||||||
|
is($nodes->[0]->{focused}, 1, 'first container focused on first ws');
|
||||||
|
|
||||||
|
diag( "Testing i3, Perl $], $^X" );
|
Loading…
Reference in New Issue