From: Michael Stapelberg Date: Fri, 5 Mar 2010 14:22:12 +0000 (+0100) Subject: Bugfix: Correctly hide/show workspaces when enabling new outputs, correctly handle... X-Git-Tag: 3.e~6^2~119 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=8b192ac7ed1bab2f0da1099fae24b627f9597bf0;p=i3%2Fi3 Bugfix: Correctly hide/show workspaces when enabling new outputs, correctly handle focus (Thanks Merovius) --- diff --git a/include/workspace.h b/include/workspace.h index f22ca8e4..1d280983 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -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 diff --git a/src/handlers.c b/src/handlers.c index 66deceff..da5697c1 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -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); } /* diff --git a/src/randr.c b/src/randr.c index ac41e34f..2d890efc 100644 --- a/src/randr.c +++ b/src/randr.c @@ -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); diff --git a/src/workspace.c b/src/workspace.c index ea1134b6..ef963a76 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -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); } /*