]> git.sur5r.net Git - i3/i3/blobdiff - src/window.c
Merge branch 'master' into next
[i3/i3] / src / window.c
index cd96890cb8baf972b62ab30424be15f66efb8671..b886c380880e865dd913340840420ab2e1cd0cbc 100644 (file)
@@ -1,8 +1,12 @@
+#undef I3__FILE__
+#define I3__FILE__ "window.c"
 /*
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2010 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ *
+ * window.c: Updates window attributes (X11 hints/properties).
  *
  */
 #include "all.h"
  * given window.
  *
  */
-void window_update_class(i3Window *win, xcb_get_property_reply_t *prop) {
+void window_update_class(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) {
     if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
-        DLOG("empty property, not updating\n");
+        DLOG("WM_CLASS not set.\n");
+        FREE(prop);
         return;
     }
 
@@ -32,6 +37,15 @@ void window_update_class(i3Window *win, xcb_get_property_reply_t *prop) {
     else win->class_class = NULL;
     LOG("WM_CLASS changed to %s (instance), %s (class)\n",
         win->class_instance, win->class_class);
+
+    if (before_mgmt) {
+        free(prop);
+        return;
+    }
+
+    run_assignments(win);
+
+    free(prop);
 }
 
 /*
@@ -39,37 +53,29 @@ void window_update_class(i3Window *win, xcb_get_property_reply_t *prop) {
  * window. Further updates using window_update_name_legacy will be ignored.
  *
  */
-void window_update_name(i3Window *win, xcb_get_property_reply_t *prop) {
+void window_update_name(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) {
     if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
         DLOG("_NET_WM_NAME not specified, not changing\n");
+        FREE(prop);
         return;
     }
 
-    /* Save the old pointer to make the update atomic */
-    char *new_name;
-    if (asprintf(&new_name, "%.*s", xcb_get_property_value_length(prop),
-                 (char*)xcb_get_property_value(prop)) == -1) {
-        perror("asprintf()");
-        DLOG("Could not get window name\n");
-        return;
-    }
-    /* Convert it to UCS-2 here for not having to convert it later every time we want to pass it to X */
-    int len;
-    char *ucs2_name = convert_utf8_to_ucs2(new_name, &len);
-    if (ucs2_name == NULL) {
-        LOG("Could not convert _NET_WM_NAME to UCS-2, ignoring new hint\n");
-        FREE(new_name);
-        return;
-    }
-    FREE(win->name_x);
-    FREE(win->name_json);
-    win->name_json = new_name;
-    win->name_x = ucs2_name;
-    win->name_len = len;
+    i3string_free(win->name);
+    win->name = i3string_from_utf8_with_length(xcb_get_property_value(prop),
+                                               xcb_get_property_value_length(prop));
     win->name_x_changed = true;
-    LOG("_NET_WM_NAME changed to \"%s\"\n", win->name_json);
+    LOG("_NET_WM_NAME changed to \"%s\"\n", i3string_as_utf8(win->name));
 
     win->uses_net_wm_name = true;
+
+    if (before_mgmt) {
+        free(prop);
+        return;
+    }
+
+    run_assignments(win);
+
+    free(prop);
 }
 
 /*
@@ -79,33 +85,37 @@ void window_update_name(i3Window *win, xcb_get_property_reply_t *prop) {
  * window_update_name()).
  *
  */
-void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop) {
+void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) {
     if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
-        DLOG("prop == NULL\n");
+        DLOG("WM_NAME not set (_NET_WM_NAME is what you want anyways).\n");
+        FREE(prop);
         return;
     }
 
     /* ignore update when the window is known to already have a UTF-8 name */
-    if (win->uses_net_wm_name)
-        return;
-
-    char *new_name;
-    if (asprintf(&new_name, "%.*s", xcb_get_property_value_length(prop),
-                 (char*)xcb_get_property_value(prop)) == -1) {
-        perror("asprintf()");
-        DLOG("Could not get legacy window name\n");
+    if (win->uses_net_wm_name) {
+        free(prop);
         return;
     }
 
+    i3string_free(win->name);
+    win->name = i3string_from_utf8_with_length(xcb_get_property_value(prop),
+                                               xcb_get_property_value_length(prop));
+
+    LOG("WM_NAME changed to \"%s\"\n", i3string_as_utf8(win->name));
     LOG("Using legacy window title. Note that in order to get Unicode window "
         "titles in i3, the application has to set _NET_WM_NAME (UTF-8)\n");
 
-    FREE(win->name_x);
-    FREE(win->name_json);
-    win->name_x = new_name;
-    win->name_json = sstrdup(new_name);
-    win->name_len = strlen(new_name);
     win->name_x_changed = true;
+
+    if (before_mgmt) {
+        free(prop);
+        return;
+    }
+
+    run_assignments(win);
+
+    free(prop);
 }
 
 /*
@@ -114,17 +124,22 @@ void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop) {
  */
 void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop) {
     if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
-        DLOG("prop == NULL\n");
+        DLOG("CLIENT_LEADER not set.\n");
+        FREE(prop);
         return;
     }
 
     xcb_window_t *leader = xcb_get_property_value(prop);
-    if (leader == NULL)
+    if (leader == NULL) {
+        free(prop);
         return;
+    }
 
     DLOG("Client leader changed to %08x\n", *leader);
 
     win->leader = *leader;
+
+    free(prop);
 }
 
 /*
@@ -133,17 +148,22 @@ void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop) {
  */
 void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop) {
     if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
-        DLOG("prop == NULL\n");
+        DLOG("TRANSIENT_FOR not set.\n");
+        FREE(prop);
         return;
     }
 
     xcb_window_t transient_for;
-    if (!xcb_icccm_get_wm_transient_for_from_reply(&transient_for, prop))
+    if (!xcb_icccm_get_wm_transient_for_from_reply(&transient_for, prop)) {
+        free(prop);
         return;
+    }
 
     DLOG("Transient for changed to %08x\n", transient_for);
 
     win->transient_for = transient_for;
+
+    free(prop);
 }
 
 /*
@@ -152,16 +172,79 @@ void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop)
  */
 void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop) {
     if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
-        DLOG("prop == NULL\n");
+        DLOG("_NET_WM_STRUT_PARTIAL not set.\n");
+        FREE(prop);
         return;
     }
 
     uint32_t *strut;
-    if (!(strut = xcb_get_property_value(prop)))
+    if (!(strut = xcb_get_property_value(prop))) {
+        free(prop);
         return;
+    }
 
     DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n",
          strut[0], strut[1], strut[2], strut[3]);
 
     win->reserved = (struct reservedpx){ strut[0], strut[1], strut[2], strut[3] };
+
+    free(prop);
+}
+
+/*
+ * Updates the WM_WINDOW_ROLE
+ *
+ */
+void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) {
+    if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
+        DLOG("WM_WINDOW_ROLE not set.\n");
+        FREE(prop);
+        return;
+    }
+
+    char *new_role;
+    if (asprintf(&new_role, "%.*s", xcb_get_property_value_length(prop),
+                 (char*)xcb_get_property_value(prop)) == -1) {
+        perror("asprintf()");
+        DLOG("Could not get WM_WINDOW_ROLE\n");
+        free(prop);
+        return;
+    }
+    FREE(win->role);
+    win->role = new_role;
+    LOG("WM_WINDOW_ROLE changed to \"%s\"\n", win->role);
+
+    if (before_mgmt) {
+        free(prop);
+        return;
+    }
+
+    run_assignments(win);
+
+    free(prop);
+}
+
+/*
+ * Updates the WM_HINTS (we only care about the input focus handling part).
+ *
+ */
+void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop) {
+    if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
+        DLOG("WM_HINTS not set.\n");
+        FREE(prop);
+        return;
+    }
+
+    xcb_icccm_wm_hints_t hints;
+
+    if (!xcb_icccm_get_wm_hints_from_reply(&hints, prop)) {
+        DLOG("Could not get WM_HINTS\n");
+        free(prop);
+        return;
+    }
+
+    win->doesnt_accept_focus = !hints.input;
+    LOG("WM_HINTS.input changed to \"%d\"\n", hints.input);
+
+    free(prop);
 }