From: Michael Stapelberg Date: Tue, 4 Jan 2011 23:16:10 +0000 (+0100) Subject: Re-Implement support for RandR changes X-Git-Tag: tree-pr2~136 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5098e45f234d9fd49af43f82c32fcbc9be9e1a60;p=i3%2Fi3 Re-Implement support for RandR changes --- diff --git a/include/data.h b/include/data.h index 6f4a4738..6174e4e4 100644 --- a/include/data.h +++ b/include/data.h @@ -202,6 +202,7 @@ struct xoutput { /** x, y, width, height */ Rect rect; +#if 0 /** The bar window */ xcb_window_t bar; xcb_gcontext_t bargc; @@ -209,6 +210,7 @@ struct xoutput { /** Contains all clients with _NET_WM_WINDOW_TYPE == * _NET_WM_WINDOW_TYPE_DOCK */ SLIST_HEAD(dock_clients_head, Client) dock_clients; +#endif TAILQ_ENTRY(xoutput) outputs; }; diff --git a/include/handlers.h b/include/handlers.h index 1f2e4b18..2d592e64 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -71,6 +71,7 @@ int handle_map_request(void *prophs, xcb_connection_t *conn, * */ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event); +#endif /** * Gets triggered upon a RandR screen change event, that is when the user @@ -79,7 +80,6 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n */ int handle_screen_change(void *prophs, xcb_connection_t *conn, xcb_generic_event_t *e); -#endif /** * Configure requests are received when the application wants to resize diff --git a/include/randr.h b/include/randr.h index 7a501b8e..779a1316 100644 --- a/include/randr.h +++ b/include/randr.h @@ -31,6 +31,16 @@ void randr_init(int *event_base); */ void disable_randr(xcb_connection_t *conn); +/** + * Initializes a CT_OUTPUT Con (searches existing ones from inplace restart + * before) to use for the given Output. + * + * XXX: for assignments, we probably need to move workspace creation from here + * to after the loop in randr_query_outputs(). + * + */ +void output_init_con(Output *output); + /** * Initializes the specified output, assigning the specified workspace to it. * diff --git a/src/handlers.c b/src/handlers.c index ed59f528..21ca4e3b 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -428,6 +428,7 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n return 1; } +#endif /* * Gets triggered upon a RandR screen change event, that is when the user @@ -436,15 +437,14 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n */ int handle_screen_change(void *prophs, xcb_connection_t *conn, xcb_generic_event_t *e) { - DLOG("RandR screen change\n"); + DLOG("RandR screen change\n"); - randr_query_outputs(conn); + randr_query_outputs(); - ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}"); + ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}"); - return 1; + return 1; } -#endif /* * Our window decorations were unmapped. That means, the window will be killed diff --git a/src/main.c b/src/main.c index e30887c9..ea7f82f2 100644 --- a/src/main.c +++ b/src/main.c @@ -325,6 +325,17 @@ int main(int argc, char *argv[]) { translate_keysyms(); grab_all_keys(conn, false); + bool needs_tree_init = true; + if (layout_path) { + LOG("Trying to restore the layout from %s...", layout_path); + needs_tree_init = !tree_restore(layout_path); + if (delete_layout_path) + unlink(layout_path); + free(layout_path); + } + if (needs_tree_init) + tree_init(); + int randr_base; if (force_xinerama) { xinerama_init(); @@ -332,24 +343,12 @@ int main(int argc, char *argv[]) { DLOG("Checking for XRandR...\n"); randr_init(&randr_base); -#if 0 xcb_event_set_handler(&evenths, randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY, handle_screen_change, NULL); -#endif } - bool needs_tree_init = true; - if (layout_path) { - LOG("Trying to restore the layout from %s...", layout_path); - needs_tree_init = !tree_restore(layout_path); - if (delete_layout_path) - unlink(layout_path); - free(layout_path); - } - if (needs_tree_init) - tree_init(); tree_render(); struct ev_loop *loop = ev_loop_new(0); diff --git a/src/randr.c b/src/randr.c index e0ad4eb2..999181ef 100644 --- a/src/randr.c +++ b/src/randr.c @@ -3,7 +3,7 @@ * * i3 - an improved dynamic tiling window manager * - * © 2009-2010 Michael Stapelberg and contributors + * © 2009-2011 Michael Stapelberg and contributors * * See file LICENSE for license information. * @@ -215,6 +215,74 @@ void disable_randr(xcb_connection_t *conn) { randr_disabled = true; } +/* + * Initializes a CT_OUTPUT Con (searches existing ones from inplace restart + * before) to use for the given Output. + * + * XXX: for assignments, we probably need to move workspace creation from here + * to after the loop in randr_query_outputs(). + * + */ +void output_init_con(Output *output) { + Con *con = NULL, *current; + bool reused = false; + static int c = 1; + + DLOG("init_con for output %s\n", output->name); + + /* Search for a Con with that name directly below the root node. There + * might be one from a restored layout. */ + TAILQ_FOREACH(current, &(croot->nodes_head), nodes) { + if (strcmp(current->name, output->name) != 0) + continue; + + con = current; + reused = true; + DLOG("Using existing con %p / %s\n", con, con->name); + break; + } + + if (con == NULL) { + con = con_new(croot); + FREE(con->name); + con->name = sstrdup(output->name); + con->type = CT_OUTPUT; + } + con->rect = output->rect; + output->con = con; + + char *name; + asprintf(&name, "[i3 con] output %s", con->name); + x_set_name(con, name); + free(name); + + if (reused) { + DLOG("Not adding workspace, this was a reused con\n"); + return; + } + DLOG("Now adding a workspace\n"); + + /* add a workspace to this output */ + Con *ws = con_new(NULL); + ws->type = CT_WORKSPACE; + /* TODO: don't just number workspaces, but get the next assigned one / unused one */ + ws->num = c; + FREE(ws->name); + asprintf(&(ws->name), "%d", c); + c++; + con_attach(ws, con, false); + + asprintf(&name, "[i3 con] workspace %s", ws->name); + x_set_name(ws, name); + free(name); + + ws->fullscreen_mode = CF_OUTPUT; + ws->orientation = HORIZ; + + /* TODO: Set focus in main.c */ + con_focus(ws); +} + /* * This function needs to be called when changing the mode of an output when * it already has some workspaces (or a bar window) assigned. @@ -227,9 +295,12 @@ void disable_randr(xcb_connection_t *conn) { * */ static void output_change_mode(xcb_connection_t *conn, Output *output) { - i3Font *font = load_font(conn, config.font); + //i3Font *font = load_font(conn, config.font); - DLOG("Output mode changed, reconfiguring bar, updating workspaces\n"); + DLOG("Output mode changed, updating rect\n"); + assert(output->con != NULL); + output->con->rect = output->rect; +#if 0 Rect bar_rect = {output->rect.x, output->rect.y + output->rect.height - (font->height + 6), output->rect.x + output->rect.width, @@ -237,7 +308,6 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) { xcb_set_window_rect(conn, output->bar, bar_rect); -#if 0 /* go through all workspaces and set force_reconfigure */ TAILQ_FOREACH(ws, workspaces, workspaces) { if (ws->output != output) @@ -442,31 +512,47 @@ void randr_query_outputs() { if ((first = get_first_output()) == NULL) die("No usable outputs available\n"); - //bool needs_init = (first->current_workspace == NULL); + /* We need to move the workspaces from the disappearing output to the first output */ + /* 1: Get the con to focus next, if the disappearing ws is focused */ + Con *next = NULL; + if (TAILQ_FIRST(&(croot->focus_head)) == output->con) { + DLOG("This output (%p) was focused! Getting next\n", output->con); + next = con_next_focused(output->con); + DLOG("next = %p\n", next); + } -#if 0 - TAILQ_FOREACH(ws, workspaces, workspaces) { - if (ws->output != output) - continue; - - workspace_assign_to(ws, first, true); - if (!needs_init) - continue; - //initialize_output(conn, first, ws); - needs_init = false; + /* 2: iterate through workspaces and re-assign them */ + Con *current; + while (!TAILQ_EMPTY(&(output->con->nodes_head))) { + current = TAILQ_FIRST(&(output->con->nodes_head)); + DLOG("Detaching current = %p / %s\n", current, current->name); + con_detach(current); + DLOG("Re-attaching current = %p / %s\n", current, current->name); + con_attach(current, first->con, false); + DLOG("Done, next\n"); } + DLOG("re-attached all workspaces\n"); - Client *dock; - while (!SLIST_EMPTY(&(output->dock_clients))) { - dock = SLIST_FIRST(&(output->dock_clients)); - SLIST_REMOVE_HEAD(&(output->dock_clients), dock_clients); - SLIST_INSERT_HEAD(&(first->dock_clients), dock, dock_clients); + if (next) { + DLOG("now focusing next = %p\n", next); + con_focus(next); } -#endif - //output->current_workspace = NULL; + DLOG("destroying disappearing con %p\n", output->con); + tree_close(output->con, false, true); + DLOG("Done. Should be fine now\n"); + output->con = NULL; + output->to_be_disabled = false; - } else if (output->changed) { + } + + if (output->active && output->con == NULL) { + DLOG("Need to initialize a Con for output %s\n", output->name); + output_init_con(output); + output->changed = false; + } + + if (output->changed) { output_change_mode(conn, output); output->changed = false; } @@ -504,7 +590,7 @@ void randr_init(int *event_base) { extreply = xcb_get_extension_data(conn, &xcb_randr_id); if (!extreply->present) disable_randr(conn); - else randr_query_outputs(conn); + else randr_query_outputs(); if (event_base != NULL) *event_base = extreply->first_event; diff --git a/src/tree.c b/src/tree.c index 0233a125..dfe5f7be 100644 --- a/src/tree.c +++ b/src/tree.c @@ -40,56 +40,15 @@ bool tree_restore(const char *path) { } /* - * Initializes the tree by creating the root node, adding all RandR outputs - * to the tree (that means randr_init() has to be called before) and - * assigning a workspace to each RandR output. + * Initializes the tree by creating the root node. The CT_OUTPUT Cons below the + * root node are created in randr.c for each Output. * */ void tree_init() { - Output *output; - croot = con_new(NULL); FREE(croot->name); croot->name = "root"; croot->type = CT_ROOT; - - Con *ws; - int c = 1; - /* add the outputs */ - TAILQ_FOREACH(output, &outputs, outputs) { - if (!output->active) - continue; - - Con *oc = con_new(croot); - FREE(oc->name); - oc->name = strdup(output->name); - oc->type = CT_OUTPUT; - oc->rect = output->rect; - output->con = oc; - - char *name; - asprintf(&name, "[i3 con] output %s", oc->name); - x_set_name(oc, name); - free(name); - - /* add a workspace to this output */ - ws = con_new(NULL); - ws->type = CT_WORKSPACE; - ws->num = c; - FREE(ws->name); - asprintf(&(ws->name), "%d", c); - c++; - con_attach(ws, oc, false); - - asprintf(&name, "[i3 con] workspace %s", ws->name); - x_set_name(ws, name); - free(name); - - ws->fullscreen_mode = CF_OUTPUT; - ws->orientation = HORIZ; - } - - con_focus(ws); } /* diff --git a/src/xinerama.c b/src/xinerama.c index 369e8ab7..8bb1b43f 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -3,7 +3,7 @@ * * i3 - an improved dynamic tiling window manager * - * © 2009-2010 Michael Stapelberg and contributors + * © 2009-2011 Michael Stapelberg and contributors * * See file LICENSE for license information. * @@ -70,6 +70,7 @@ static void query_screens(xcb_connection_t *conn) { if (s->rect.x == 0 && s->rect.y == 0) TAILQ_INSERT_HEAD(&outputs, s, outputs); else TAILQ_INSERT_TAIL(&outputs, s, outputs); + output_init_con(s); num_screens++; }