]> git.sur5r.net Git - i3/i3/commitdiff
Get the _NET_STARTUP_ID in manage_window, get the corresponding workspace
authorMichael Stapelberg <michael@stapelberg.de>
Mon, 10 Oct 2011 11:48:43 +0000 (12:48 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 10 Oct 2011 14:54:17 +0000 (15:54 +0100)
include/atoms.xmacro
include/startup.h
src/manage.c
src/startup.c

index 309a3325f8bd3dcc972f0ab21770a32871e7380e..f08a90d5585abbbf60292b4dcea27d99c1362ba5 100644 (file)
@@ -15,6 +15,7 @@ xmacro(_NET_CLIENT_LIST_STACKING)
 xmacro(_NET_CURRENT_DESKTOP)
 xmacro(_NET_ACTIVE_WINDOW)
 xmacro(_NET_WORKAREA)
+xmacro(_NET_STARTUP_ID)
 xmacro(WM_PROTOCOLS)
 xmacro(WM_DELETE_WINDOW)
 xmacro(UTF8_STRING)
index 9e131019a226d05177e81670a63bc2404fca5c36..555a11914a054603343311aa0352edb0e04f8249 100644 (file)
@@ -32,4 +32,15 @@ void start_application(const char *command);
  */
 void startup_monitor_event(SnMonitorEvent *event, void *userdata);
 
+/**
+ * Checks if the given window belongs to a startup notification by checking if
+ * the _NET_STARTUP_ID property is set on the window (or on its leader, if it’s
+ * unset).
+ *
+ * If so, returns the workspace on which the startup was initiated.
+ * Returns NULL otherwise.
+ *
+ */
+char *startup_workspace_for_window(i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply);
+
 #endif
index 35055d17ea04e7787efe40dde42e6cb6fdf3e751..22c2814fa4fcdcfb10f697e388b82a9640988d4b 100644 (file)
@@ -84,7 +84,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     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;
+                              role_cookie, startup_id_cookie;
 
 
     geomc = xcb_get_geometry(conn, d);
@@ -147,6 +147,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     title_cookie = GET_PROPERTY(XCB_ATOM_WM_NAME, 128);
     class_cookie = GET_PROPERTY(XCB_ATOM_WM_CLASS, 128);
     role_cookie = GET_PROPERTY(A_WM_WINDOW_ROLE, 128);
+    startup_id_cookie = GET_PROPERTY(A__NET_STARTUP_ID, 512);
     /* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
 
     DLOG("reparenting!\n");
@@ -175,6 +176,11 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     window_update_strut_partial(cwindow, xcb_get_property_reply(conn, strut_cookie, NULL));
     window_update_role(cwindow, xcb_get_property_reply(conn, role_cookie, NULL), true);
 
+    xcb_get_property_reply_t *startup_id_reply;
+    startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL);
+    char *startup_ws = startup_workspace_for_window(cwindow, startup_id_reply);
+    DLOG("startup workspace = %s\n", startup_ws);
+
     /* check if the window needs WM_TAKE_FOCUS */
     cwindow->needs_take_focus = window_supports_protocol(cwindow->id, A_WM_TAKE_FOCUS);
 
@@ -233,6 +239,15 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
                 else nc = tree_open_con(nc->parent, cwindow);
             }
         /* TODO: handle assignments with type == A_TO_OUTPUT */
+        } else if (startup_ws) {
+            /* If it’s not assigned, but was started on a specific workspace,
+             * we want to open it there */
+            DLOG("Using workspace on which this application was started (%s)\n", startup_ws);
+            nc = con_descend_tiling_focused(workspace_get(startup_ws, NULL));
+            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 {
             /* If not, insert it at the currently focused position */
             if (focused->type == CT_CON && con_accepts_window(focused)) {
index 5fc875a3a3737bb6bf66e8d7fe96b6cdb5babc0b..30932e33dcad89398073c961e6decd5672fdbb4c 100644 (file)
@@ -115,3 +115,51 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
             break;
     }
 }
+
+/*
+ * Checks if the given window belongs to a startup notification by checking if
+ * the _NET_STARTUP_ID property is set on the window (or on its leader, if it’s
+ * unset).
+ *
+ * If so, returns the workspace on which the startup was initiated.
+ * Returns NULL otherwise.
+ *
+ */
+char *startup_workspace_for_window(i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply) {
+    /* The _NET_STARTUP_ID is only needed during this function, so we get it
+     * here and don’t save it in the 'cwindow'. */
+    if (startup_id_reply == NULL || xcb_get_property_value_length(startup_id_reply) == 0) {
+        DLOG("No _NET_STARTUP_ID set on this window\n");
+        /* TODO: check the leader, if any */
+        FREE(startup_id_reply);
+        return NULL;
+    }
+
+    char *startup_id;
+    if (asprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
+                 (char*)xcb_get_property_value(startup_id_reply)) == -1) {
+        perror("asprintf()");
+        DLOG("Could not get _NET_STARTUP_ID\n");
+        free(startup_id_reply);
+        return NULL;
+    }
+
+    struct Startup_Sequence *current, *sequence = NULL;
+    TAILQ_FOREACH(current, &startup_sequences, sequences) {
+        if (strcmp(current->id, startup_id) != 0)
+            continue;
+
+        sequence = current;
+        break;
+    }
+
+    free(startup_id);
+    free(startup_id_reply);
+
+    if (!sequence) {
+        DLOG("WARNING: This sequence (ID %s) was not found\n", startup_id);
+        return NULL;
+    }
+
+    return sequence->workspace;
+}