]> git.sur5r.net Git - i3/i3/blobdiff - src/manage.c
Merge pull request #2887 from orestisf1993/next
[i3/i3] / src / manage.c
index f86e98f5564d656bdb49b646472c383325fd6aea..f155603d4f9a390e515f90496f4456eb4c039873 100644 (file)
@@ -1,5 +1,3 @@
-#undef I3__FILE__
-#define I3__FILE__ "manage.c"
 /*
  * vim:ts=4:sw=4:expandtab
  *
@@ -10,6 +8,7 @@
  *
  */
 #include "all.h"
+
 #include "yajl_utils.h"
 
 #include <yajl/yajl_gen.h>
@@ -220,7 +219,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         LOG("This window is of type dock\n");
         Output *output = get_output_containing(geom->x, geom->y);
         if (output != NULL) {
-            DLOG("Starting search at output %s\n", output->name);
+            DLOG("Starting search at output %s\n", output_primary_name(output));
             search_at = output->con;
         }
 
@@ -260,9 +259,26 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         Con *wm_desktop_ws = NULL;
 
         /* If not, check if it is assigned to a specific workspace */
-        if ((assignment = assignment_for(cwindow, A_TO_WORKSPACE))) {
+        if ((assignment = assignment_for(cwindow, A_TO_WORKSPACE)) ||
+            (assignment = assignment_for(cwindow, A_TO_WORKSPACE_NUMBER))) {
             DLOG("Assignment matches (%p)\n", match);
-            Con *assigned_ws = workspace_get(assignment->dest.workspace, NULL);
+
+            Con *assigned_ws = NULL;
+            if (assignment->type == A_TO_WORKSPACE_NUMBER) {
+                Con *output = NULL;
+                long parsed_num = ws_name_to_number(assignment->dest.workspace);
+
+                /* This will only work for workspaces that already exist. */
+                TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+                    GREP_FIRST(assigned_ws, output_get_content(output), child->num == parsed_num);
+                }
+            }
+            /* A_TO_WORKSPACE type assignment or fallback from A_TO_WORKSPACE_NUMBER
+             * when the target workspace number does not exist yet. */
+            if (!assigned_ws) {
+                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)
@@ -430,7 +446,10 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_STICKY))
         nc->sticky = true;
 
-    if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL) {
+    /* We ignore the hint for an internal workspace because windows in the
+     * scratchpad also have this value, but upon restarting i3 we don't want
+     * them to become sticky windows. */
+    if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL && (ws == NULL || !con_is_internal(ws))) {
         DLOG("This window has _NET_WM_DESKTOP = 0xFFFFFFFF. Will float it and make it sticky.\n");
         nc->sticky = true;
         want_floating = true;
@@ -489,6 +508,12 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         geom->height = wm_size_hints.height;
     }
 
+    if (wm_size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
+        DLOG("Window specifies minimum size %d x %d\n", wm_size_hints.min_width, wm_size_hints.min_height);
+        nc->window->min_width = wm_size_hints.min_width;
+        nc->window->min_height = wm_size_hints.min_height;
+    }
+
     /* Store the requested geometry. The width/height gets raised to at least
      * 75x50 when entering floating mode, which is the minimum size for a
      * window to be useful (smaller windows are usually overlays/toolbars/…
@@ -577,7 +602,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         /* The first window on a workspace should always be focused. We have to
          * compare with == 1 because the container has already been inserted at
          * this point. */
-        if (con_num_children(ws) == 1) {
+        if (con_num_windows(ws) == 1) {
             DLOG("This is the first window on this workspace, ignoring no_focus.\n");
         } else {
             DLOG("no_focus was set for con = %p, not setting focus.\n", nc);
@@ -602,9 +627,20 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         xcb_discard_reply(conn, wm_user_time_cookie.sequence);
     }
 
+    if (set_focus) {
+        /* Even if the client doesn't want focus, we still need to focus the
+         * container to not break focus workflows. Our handling towards X will
+         * take care of not setting the input focus. However, one exception to
+         * this are clients using the globally active input model which we
+         * don't want to focus at all. */
+        if (nc->window->doesnt_accept_focus && !nc->window->needs_take_focus) {
+            set_focus = false;
+        }
+    }
+
     /* Defer setting focus after the 'new' event has been sent to ensure the
      * proper window event sequence. */
-    if (set_focus && !nc->window->doesnt_accept_focus && nc->mapped) {
+    if (set_focus && nc->mapped) {
         DLOG("Now setting focus.\n");
         con_focus(nc);
     }