X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fmanage.c;h=06f4e664338f736dceca5034a1486c64cea13951;hb=6e5e2fe5ee7ea92c93207b8f5ff5f8b674d7a72e;hp=b80c94e0ce930757b06904730138f300ddac3cb4;hpb=e7e9e8e49d3df01c3f534a17e810242b9621058c;p=i3%2Fi3 diff --git a/src/manage.c b/src/manage.c index b80c94e0..06f4e664 100644 --- a/src/manage.c +++ b/src/manage.c @@ -3,7 +3,7 @@ * * i3 - an improved dynamic tiling window manager * - * © 2009 Michael Stapelberg and contributors + * © 2009-2010 Michael Stapelberg and contributors * * See file LICENSE for license information. * @@ -63,6 +63,28 @@ void manage_existing_windows(xcb_connection_t *conn, xcb_property_handlers_t *pr free(cookies); } +/* + * Restores the geometry of each window by reparenting it to the root window + * at the position of its frame. + * + * This is to be called *only* before exiting/restarting i3 because of evil + * side-effects which are to be expected when continuing to run i3. + * + */ +void restore_geometry(xcb_connection_t *conn) { + Workspace *ws; + Client *client; + DLOG("Restoring geometry\n"); + + TAILQ_FOREACH(ws, workspaces, workspaces) + SLIST_FOREACH(client, &(ws->focus_stack), focus_clients) + xcb_reparent_window(conn, client->child, root, + client->rect.x, client->rect.y); + + /* Make sure our changes reach the X server, we restart/exit now */ + xcb_flush(conn); +} + /* * Do some sanity checks and then reparent the window. * @@ -160,7 +182,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, LOG("Managing window 0x%08x\n", child); DLOG("x = %d, y = %d, width = %d, height = %d\n", x, y, width, height); - new = calloc(sizeof(Client), 1); + new = scalloc(sizeof(Client)); new->force_reconfigure = true; /* Update the data structures */ @@ -250,12 +272,20 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, for (int i = 0; i < xcb_get_property_value_length(preply); i++) if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DOCK]) { DLOG("Window is a dock.\n"); + Output *t_out = get_output_containing(x, y); + if (t_out == NULL) + t_out = c_ws->output; + if (t_out != c_ws->output) { + DLOG("Dock client requested to be on output %s by geometry (%d, %d)\n", + t_out->name, x, y); + new->workspace = t_out->current_workspace; + } new->dock = true; new->borderless = true; new->titlebar_position = TITLEBAR_OFF; new->force_reconfigure = true; new->container = NULL; - SLIST_INSERT_HEAD(&(c_ws->screen->dock_clients), new, dock_clients); + SLIST_INSERT_HEAD(&(t_out->dock_clients), new, dock_clients); /* If it’s a dock we can’t make it float, so we break */ new->floating = FLOATING_AUTO_OFF; break; @@ -318,6 +348,29 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, preply = xcb_get_property_reply(conn, leader_cookie, NULL); handle_clientleader_change(NULL, conn, 0, new->child, atoms[WM_CLIENT_LEADER], preply); + /* if WM_CLIENT_LEADER is set, we put the new window on the + * same window as its leader. This might be overwritten by + * assignments afterwards. */ + if (new->leader != XCB_NONE) { + DLOG("client->leader is set (to 0x%08x)\n", new->leader); + Client *parent = table_get(&by_child, new->leader); + if (parent != NULL && parent->container != NULL) { + Workspace *t_ws = parent->workspace; + new->container = t_ws->table[parent->container->col][parent->container->row]; + new->workspace = t_ws; + old_focused = new->container->currently_focused; + map_frame = workspace_is_visible(t_ws); + new->urgent = true; + /* This is a little tricky: we cannot use + * workspace_update_urgent_flag() because the + * new window was not yet inserted into the + * focus stack on t_ws. */ + t_ws->urgent = true; + } else { + DLOG("parent is not usable\n"); + } + } + struct Assignment *assign; TAILQ_FOREACH(assign, &assignments, assignments) { if (get_matching_client(conn, assign->windowclass_title, new) == NULL) @@ -334,14 +387,14 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, LOG("Assignment \"%s\" matches, so putting it on workspace %d\n", assign->windowclass_title, assign->workspace); - if (c_ws->screen->current_workspace->num == (assign->workspace-1)) { + if (c_ws->output->current_workspace->num == (assign->workspace-1)) { DLOG("We are already there, no need to do anything\n"); break; } DLOG("Changing container/workspace and unmapping the client\n"); Workspace *t_ws = workspace_get(assign->workspace-1); - workspace_initialize(t_ws, c_ws->screen, false); + workspace_initialize(t_ws, c_ws->output, false); new->container = t_ws->table[t_ws->current_col][t_ws->current_row]; new->workspace = t_ws; @@ -355,9 +408,15 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, if (new->workspace->fullscreen_client != NULL) { DLOG("Setting below fullscreen window\n"); - /* If we are in fullscreen, we should lower the window to not be annoying */ - uint32_t values[] = { XCB_STACK_MODE_BELOW }; - xcb_configure_window(conn, new->frame, XCB_CONFIG_WINDOW_STACK_MODE, values); + /* If we are in fullscreen, we should place the window below + * the fullscreen window to not be annoying */ + uint32_t values[] = { + new->workspace->fullscreen_client->frame, + XCB_STACK_MODE_BELOW + }; + xcb_configure_window(conn, new->frame, + XCB_CONFIG_WINDOW_SIBLING | + XCB_CONFIG_WINDOW_STACK_MODE, values); } /* Insert into the currently active container, if it’s not a dock window */