]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Warp pointer to the correct window when using the 'focus' command
authorMichael Stapelberg <michael@stapelberg.de>
Mon, 3 Oct 2011 20:54:36 +0000 (21:54 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 3 Oct 2011 20:54:36 +0000 (21:54 +0100)
Comment in the code makes the fix clear, I think.

Steps to reproduce the issue:
1) On the right monitor, open two terminals (h-split workspace)
2) 'i3 mark foo' on the right terminal
3) Focus the left terminal
4) Switch to the left monitor
5) i3 '[con_mark="foo"] focus'
6) the left window will contain the pointer (and is focused for a short period
   of time, or even permanently due to race conditions)

src/cmdparse.y

index da962cf46b6cbed45188a4a63ee34d6aa4e4c1b1..ecc4bc020070af1b9bbcf2bdfdeb06fd0af6a7d2 100644 (file)
@@ -440,6 +440,24 @@ focus:
         int count = 0;
         TAILQ_FOREACH(current, &owindows, owindows) {
             Con *ws = con_get_workspace(current->con);
+
+            /* If the container is not on the current workspace,
+             * workspace_show() will switch to a different workspace and (if
+             * enabled) trigger a mouse pointer warp to the currently focused
+             * container (!) on the target workspace.
+             *
+             * Therefore, before calling workspace_show(), we make sure that
+             * 'current' will be focused on the workspace. However, we cannot
+             * just con_focus(current) because then the pointer will not be
+             * warped at all (the code thinks we are already there).
+             *
+             * So we focus 'current' to make it the currently focused window of
+             * the target workspace, then revert focus. */
+            Con *currently_focused = focused;
+            con_focus(current->con);
+            con_focus(currently_focused);
+
+            /* Now switch to the workspace, then focus */
             workspace_show(ws);
             LOG("focusing %p / %s\n", current->con, current->con->name);
             con_focus(current->con);