]> git.sur5r.net Git - i3/i3/blobdiff - src/manage.c
Update copyright notices and get rid of ranges
[i3/i3] / src / manage.c
index 3afde994325d385c9ddc720a87ba24b604dde076..ee56c0b39b28fa7ae78559a1d7409a204916cd32 100644 (file)
@@ -4,7 +4,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * manage.c: Initially managing new windows (or existing ones on restart).
  *
@@ -57,19 +57,19 @@ void restore_geometry(void) {
 
     Con *con;
     TAILQ_FOREACH(con, &all_cons, all_cons)
-        if (con->window) {
-            DLOG("Re-adding X11 border of %d px\n", con->border_width);
-            con->window_rect.width += (2 * con->border_width);
-            con->window_rect.height += (2 * con->border_width);
-            xcb_set_window_rect(conn, con->window->id, con->window_rect);
-            DLOG("placing window %08x at %d %d\n", con->window->id, con->rect.x, con->rect.y);
-            xcb_reparent_window(conn, con->window->id, root,
-                                con->rect.x, con->rect.y);
-        }
+    if (con->window) {
+        DLOG("Re-adding X11 border of %d px\n", con->border_width);
+        con->window_rect.width += (2 * con->border_width);
+        con->window_rect.height += (2 * con->border_width);
+        xcb_set_window_rect(conn, con->window->id, con->window_rect);
+        DLOG("placing window %08x at %d %d\n", con->window->id, con->rect.x, con->rect.y);
+        xcb_reparent_window(conn, con->window->id, root,
+                            con->rect.x, con->rect.y);
+    }
 
     /* Strictly speaking, this line doesn’t really belong here, but since we
      * are syncing, let’s un-register as a window manager first */
-    xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT });
+    xcb_change_window_attributes(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT});
 
     /* Make sure our changes reach the X server, we restart/exit now */
     xcb_aux_sync(conn);
@@ -81,17 +81,16 @@ void restore_geometry(void) {
  */
 void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cookie,
                    bool needs_to_be_mapped) {
-    xcb_drawable_t d = { window };
+    xcb_drawable_t d = {window};
     xcb_get_geometry_cookie_t geomc;
     xcb_get_geometry_reply_t *geom;
     xcb_get_window_attributes_reply_t *attr = NULL;
 
     xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
-                              utf8_title_cookie, title_cookie,
-                              class_cookie, leader_cookie, transient_cookie,
-                              role_cookie, startup_id_cookie, wm_hints_cookie,
-                              wm_normal_hints_cookie, motif_wm_hints_cookie;
-
+        utf8_title_cookie, title_cookie,
+        class_cookie, leader_cookie, transient_cookie,
+        role_cookie, startup_id_cookie, wm_hints_cookie,
+        wm_normal_hints_cookie, motif_wm_hints_cookie;
 
     geomc = xcb_get_geometry(conn, d);
 
@@ -254,23 +253,20 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     /* See if any container swallows this new window */
     nc = con_for_window(search_at, cwindow, &match);
     if (nc == NULL) {
-        /* If not, check if it is assigned to a specific workspace / output */
-        if ((assignment = assignment_for(cwindow, A_TO_WORKSPACE | A_TO_OUTPUT))) {
+        /* If not, check if it is assigned to a specific workspace */
+        if ((assignment = assignment_for(cwindow, A_TO_WORKSPACE))) {
             DLOG("Assignment matches (%p)\n", match);
-            if (assignment->type == A_TO_WORKSPACE) {
-                Con *assigned_ws = workspace_get(assignment->dest.workspace, NULL);
-                nc = con_descend_tiling_focused(assigned_ws);
-                DLOG("focused on ws %s: %p / %s\n", assigned_ws->name, nc, nc->name);
-                if (nc->type == CT_WORKSPACE)
-                    nc = tree_open_con(nc, cwindow);
-                else
-                    nc = tree_open_con(nc->parent, cwindow);
-
-                /* set the urgency hint on the window if the workspace is not visible */
-                if (!workspace_is_visible(assigned_ws))
-                    urgency_hint = true;
-            }
-        /* TODO: handle assignments with type == A_TO_OUTPUT */
+            Con *assigned_ws = workspace_get(assignment->dest.workspace, NULL);
+            nc = con_descend_tiling_focused(assigned_ws);
+            DLOG("focused on ws %s: %p / %s\n", assigned_ws->name, nc, nc->name);
+            if (nc->type == CT_WORKSPACE)
+                nc = tree_open_con(nc, cwindow);
+            else
+                nc = tree_open_con(nc->parent, cwindow);
+
+            /* set the urgency hint on the window if the workspace is not visible */
+            if (!workspace_is_visible(assigned_ws))
+                urgency_hint = true;
         } else if (startup_ws) {
             /* If it’s not assigned, but was started on a specific workspace,
              * we want to open it there */
@@ -279,14 +275,16 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
             DLOG("focused on ws %s: %p / %s\n", startup_ws, nc, nc->name);
             if (nc->type == CT_WORKSPACE)
                 nc = tree_open_con(nc, cwindow);
-            else nc = tree_open_con(nc->parent, cwindow);
+            else
+                nc = tree_open_con(nc->parent, cwindow);
         } else {
             /* If not, insert it at the currently focused position */
             if (focused->type == CT_CON && con_accepts_window(focused)) {
                 LOG("using current container, focused = %p, focused->name = %s\n",
-                                focused, focused->name);
+                    focused, focused->name);
                 nc = focused;
-            } else nc = tree_open_con(NULL, cwindow);
+            } else
+                nc = tree_open_con(NULL, cwindow);
         }
     } else {
         /* M_BELOW inserts the new window as a child of the one which was
@@ -328,8 +326,11 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         fs = con_get_fullscreen_con(croot, CF_GLOBAL);
 
     if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_FULLSCREEN)) {
+        /* If this window is already fullscreen (after restarting!), skip
+         * toggling fullscreen, that would drop it out of fullscreen mode. */
+        if (fs != nc)
+            con_toggle_fullscreen(nc, CF_OUTPUT);
         fs = NULL;
-        con_toggle_fullscreen(nc, CF_OUTPUT);
     }
 
     bool set_focus = false;
@@ -346,9 +347,12 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
             if (workspace_is_visible(ws) && current_output == target_output) {
                 if (!match || !match->restart_mode) {
                     set_focus = true;
-                } else DLOG("not focusing, matched with restart_mode == true\n");
-            } else DLOG("workspace not visible, not focusing\n");
-        } else DLOG("dock, not focusing\n");
+                } else
+                    DLOG("not focusing, matched with restart_mode == true\n");
+            } else
+                DLOG("workspace not visible, not focusing\n");
+        } else
+            DLOG("dock, not focusing\n");
     } else {
         DLOG("fs = %p, ws = %p, not focusing\n", fs, ws);
         /* Insert the new container in focus stack *after* the currently
@@ -407,6 +411,11 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
                 Con *next_transient = con_by_window_id(transient_win->transient_for);
                 if (next_transient == NULL)
                     break;
+                /* Some clients (e.g. x11-ssh-askpass) actually set
+                 * WM_TRANSIENT_FOR to their own window id, so break instead of
+                 * looping endlessly. */
+                if (transient_win == next_transient->window)
+                    break;
                 transient_win = next_transient->window;
             }
         }
@@ -421,12 +430,8 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
      * window to be useful (smaller windows are usually overlays/toolbars/…
      * which are not managed by the wm anyways). We store the original geometry
      * here because it’s used for dock clients. */
-    nc->geometry = (Rect){ geom->x, geom->y, geom->width, geom->height };
-
-    if (want_floating) {
-        DLOG("geometry = %d x %d\n", nc->geometry.width, nc->geometry.height);
-        floating_enable(nc, true);
-    }
+    if (nc->geometry.width == 0)
+        nc->geometry = (Rect){geom->x, geom->y, geom->width, geom->height};
 
     if (motif_border_style != BS_NORMAL) {
         DLOG("MOTIF_WM_HINTS specifies decorations (border_style = %d)\n", motif_border_style);
@@ -437,6 +442,20 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         }
     }
 
+    if (want_floating) {
+        DLOG("geometry = %d x %d\n", nc->geometry.width, nc->geometry.height);
+        /* automatically set the border to the default value if a motif border
+         * was not specified */
+        bool automatic_border = (motif_border_style == BS_NORMAL);
+
+        floating_enable(nc, automatic_border);
+    }
+
+    /* explicitly set the border width to the default */
+    if (nc->current_border_width == -1) {
+        nc->current_border_width = (want_floating ? config.default_floating_border_width : config.default_border_width);
+    }
+
     /* to avoid getting an UnmapNotify event due to reparenting, we temporarily
      * declare no interest in any state change event of this window */
     values[0] = XCB_NONE;
@@ -492,9 +511,11 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
 
     /* Defer setting focus after the 'new' event has been sent to ensure the
      * proper window event sequence. */
-    if (set_focus) {
-        DLOG("Now setting focus.\n");
-        con_focus(nc);
+    if (set_focus && !nc->window->doesnt_accept_focus && nc->mapped) {
+        if (assignment_for(cwindow, A_NO_FOCUS) == NULL) {
+            DLOG("Now setting focus.\n");
+            con_focus(nc);
+        }
     }
 
     tree_render();