]> git.sur5r.net Git - i3/i3/blobdiff - src/commands.c
Don't refocus a workspace cleaned up by `workspace_show` during rename
[i3/i3] / src / commands.c
index 98e10c1d0815704468c5439ad35cdff27b79b966..0c5b8bcb2a2c47e121bdcfbf0a76d535efaa05b6 100644 (file)
@@ -2000,6 +2000,7 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
 
     /* By re-attaching, the sort order will be correct afterwards. */
     Con *previously_focused = focused;
+    Con *previously_focused_content = focused->type == CT_WORKSPACE ? focused->parent : NULL;
     Con *parent = workspace->parent;
     con_detach(workspace);
     con_attach(workspace, parent, false);
@@ -2020,15 +2021,28 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
         }
         workspace_move_to_output(workspace, target_output);
 
-        if (previously_focused)
+        bool can_restore_focus = previously_focused != NULL;
+        /* NB: If previously_focused is a workspace we can't
+         * work directly with it since it might have been cleaned up by
+         * workspace_show() already, depending on the
+         * focus order/number of other workspaces on the output.
+         * Instead, we loop through the available workspaces and only focus
+         * previously_focused if we still find it. */
+        if (previously_focused_content) {
+            Con *workspace = NULL;
+            GREP_FIRST(workspace, previously_focused_content, child == previously_focused);
+            can_restore_focus &= (workspace != NULL);
+        }
+
+        if (can_restore_focus) {
+            /* Restore the previous focus since con_attach messes with the focus. */
             workspace_show(con_get_workspace(previously_focused));
+            con_activate(previously_focused);
+        }
 
         break;
     }
 
-    /* Restore the previous focus since con_attach messes with the focus. */
-    con_activate(previously_focused);
-
     cmd_output->needs_tree_render = true;
     ysuccess(true);