Big rework of image.c and the image cache system.
[dana/openbox.git] / openbox / client.c
index 4cba7f1..ccc64c6 100644 (file)
@@ -114,18 +114,9 @@ static gboolean client_can_steal_focus(ObClient *self,
 
 void client_startup(gboolean reconfig)
 {
-    if ((client_default_icon = RrImageCacheFind(ob_rr_icons,
-                                                ob_rr_theme->def_win_icon,
-                                                ob_rr_theme->def_win_icon_w,
-                                                ob_rr_theme->def_win_icon_h)))
-        RrImageRef(client_default_icon);
-    else {
-        client_default_icon = RrImageNew(ob_rr_icons);
-        RrImageAddPicture(client_default_icon,
-                          ob_rr_theme->def_win_icon,
-                          ob_rr_theme->def_win_icon_w,
-                          ob_rr_theme->def_win_icon_h);
-    }
+    client_default_icon = RrImageNewFromData(
+        ob_rr_icons, ob_rr_theme->def_win_icon,
+        ob_rr_theme->def_win_icon_w, ob_rr_theme->def_win_icon_h);
 
     if (reconfig) return;
 
@@ -245,11 +236,6 @@ void client_manage(Window window, ObPrompt *prompt)
        that needs to be freed with g_free(). */
     settings = client_get_settings_state(self);
 
-    /* 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, unless we are managing
        an internal ObPrompt window  */
@@ -288,12 +274,12 @@ void client_manage(Window window, ObPrompt *prompt)
     if (ob_state() != OB_STATE_STARTING &&
         (!self->session || self->session->focused) &&
         /* this means focus=true for window is same as config_focus_new=true */
-        ((config_focus_new || (settings && settings->focus == 1)) ||
+        ((config_focus_new || settings->focus == 1) ||
          client_search_focus_tree_full(self)) &&
         /* NET_WM_USER_TIME 0 when mapping means don't focus */
         (user_time != 0) &&
         /* this checks for focus=false for the window */
-        (!settings || settings->focus != 0) &&
+        settings->focus != 0 &&
         focus_valid_target(self, self->desktop,
                            FALSE, FALSE, TRUE, TRUE, FALSE, FALSE,
                            settings->focus == 1))
@@ -373,7 +359,7 @@ void client_manage(Window window, ObPrompt *prompt)
                              (self->type == OB_CLIENT_TYPE_DIALOG ||
                               self->type == OB_CLIENT_TYPE_SPLASH ||
                               (!((self->positioned & USPosition) ||
-                                 (settings && settings->pos_given)) &&
+                                 settings->pos_given) &&
                                client_normal(self) &&
                                !self->session &&
                                /* don't move oldschool fullscreen windows to
@@ -441,7 +427,7 @@ void client_manage(Window window, ObPrompt *prompt)
     ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s",
                   activate ? "yes" : "no");
     if (activate) {
-        activate = client_can_steal_focus(self, (settings && settings->focus),
+        activate = client_can_steal_focus(self, settings->focus,
                                           event_time(), launch_time);
 
         if (!activate) {
@@ -520,11 +506,11 @@ ObClient *client_fake_manage(Window window)
        uses too. this returns a shallow copy that needs to be freed */
     settings = client_get_settings_state(self);
 
-    client_setup_decor_and_functions(self, FALSE);
-
     /* create the decoration frame for the client window and adjust its size */
     self->frame = frame_new(self);
-    frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
+
+    client_apply_startup_state(self, self->area.x, self->area.y,
+                               self->area.width, self->area.height);
 
     ob_debug("gave extents left %d right %d top %d bottom %d",
              self->frame->size.left, self->frame->size.right,
@@ -1103,9 +1089,16 @@ static void client_get_all(ObClient *self, gboolean real)
     client_get_mwm_hints(self);
     /* this can change the mwmhints for special cases */
     client_get_type_and_transientness(self);
-    client_get_state(self);
     client_update_normal_hints(self);
 
+    /* set up the decor/functions before getting the state.  the states may
+       affect which functions are available, but we want to know the maximum
+       decor/functions are available to this window, so we can then apply them
+       in client_apply_startup_state() */
+    client_setup_decor_and_functions(self, FALSE);
+
+    client_get_state(self);
+
     /* get the session related properties, these can change decorations
        from per-app settings */
     client_get_session_ids(self);
@@ -1152,11 +1145,10 @@ static void client_get_all(ObClient *self, gboolean real)
 
 static void client_get_startup_id(ObClient *self)
 {
-    if (!(OBT_PROP_GETS(self->window, NET_STARTUP_ID, utf8,
-                        &self->startup_id)))
+    if (!(OBT_PROP_GETS_UTF8(self->window, NET_STARTUP_ID, &self->startup_id)))
         if (self->group)
-            OBT_PROP_GETS(self->group->leader,
-                          NET_STARTUP_ID, utf8, &self->startup_id);
+            OBT_PROP_GETS_UTF8(self->group->leader, NET_STARTUP_ID,
+                               &self->startup_id);
 }
 
 static void client_get_area(ObClient *self)
@@ -1967,15 +1959,14 @@ void client_update_title(ObClient *self)
     g_free(self->original_title);
 
     /* try netwm */
-    if (!OBT_PROP_GETS(self->window, NET_WM_NAME, utf8, &data)) {
+    if (!OBT_PROP_GETS_UTF8(self->window, NET_WM_NAME, &data)) {
         /* try old x stuff */
-        if (!(OBT_PROP_GETS(self->window, WM_NAME, locale, &data)
-              || OBT_PROP_GETS(self->window, WM_NAME, utf8, &data))) {
+        if (!OBT_PROP_GETS(self->window, WM_NAME, &data)) {
             if (self->transient) {
-    /*
-    GNOME alert windows are not given titles:
-    http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
-    */
+   /*
+   GNOME alert windows are not given titles:
+   http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
+   */
                 data = g_strdup("");
             } else
                 data = g_strdup(_("Unnamed Window"));
@@ -1998,7 +1989,7 @@ void client_update_title(ObClient *self)
         g_free(data);
     }
 
-    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_NAME, utf8, visible);
+    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_NAME, visible);
     self->title = visible;
 
     if (self->frame)
@@ -2009,10 +2000,9 @@ void client_update_title(ObClient *self)
     g_free(self->icon_title);
 
     /* try netwm */
-    if (!OBT_PROP_GETS(self->window, NET_WM_ICON_NAME, utf8, &data))
+    if (!OBT_PROP_GETS_UTF8(self->window, NET_WM_ICON_NAME, &data))
         /* try old x stuff */
-        if (!(OBT_PROP_GETS(self->window, WM_ICON_NAME, locale, &data) ||
-              OBT_PROP_GETS(self->window, WM_ICON_NAME, utf8, &data)))
+        if (!OBT_PROP_GETS(self->window, WM_ICON_NAME, &data))
             data = g_strdup(self->title);
 
     if (self->client_machine) {
@@ -2030,7 +2020,7 @@ void client_update_title(ObClient *self)
         g_free(data);
     }
 
-    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_ICON_NAME, utf8, visible);
+    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_ICON_NAME, visible);
     self->icon_title = visible;
 }
 
@@ -2093,7 +2083,6 @@ void client_update_icons(ObClient *self)
     guint num;
     guint32 *data;
     guint w, h, i, j;
-    guint num_seen;  /* number of icons present */
     RrImage *img;
 
     img = NULL;
@@ -2106,13 +2095,15 @@ 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;
-        num_seen = 0;
         while (i + 2 < num) { /* +2 is to make sure there is a w and h */
             w = data[i++];
             h = data[i++];
             /* watch for the data being too small for the specified size,
                or for zero sized icons. */
-            if (i + w*h > num || w == 0 || h == 0) break;
+            if (i + w*h > num || w == 0 || h == 0) {
+                i += w*h;
+                continue;
+            }
 
             /* convert it to the right bit order for ObRender */
             for (j = 0; j < w*h; ++j)
@@ -2122,29 +2113,13 @@ void client_update_icons(ObClient *self)
                     (((data[i+j] >>  8) & 0xff) << RrDefaultGreenOffset) +
                     (((data[i+j] >>  0) & 0xff) << RrDefaultBlueOffset);
 
-            /* is it in the cache? */
-            img = RrImageCacheFind(ob_rr_icons, &data[i], w, h);
-            if (img) RrImageRef(img); /* own it */
+            /* add it to the image cache as an original */
+            if (!img)
+                img = RrImageNewFromData(ob_rr_icons, &data[i], w, h);
+            else
+                RrImageAddFromData(img, &data[i], w, h);
 
             i += w*h;
-            ++num_seen;
-
-            /* don't bother looping anymore if we already found it in the cache
-               since we'll just use that! */
-            if (img) break;
-        }
-
-        /* if it's not in the cache yet, then add it to the cache now.
-           we have already converted it to the correct bit order above */
-        if (!img && num_seen > 0) {
-            img = RrImageNew(ob_rr_icons);
-            i = 0;
-            for (j = 0; j < num_seen; ++j) {
-                w = data[i++];
-                h = data[i++];
-                RrImageAddPicture(img, &data[i], w, h);
-                i += w*h;
-            }
         }
 
         g_free(data);
@@ -2168,15 +2143,10 @@ void client_update_icons(ObClient *self)
 
                 if (xicon) {
                     if (w > 0 && h > 0) {
-                        /* is this icon in the cache yet? */
-                        img = RrImageCacheFind(ob_rr_icons, data, w, h);
-                        if (img) RrImageRef(img); /* own it */
-
-                        /* if not, then add it */
-                        if (!img) {
-                            img = RrImageNew(ob_rr_icons);
-                            RrImageAddPicture(img, data, w, h);
-                        }
+                        if (!img)
+                            img = RrImageNewFromData(ob_rr_icons, data, w, h);
+                        else
+                            RrImageAddFromData(img, data, w, h);
                     }
 
                     g_free(data);
@@ -2246,19 +2216,14 @@ static void client_get_session_ids(ObClient *self)
         leader = None;
 
     /* get the SM_CLIENT_ID */
-    got = FALSE;
-    if (leader)
-        got = OBT_PROP_GETS(leader, SM_CLIENT_ID, locale, &self->sm_client_id);
-    if (!got)
-        OBT_PROP_GETS(self->window, SM_CLIENT_ID, locale, &self->sm_client_id);
+    if (leader && leader != self->window)
+        OBT_PROP_GETS_XPCS(leader, SM_CLIENT_ID, &self->sm_client_id);
+    else
+        OBT_PROP_GETS_XPCS(self->window, SM_CLIENT_ID, &self->sm_client_id);
 
     /* get the WM_CLASS (name and class). make them "" if they are not
        provided */
-    got = FALSE;
-    if (leader)
-        got = OBT_PROP_GETSS(leader, WM_CLASS, locale, &ss);
-    if (!got)
-        got = OBT_PROP_GETSS(self->window, WM_CLASS, locale, &ss);
+    got = OBT_PROP_GETSS_TYPE(self->window, WM_CLASS, STRING_NO_CC, &ss);
 
     if (got) {
         if (ss[0]) {
@@ -2273,11 +2238,7 @@ static void client_get_session_ids(ObClient *self)
     if (self->class == NULL) self->class = g_strdup("");
 
     /* get the WM_WINDOW_ROLE. make it "" if it is not provided */
-    got = FALSE;
-    if (leader)
-        got = OBT_PROP_GETS(leader, WM_WINDOW_ROLE, locale, &s);
-    if (!got)
-        got = OBT_PROP_GETS(self->window, WM_WINDOW_ROLE, locale, &s);
+    got = OBT_PROP_GETS_XPCS(self->window, WM_WINDOW_ROLE, &s);
 
     if (got)
         self->role = s;
@@ -2288,9 +2249,9 @@ static void client_get_session_ids(ObClient *self)
     got = FALSE;
 
     if (leader)
-        got = OBT_PROP_GETSS(leader, WM_COMMAND, locale, &ss);
+        got = OBT_PROP_GETSS(leader, WM_COMMAND, &ss);
     if (!got)
-        got = OBT_PROP_GETSS(self->window, WM_COMMAND, locale, &ss);
+        got = OBT_PROP_GETSS(self->window, WM_COMMAND, &ss);
 
     if (got) {
         /* merge/mash them all together */
@@ -2313,9 +2274,9 @@ static void client_get_session_ids(ObClient *self)
     /* get the WM_CLIENT_MACHINE */
     got = FALSE;
     if (leader)
-        got = OBT_PROP_GETS(leader, WM_CLIENT_MACHINE, locale, &s);
+        got = OBT_PROP_GETS(leader, WM_CLIENT_MACHINE, &s);
     if (!got)
-        got = OBT_PROP_GETS(self->window, WM_CLIENT_MACHINE, locale, &s);
+        got = OBT_PROP_GETS(self->window, WM_CLIENT_MACHINE, &s);
 
     if (got) {
         gchar localhost[128];
@@ -2342,10 +2303,10 @@ static void client_save_app_rule_values(ObClient *self)
 {
     const gchar *type;
 
-    OBT_PROP_SETS(self->window, OB_APP_ROLE, utf8, self->role);
-    OBT_PROP_SETS(self->window, OB_APP_NAME, utf8, self->name);
-    OBT_PROP_SETS(self->window, OB_APP_CLASS, utf8, self->class);
-    OBT_PROP_SETS(self->window, OB_APP_TITLE, utf8, self->original_title);
+    OBT_PROP_SETS(self->window, OB_APP_ROLE, self->role);
+    OBT_PROP_SETS(self->window, OB_APP_NAME, self->name);
+    OBT_PROP_SETS(self->window, OB_APP_CLASS, self->class);
+    OBT_PROP_SETS(self->window, OB_APP_TITLE, self->original_title);
 
     switch (self->type) {
     case OB_CLIENT_TYPE_NORMAL:
@@ -2365,7 +2326,7 @@ static void client_save_app_rule_values(ObClient *self)
     case OB_CLIENT_TYPE_DOCK:
         type = "dock"; break;
     }
-    OBT_PROP_SETS(self->window, OB_APP_TYPE, utf8, type);
+    OBT_PROP_SETS(self->window, OB_APP_TYPE, type);
 }
 
 static void client_change_wm_state(ObClient *self)
@@ -2734,8 +2695,6 @@ static void client_apply_startup_state(ObClient *self,
 
     if (iconic)
         client_iconify(self, TRUE, FALSE, TRUE);
-    if (fullscreen)
-        client_fullscreen(self, TRUE);
     if (undecorated)
         client_set_undecorated(self, TRUE);
     if (shaded)
@@ -2750,6 +2709,10 @@ static void client_apply_startup_state(ObClient *self,
     else if (max_horz)
         client_maximize(self, TRUE, 1);
 
+    /* fullscreen removes the ability to apply other states */
+    if (fullscreen)
+        client_fullscreen(self, TRUE);
+
     /* if the window hasn't been configured yet, then do so now, in fact the
        x,y,w,h may _not_ be the same as the area rect, which can end up
        meaning that the client isn't properly moved/resized by the fullscreen