new->layout = layout;
new->last_split_layout = con->last_split_layout;
- /* Save the container that was focused before we move containers
- * around, but only if the container is visible (otherwise focus
- * will be restored properly automatically when switching). */
- Con *old_focused = TAILQ_FIRST(&(con->focus_head));
- if (old_focused == TAILQ_END(&(con->focus_head)))
- old_focused = NULL;
- if (old_focused != NULL &&
- !workspace_is_visible(con_get_workspace(old_focused)))
- old_focused = NULL;
-
/* 3: move the existing cons of this workspace below the new con */
+ Con **focus_order = get_focus_order(con);
+
DLOG("Moving cons\n");
Con *child;
while (!TAILQ_EMPTY(&(con->nodes_head))) {
con_attach(child, new, true);
}
+ set_focus_order(new, focus_order);
+ free(focus_order);
+
/* 4: attach the new split container to the workspace */
DLOG("Attaching new split to ws\n");
con_attach(new, con, false);
- if (old_focused)
- con_activate(old_focused);
-
tree_flatten(croot);
}
con_force_split_parents_redraw(con);
/* 2: copy layout from workspace */
split->layout = ws->layout;
- Con *old_focused = TAILQ_FIRST(&(ws->focus_head));
-
/* 3: move the existing cons of this workspace below the new con */
+ Con **focus_order = get_focus_order(ws);
+
DLOG("Moving cons\n");
while (!TAILQ_EMPTY(&(ws->nodes_head))) {
Con *child = TAILQ_FIRST(&(ws->nodes_head));
con_attach(child, split, true);
}
+ set_focus_order(split, focus_order);
+ free(focus_order);
+
/* 4: switch workspace layout */
ws->layout = (orientation == HORIZ) ? L_SPLITH : L_SPLITV;
DLOG("split->layout = %d, ws->layout = %d\n", split->layout, ws->layout);
/* 6: fix the percentages */
con_fix_percent(ws);
-
- if (old_focused)
- con_activate(old_focused);
}
/*
new->parent = ws;
new->layout = ws->layout;
+ Con **focus_order = get_focus_order(ws);
+
DLOG("Moving children of workspace %p / %s into container %p\n",
ws, ws->name, new);
-
Con *child;
while (!TAILQ_EMPTY(&(ws->nodes_head))) {
child = TAILQ_FIRST(&(ws->nodes_head));
con_attach(child, new, true);
}
+ set_focus_order(new, focus_order);
+ free(focus_order);
+
con_attach(new, ws, true);
return new;
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Verify that the corrent focus stack order is preserved after various
+# operations.
+use i3test;
+
+sub kill_and_confirm_focus {
+ my $focus = shift;
+ my $msg = shift;
+ cmd "kill";
+ sync_with_i3;
+ is($x->input_focus, $focus, $msg);
+}
+
+my @windows;
+
+sub focus_windows {
+ for (my $i = $#windows; $i >= 0; $i--) {
+ cmd '[id=' . $windows[$i]->id . '] focus';
+ }
+}
+
+sub confirm_focus {
+ my $msg = shift;
+ sync_with_i3;
+ is($x->input_focus, $windows[0]->id, $msg . ': window 0 focused');
+ foreach my $i (1 .. $#windows) {
+ kill_and_confirm_focus($windows[$i]->id, "$msg: window $i focused");
+ }
+ cmd 'kill';
+ @windows = ();
+}
+
+#####################################################################
+# Open 5 windows, focus them in a custom order and then change to
+# tabbed layout. The focus order should be preserved.
+#####################################################################
+
+fresh_workspace;
+
+$windows[3] = open_window;
+$windows[1] = open_window;
+$windows[0] = open_window;
+$windows[2] = open_window;
+$windows[4] = open_window;
+focus_windows;
+
+cmd 'layout tabbed';
+confirm_focus('tabbed');
+
+#####################################################################
+# Same as above but with stacked.
+#####################################################################
+
+fresh_workspace;
+
+$windows[3] = open_window;
+$windows[1] = open_window;
+$windows[0] = open_window;
+$windows[2] = open_window;
+$windows[4] = open_window;
+focus_windows;
+
+cmd 'layout stacked';
+confirm_focus('stacked');
+
+#####################################################################
+# Open 4 windows horizontally, move the last one down. The focus
+# order should be preserved.
+#####################################################################
+
+fresh_workspace;
+$windows[3] = open_window;
+$windows[2] = open_window;
+$windows[1] = open_window;
+$windows[0] = open_window;
+
+cmd 'move down';
+confirm_focus('split-h + move');
+
+#####################################################################
+# Same as above but with a vertical split.
+#####################################################################
+
+fresh_workspace;
+$windows[3] = open_window;
+cmd 'split v';
+$windows[2] = open_window;
+$windows[1] = open_window;
+$windows[0] = open_window;
+
+cmd 'move left';
+confirm_focus('split-v + move');
+
+done_testing;