]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
Merge branch 'backport' into work
[chaz/openbox] / openbox / client.c
index 281883b14b8a6ed288cd2b172a915364be31d030..4b0aea2f4e3d375c81333bc589956c048e7a68a4 100644 (file)
@@ -165,8 +165,8 @@ void client_set_list(void)
     } else
         windows = NULL;
 
-    OBT_PROP_SETA32(RootWindow(obt_display, ob_screen),
-                    NET_CLIENT_LIST, WINDOW, (gulong*)windows, size);
+    OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST, WINDOW,
+                    (gulong*)windows, size);
 
     if (windows)
         g_free(windows);
@@ -200,6 +200,9 @@ void client_manage_all(void)
         }
     }
 
+    /* manage windows in reverse order from how they were originally mapped.
+       this is an attempt to manage children windows before their parents, so
+       that when the parent is mapped, it can find the child */
     for (i = 0; i < nchild; ++i) {
         if (children[i] == None)
             continue;
@@ -274,7 +277,7 @@ void client_manage(Window window)
     /* create the ObClient struct, and populate it from the hints on the
        window */
     self = g_new0(ObClient, 1);
-    self->obwin.type = Window_Client;
+    self->obwin.type = OB_WINDOW_CLASS_CLIENT;
     self->window = window;
 
     /* non-zero defaults */
@@ -288,6 +291,11 @@ void client_manage(Window window)
     ob_debug("Window type: %d\n", self->type);
     ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
 
+    /* now we have all of the window's information so we can set this up.
+       do this before creating the frame, so it can tell that we are still
+       mapping and doesn't go applying things right away */
+    client_setup_decor_and_functions(self, FALSE);
+
     /* specify that if we exit, the window should not be destroyed and
        should be reparented back to root automatically */
     XChangeSaveSet(obt_display, window, SetModeInsert);
@@ -308,11 +316,8 @@ void client_manage(Window window)
     /* the session should get the last say though */
     client_restore_session_state(self);
 
-    /* now we have all of the window's information so we can set this up */
-    client_setup_decor_and_functions(self, FALSE);
-
     /* tell startup notification that this app started */
-    launch_time = sn_app_started(self->startup_id, self->class);
+    launch_time = sn_app_started(self->startup_id, self->class, self->name);
 
     /* do this after we have a frame.. it uses the frame to help determine the
        WM_STATE to apply. */
@@ -597,7 +602,7 @@ void client_manage(Window window)
 
     /* add to client list/map */
     client_list = g_list_append(client_list, self);
-    g_hash_table_insert(window_map, &self->window, self);
+    window_add(&self->window, CLIENT_AS_WINDOW(self));
 
     /* this has to happen after we're in the client_list */
     if (STRUT_EXISTS(self->strut))
@@ -705,7 +710,7 @@ void client_unmanage(ObClient *self)
 
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
-    g_hash_table_remove(window_map, &self->window);
+    window_remove(self->window);
 
     /* once the client is out of the list, update the struts to remove its
        influence */
@@ -783,8 +788,8 @@ void client_unmanage(ObClient *self)
 
     /* these should not be left on the window ever.  other window managers
        don't necessarily use them and it will mess them up (like compiz) */
-    PROP_ERASE(self->window, net_wm_visible_name);
-    PROP_ERASE(self->window, net_wm_visible_icon_name);
+    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_NAME);
+    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_ICON_NAME);
 
     /* update the list hints */
     client_set_list();
@@ -797,6 +802,7 @@ void client_unmanage(ObClient *self)
         g_free(self->icons[j].data);
     if (self->nicons > 0)
         g_free(self->icons);
+    g_free(self->startup_id);
     g_free(self->wm_command);
     g_free(self->title);
     g_free(self->icon_title);
@@ -1285,20 +1291,20 @@ void client_update_transient_for(ObClient *self)
 
     if (XGetTransientForHint(obt_display, self->window, &t)) {
         if (t != self->window) { /* cant be transient to itself! */
-            target = g_hash_table_lookup(window_map, &t);
+            ObWindow *tw = window_find(t);
             /* if this happens then we need to check for it*/
-            g_assert(target != self);
-            if (target && !WINDOW_IS_CLIENT(target)) {
-                /* this can happen when a dialog is a child of
-                   a dockapp, for example */
-                target = NULL;
+            g_assert(tw != CLIENT_AS_WINDOW(self));
+            if (tw && WINDOW_IS_CLIENT(tw)) {
+                /* watch out for windows with a parent that is something
+                   different, like a dockapp for example */
+                target = WINDOW_AS_CLIENT(tw);
             }
         }
 
         /* Setting the transient_for to Root is actually illegal, however
            applications from time have done this to specify transient for
            their group */
-        if (!target && self->group && t == RootWindow(obt_display, ob_screen))
+        if (!target && self->group && t == obt_root(ob_screen))
             trangroup = TRUE;
     } else if (self->group && self->transient)
         trangroup = TRUE;
@@ -1528,7 +1534,7 @@ void client_update_protocols(ObClient *self)
                 /* if this protocol is requested, then the window will be
                    notified whenever we want it to receive focus */
                 self->focus_notify = TRUE;
-            else if (proto[i] == prop_atoms.net_wm_ping)
+            else if (proto[i] == OBT_PROP_ATOM(NET_WM_PING))
                 /* if this protocol is requested, then the window will allow
                    pings to determine if it is still alive */
                 self->ping = TRUE;
@@ -1832,16 +1838,16 @@ static void client_change_allowed_actions(ObClient *self)
 
     OBT_PROP_SETA32(self->window, NET_WM_ALLOWED_ACTIONS, ATOM, actions, num);
 
-    /* make sure the window isn't breaking any rules now */
+    /* make sure the window isn't breaking any rules now
+
+       don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
+       it can't be iconified with its parent
+    */
 
     if (!(self->functions & OB_CLIENT_FUNC_SHADE) && self->shaded) {
         if (self->frame) client_shade(self, FALSE);
         else self->shaded = FALSE;
     }
-    if (!(self->functions & OB_CLIENT_FUNC_ICONIFY) && self->iconic) {
-        if (self->frame) client_iconify(self, FALSE, TRUE, FALSE);
-        else self->iconic = FALSE;
-    }
     if (!(self->functions & OB_CLIENT_FUNC_FULLSCREEN) && self->fullscreen) {
         if (self->frame) client_fullscreen(self, FALSE);
         else self->fullscreen = FALSE;
@@ -2069,11 +2075,17 @@ void client_update_strut(ObClient *self)
     }
 }
 
+/* Avoid storing icons above this size if possible */
+#define AVOID_ABOVE 64
+
 void client_update_icons(ObClient *self)
 {
     guint num;
     guint32 *data;
     guint w, h, i, j;
+    guint num_seen;  /* number of icons present */
+    guint num_small_seen;  /* number of icons small enough present */
+    guint smallest, smallest_area;
 
     for (i = 0; i < self->nicons; ++i)
         g_free(self->icons[i].data);
@@ -2084,25 +2096,54 @@ void client_update_icons(ObClient *self)
     if (OBT_PROP_GETA32(self->window, NET_WM_ICON, CARDINAL, &data, &num)) {
         /* figure out how many valid icons are in here */
         i = 0;
-        while (num - i > 2) {
-            w = data[i++];
-            h = data[i++];
-            i += w * h;
-            if (i > num || w*h == 0) break;
-            ++self->nicons;
-        }
+        num_seen = num_small_seen = 0;
+        smallest = smallest_area = 0;
+        if (num > 2)
+            while (i < num) {
+                w = data[i++];
+                h = data[i++];
+                i += w * h;
+                /* watch for it being too small for the specified size, or for
+                   zero sized icons. */
+                if (i > num || w == 0 || h == 0) break;
+
+                if (!smallest_area || w*h < smallest_area) {
+                    smallest = num_seen;
+                    smallest_area = w*h;
+                }
+                ++num_seen;
+                if (w <= AVOID_ABOVE && h <= AVOID_ABOVE)
+                    ++num_small_seen;
+            }
+        if (num_small_seen > 0)
+            self->nicons = num_small_seen;
+        else if (num_seen)
+            self->nicons = 1;
 
         self->icons = g_new(ObClientIcon, self->nicons);
 
         /* store the icons */
         i = 0;
-        for (j = 0; j < self->nicons; ++j) {
+        for (j = 0; j < self->nicons;) {
             guint x, y, t;
 
             w = self->icons[j].width = data[i++];
             h = self->icons[j].height = data[i++];
 
-            if (w*h == 0) continue;
+            /* if there are some icons smaller than the threshold, we're
+               skipping all the ones above */
+            if (num_small_seen > 0) {
+                if (w > AVOID_ABOVE || h > AVOID_ABOVE) {
+                    i += w*h;
+                    continue;
+                }
+            }
+            /* if there were no icons smaller than the threshold, then we are
+               only taking the smallest available one we saw */
+            else if (j != smallest) {
+                i += w*h;
+                continue;
+            }
 
             self->icons[j].data = g_new(RrPixel32, w * h);
             for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) {
@@ -2117,6 +2158,8 @@ void client_update_icons(ObClient *self)
                     (((data[i] >> 0) & 0xff) << RrDefaultBlueOffset);
             }
             g_assert(i <= num);
+
+            ++j;
         }
 
         g_free(data);
@@ -2179,11 +2222,13 @@ void client_update_icon_geometry(ObClient *self)
     RECT_SET(self->icon_geometry, 0, 0, 0, 0);
 
     if (OBT_PROP_GETA32(self->window, NET_WM_ICON_GEOMETRY, CARDINAL,
-                        &data, &num) && num == 4)
+                        &data, &num))
     {
-        /* don't let them set it with an area < 0 */
-        RECT_SET(self->icon_geometry, data[0], data[1],
-                 MAX(data[2],0), MAX(data[3],0));
+        if (num == 4)
+            /* don't let them set it with an area < 0 */
+            RECT_SET(self->icon_geometry, data[0], data[1],
+                     MAX(data[2],0), MAX(data[3],0));
+        g_free(data);
     }
 }
 
@@ -2282,7 +2327,7 @@ static void client_get_session_ids(ObClient *self)
 
         /* see if it has the PID set too (the PID requires that the
            WM_CLIENT_MACHINE be set) */
-        if (PROP_GET32(self->window, net_wm_pid, cardinal, &pid))
+        if (OBT_PROP_GET32(self->window, NET_WM_PID, CARDINAL, &pid))
             self->pid = pid;
     }
 }
@@ -3240,8 +3285,8 @@ void client_close(ObClient *self)
     else
         /* request the client to close with WM_DELETE_WINDOW */
         OBT_PROP_MSG_TO(self->window, self->window, WM_PROTOCOLS,
-                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime, 0, 0,
-                        NoEventMask);
+                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime,
+                        0, 0, 0, NoEventMask);
 }
 
 void client_kill(ObClient *self)
This page took 0.03482 seconds and 4 git commands to generate.