]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Correctly hide/show workspaces when enabling new outputs, correctly handle...
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 5 Mar 2010 14:22:12 +0000 (15:22 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 5 Mar 2010 14:22:12 +0000 (15:22 +0100)
include/workspace.h
src/handlers.c
src/randr.c
src/workspace.c

index f22ca8e4be61ce0a11795a258ffab08be0aed8dc..1d2809831dd7801e4d170e2b9fe72d93d2369467 100644 (file)
@@ -53,7 +53,7 @@ void workspace_show(xcb_connection_t *conn, int workspace);
  * screen 1 and you just plugged in screen 1).
  *
  */
-void workspace_assign_to(Workspace *ws, Output *screen);
+void workspace_assign_to(Workspace *ws, Output *screen, bool hide_it);
 
 /**
  * Initializes the given workspace if it is not already initialized. The given
index 66deceff5af7e2b98d7ee25ff4a791721dfe72f8..da5697c1c314882338b7166d1d9298f2c6864a43 100644 (file)
@@ -179,6 +179,24 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) {
         current_row = c_ws->current_row;
         current_col = c_ws->current_col;
         DLOG("We're now on output %p\n", output);
+
+        /* While usually this function is only called when the user switches
+         * to a different output using his mouse (and thus the output is
+         * empty), it may be that the following race condition occurs:
+         * 1) the user actives a new output (say VGA1).
+         * 2) the cursor is sent to the first pixel of the new VGA1, thus
+         *    generating an enter_notify for the screen (the enter_notify
+         *    is not yet received by i3).
+         * 3) i3 requeries screen configuration and maps a workspace onto the
+         *    new output.
+         * 4) the enter_notify event arrives and c_ws is set to the new
+         *    workspace but the existing windows on the new workspace are not
+         *    focused.
+         *
+         * Therefore, we re-set the focus here to be sure it’s correct. */
+        Client *first_client = SLIST_FIRST(&(c_ws->focus_stack));
+        if (first_client != NULL)
+                set_focus(global_conn, first_client, true);
 }
 
 /*
index ac41e34f801a9f75ff82bc0ef8248126843f025e..2d890efc14b6807b6ab5106ff790474266e5eb0d 100644 (file)
@@ -162,6 +162,12 @@ static void initialize_output(xcb_connection_t *conn, Output *output,
         workspace->output = output;
         output->current_workspace = workspace;
 
+        /* Copy rect for the workspace */
+        memcpy(&(workspace->rect), &(output->rect), sizeof(Rect));
+
+        /* Map clients on the workspace, if any */
+        workspace_map_clients(conn, workspace);
+
         /* Create a xoutput for each output */
         Rect bar_rect = {output->rect.x,
                          output->rect.y + output->rect.height - (font->height + 6),
@@ -437,7 +443,7 @@ void randr_query_screens(xcb_connection_t *conn) {
                                 if (ws->output != output)
                                         continue;
 
-                                workspace_assign_to(ws, first);
+                                workspace_assign_to(ws, first, true);
                                 if (!needs_init)
                                         continue;
                                 initialize_output(conn, first, ws);
index ea1134b667552acb45740d0b78f2ad45f7a63817..ef963a76f95cf2206ed7a62ffb8ceea7dee4853e 100644 (file)
@@ -204,7 +204,7 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
  * output 1 and you just plugged in output 1).
  *
  */
-void workspace_assign_to(Workspace *ws, Output *output) {
+void workspace_assign_to(Workspace *ws, Output *output, bool hide_it) {
         Client *client;
         bool empty = true;
         bool visible = workspace_is_visible(ws);
@@ -229,7 +229,7 @@ void workspace_assign_to(Workspace *ws, Output *output) {
         render_workspace(global_conn, output, ws);
 
         /* …unless we want to see them at the moment, we should hide that workspace */
-        if (visible)
+        if (visible && !hide_it)
                 return;
 
         workspace_unmap_clients(global_conn, ws);
@@ -269,7 +269,7 @@ void workspace_initialize(Workspace *ws, Output *output, bool recheck) {
         if (old_output != NULL && ws->output == old_output)
                 return;
 
-        workspace_assign_to(ws, ws->output);
+        workspace_assign_to(ws, ws->output, false);
 }
 
 /*