iconcache.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /* Metacity window icons */
00004 
00005 /*
00006  * Copyright (C) 2002 Havoc Pennington
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00021  * 02111-1307, USA.
00022  */
00023 
00024 #include <config.h>
00025 #include "iconcache.h"
00026 #include "ui.h"
00027 #include "errors.h"
00028 
00029 #include <X11/Xatom.h>
00030 
00031 /* The icon-reading code is also in libwnck, please sync bugfixes */
00032 
00033 static void
00034 get_fallback_icons (MetaScreen     *screen,
00035                     GdkPixbuf     **iconp,
00036                     int             ideal_width,
00037                     int             ideal_height,
00038                     GdkPixbuf     **mini_iconp,
00039                     int             ideal_mini_width,
00040                     int             ideal_mini_height)
00041 {
00042   /* we don't scale, should be fixed if we ever un-hardcode the icon
00043    * size
00044    */
00045   *iconp = meta_ui_get_default_window_icon (screen->ui);
00046   *mini_iconp = meta_ui_get_default_mini_icon (screen->ui);
00047 }
00048 
00049 static gboolean
00050 find_largest_sizes (gulong *data,
00051                     gulong  nitems,
00052                     int    *width,
00053                     int    *height)
00054 {
00055   *width = 0;
00056   *height = 0;
00057 
00058   while (nitems > 0)
00059     {
00060       int w, h;
00061 
00062       if (nitems < 3)
00063         return FALSE; /* no space for w, h */
00064 
00065       w = data[0];
00066       h = data[1];
00067 
00068       if (nitems < ((gulong)(w * h) + 2))
00069         return FALSE; /* not enough data */
00070 
00071       *width = MAX (w, *width);
00072       *height = MAX (h, *height);
00073 
00074       data += (w * h) + 2;
00075       nitems -= (w * h) + 2;
00076     }
00077 
00078   return TRUE;
00079 }
00080 
00081 static gboolean
00082 find_best_size (gulong  *data,
00083                 gulong   nitems,
00084                 int      ideal_width,
00085                 int      ideal_height,
00086                 int     *width,
00087                 int     *height,
00088                 gulong **start)
00089 {
00090   int best_w;
00091   int best_h;
00092   gulong *best_start;
00093   int max_width, max_height;
00094 
00095   *width = 0;
00096   *height = 0;
00097   *start = NULL;
00098 
00099   if (!find_largest_sizes (data, nitems, &max_width, &max_height))
00100     return FALSE;
00101 
00102   if (ideal_width < 0)
00103     ideal_width = max_width;
00104   if (ideal_height < 0)
00105     ideal_height = max_height;
00106 
00107   best_w = 0;
00108   best_h = 0;
00109   best_start = NULL;
00110 
00111   while (nitems > 0)
00112     {
00113       int w, h;
00114       gboolean replace;
00115 
00116       replace = FALSE;
00117 
00118       if (nitems < 3)
00119         return FALSE; /* no space for w, h */
00120 
00121       w = data[0];
00122       h = data[1];
00123 
00124       if (nitems < ((gulong)(w * h) + 2))
00125         break; /* not enough data */
00126 
00127       if (best_start == NULL)
00128         {
00129           replace = TRUE;
00130         }
00131       else
00132         {
00133           /* work with averages */
00134           const int ideal_size = (ideal_width + ideal_height) / 2;
00135           int best_size = (best_w + best_h) / 2;
00136           int this_size = (w + h) / 2;
00137 
00138           /* larger than desired is always better than smaller */
00139           if (best_size < ideal_size &&
00140               this_size >= ideal_size)
00141             replace = TRUE;
00142           /* if we have too small, pick anything bigger */
00143           else if (best_size < ideal_size &&
00144                    this_size > best_size)
00145             replace = TRUE;
00146           /* if we have too large, pick anything smaller
00147            * but still >= the ideal
00148            */
00149           else if (best_size > ideal_size &&
00150                    this_size >= ideal_size &&
00151                    this_size < best_size)
00152             replace = TRUE;
00153         }
00154 
00155       if (replace)
00156         {
00157           best_start = data + 2;
00158           best_w = w;
00159           best_h = h;
00160         }
00161 
00162       data += (w * h) + 2;
00163       nitems -= (w * h) + 2;
00164     }
00165 
00166   if (best_start)
00167     {
00168       *start = best_start;
00169       *width = best_w;
00170       *height = best_h;
00171       return TRUE;
00172     }
00173   else
00174     return FALSE;
00175 }
00176 
00177 static void
00178 argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata)
00179 {
00180   guchar *p;
00181   int i;
00182 
00183   *pixdata = g_new (guchar, len * 4);
00184   p = *pixdata;
00185 
00186   /* One could speed this up a lot. */
00187   i = 0;
00188   while (i < len)
00189     {
00190       guint argb;
00191       guint rgba;
00192 
00193       argb = argb_data[i];
00194       rgba = (argb << 8) | (argb >> 24);
00195 
00196       *p = rgba >> 24;
00197       ++p;
00198       *p = (rgba >> 16) & 0xff;
00199       ++p;
00200       *p = (rgba >> 8) & 0xff;
00201       ++p;
00202       *p = rgba & 0xff;
00203       ++p;
00204 
00205       ++i;
00206     }
00207 }
00208 
00209 static gboolean
00210 read_rgb_icon (MetaDisplay   *display,
00211                Window         xwindow,
00212                int            ideal_width,
00213                int            ideal_height,
00214                int            ideal_mini_width,
00215                int            ideal_mini_height,
00216                int           *width,
00217                int           *height,
00218                guchar       **pixdata,
00219                int           *mini_width,
00220                int           *mini_height,
00221                guchar       **mini_pixdata)
00222 {
00223   Atom type;
00224   int format;
00225   gulong nitems;
00226   gulong bytes_after;
00227   int result, err;
00228   gulong *data;
00229   gulong *best;
00230   int w, h;
00231   gulong *best_mini;
00232   int mini_w, mini_h;
00233 
00234   meta_error_trap_push_with_return (display);
00235   type = None;
00236   data = NULL;
00237   result = XGetWindowProperty (display->xdisplay,
00238                                xwindow,
00239                                display->atom__NET_WM_ICON,
00240                                0, G_MAXLONG,
00241                                False, XA_CARDINAL, &type, &format, &nitems,
00242                                &bytes_after, ((guchar **)&data));
00243 
00244   err = meta_error_trap_pop_with_return (display, TRUE);
00245 
00246   if (err != Success ||
00247       result != Success)
00248     return FALSE;
00249 
00250   if (type != XA_CARDINAL)
00251     {
00252       XFree (data);
00253       return FALSE;
00254     }
00255 
00256   if (!find_best_size (data, nitems,
00257                        ideal_width, ideal_height,
00258                        &w, &h, &best))
00259     {
00260       XFree (data);
00261       return FALSE;
00262     }
00263 
00264   if (!find_best_size (data, nitems,
00265                        ideal_mini_width, ideal_mini_height,
00266                        &mini_w, &mini_h, &best_mini))
00267     {
00268       XFree (data);
00269       return FALSE;
00270     }
00271 
00272   *width = w;
00273   *height = h;
00274 
00275   *mini_width = mini_w;
00276   *mini_height = mini_h;
00277 
00278   argbdata_to_pixdata (best, w * h, pixdata);
00279   argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata);
00280 
00281   XFree (data);
00282 
00283   return TRUE;
00284 }
00285 
00286 static void
00287 free_pixels (guchar *pixels, gpointer data)
00288 {
00289   g_free (pixels);
00290 }
00291 
00292 static void
00293 get_pixmap_geometry (MetaDisplay *display,
00294                      Pixmap       pixmap,
00295                      int         *w,
00296                      int         *h,
00297                      int         *d)
00298 {
00299   Window root_ignored;
00300   int x_ignored, y_ignored;
00301   guint width, height;
00302   guint border_width_ignored;
00303   guint depth;
00304 
00305   if (w)
00306     *w = 1;
00307   if (h)
00308     *h = 1;
00309   if (d)
00310     *d = 1;
00311 
00312   XGetGeometry (display->xdisplay,
00313                 pixmap, &root_ignored, &x_ignored, &y_ignored,
00314                 &width, &height, &border_width_ignored, &depth);
00315 
00316   if (w)
00317     *w = width;
00318   if (h)
00319     *h = height;
00320   if (d)
00321     *d = depth;
00322 }
00323 
00324 static GdkPixbuf*
00325 apply_mask (GdkPixbuf *pixbuf,
00326             GdkPixbuf *mask)
00327 {
00328   int w, h;
00329   int i, j;
00330   GdkPixbuf *with_alpha;
00331   guchar *src;
00332   guchar *dest;
00333   int src_stride;
00334   int dest_stride;
00335 
00336   w = MIN (gdk_pixbuf_get_width (mask), gdk_pixbuf_get_width (pixbuf));
00337   h = MIN (gdk_pixbuf_get_height (mask), gdk_pixbuf_get_height (pixbuf));
00338 
00339   with_alpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
00340 
00341   dest = gdk_pixbuf_get_pixels (with_alpha);
00342   src = gdk_pixbuf_get_pixels (mask);
00343 
00344   dest_stride = gdk_pixbuf_get_rowstride (with_alpha);
00345   src_stride = gdk_pixbuf_get_rowstride (mask);
00346 
00347   i = 0;
00348   while (i < h)
00349     {
00350       j = 0;
00351       while (j < w)
00352         {
00353           guchar *s = src + i * src_stride + j * 3;
00354           guchar *d = dest + i * dest_stride + j * 4;
00355 
00356           /* s[0] == s[1] == s[2], they are 255 if the bit was set, 0
00357            * otherwise
00358            */
00359           if (s[0] == 0)
00360             d[3] = 0;   /* transparent */
00361           else
00362             d[3] = 255; /* opaque */
00363 
00364           ++j;
00365         }
00366 
00367       ++i;
00368     }
00369 
00370   return with_alpha;
00371 }
00372 
00373 static gboolean
00374 try_pixmap_and_mask (MetaDisplay *display,
00375                      Pixmap       src_pixmap,
00376                      Pixmap       src_mask,
00377                      GdkPixbuf  **iconp,
00378                      int          ideal_width,
00379                      int          ideal_height,
00380                      GdkPixbuf  **mini_iconp,
00381                      int          ideal_mini_width,
00382                      int          ideal_mini_height)
00383 {
00384   GdkPixbuf *unscaled = NULL;
00385   GdkPixbuf *mask = NULL;
00386   int w, h;
00387 
00388   if (src_pixmap == None)
00389     return FALSE;
00390 
00391   meta_error_trap_push (display);
00392 
00393   get_pixmap_geometry (display, src_pixmap, &w, &h, NULL);
00394 
00395   unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
00396                                               src_pixmap,
00397                                               0, 0, 0, 0,
00398                                               w, h);
00399 
00400   if (unscaled && src_mask != None)
00401     {
00402       get_pixmap_geometry (display, src_mask, &w, &h, NULL);
00403       mask = meta_gdk_pixbuf_get_from_pixmap (NULL,
00404                                               src_mask,
00405                                               0, 0, 0, 0,
00406                                               w, h);
00407     }
00408 
00409   meta_error_trap_pop (display, FALSE);
00410 
00411   if (mask)
00412     {
00413       GdkPixbuf *masked;
00414 
00415       masked = apply_mask (unscaled, mask);
00416       g_object_unref (G_OBJECT (unscaled));
00417       unscaled = masked;
00418 
00419       g_object_unref (G_OBJECT (mask));
00420       mask = NULL;
00421     }
00422 
00423   if (unscaled)
00424     {
00425       *iconp =
00426         gdk_pixbuf_scale_simple (unscaled,
00427                                  ideal_width > 0 ? ideal_width :
00428                                  gdk_pixbuf_get_width (unscaled),
00429                                  ideal_height > 0 ? ideal_height :
00430                                  gdk_pixbuf_get_height (unscaled),
00431                                  GDK_INTERP_BILINEAR);
00432       *mini_iconp =
00433         gdk_pixbuf_scale_simple (unscaled,
00434                                  ideal_mini_width > 0 ? ideal_mini_width :
00435                                  gdk_pixbuf_get_width (unscaled),
00436                                  ideal_mini_height > 0 ? ideal_mini_height :
00437                                  gdk_pixbuf_get_height (unscaled),
00438                                  GDK_INTERP_BILINEAR);
00439 
00440       g_object_unref (G_OBJECT (unscaled));
00441       
00442       if (*iconp && *mini_iconp)
00443         return TRUE;
00444       else
00445         {
00446           if (*iconp)
00447             g_object_unref (G_OBJECT (*iconp));
00448           if (*mini_iconp)
00449             g_object_unref (G_OBJECT (*mini_iconp));
00450           return FALSE;
00451         }
00452     }
00453   else
00454     return FALSE;
00455 }
00456 
00457 static void
00458 get_kwm_win_icon (MetaDisplay *display,
00459                   Window       xwindow,
00460                   Pixmap      *pixmap,
00461                   Pixmap      *mask)
00462 {
00463   Atom type;
00464   int format;
00465   gulong nitems;
00466   gulong bytes_after;
00467   Pixmap *icons;
00468   int err, result;
00469 
00470   *pixmap = None;
00471   *mask = None;
00472 
00473   meta_error_trap_push_with_return (display);
00474   icons = NULL;
00475   result = XGetWindowProperty (display->xdisplay, xwindow,
00476                                display->atom__KWM_WIN_ICON,
00477                                0, G_MAXLONG,
00478                                False,
00479                                display->atom__KWM_WIN_ICON,
00480                                &type, &format, &nitems,
00481                                &bytes_after, (guchar **)&icons);
00482 
00483   err = meta_error_trap_pop_with_return (display, TRUE);
00484   if (err != Success ||
00485       result != Success)
00486     return;
00487 
00488   if (type != display->atom__KWM_WIN_ICON)
00489     {
00490       XFree (icons);
00491       return;
00492     }
00493 
00494   *pixmap = icons[0];
00495   *mask = icons[1];
00496 
00497   XFree (icons);
00498 
00499   return;
00500 }
00501 
00502 void
00503 meta_icon_cache_init (MetaIconCache *icon_cache)
00504 {
00505   g_return_if_fail (icon_cache != NULL);
00506 
00507   icon_cache->origin = USING_NO_ICON;
00508   icon_cache->prev_pixmap = None;
00509   icon_cache->prev_mask = None;
00510 #if 0
00511   icon_cache->icon = NULL;
00512   icon_cache->mini_icon = NULL;
00513   icon_cache->ideal_width = -1; /* won't be a legit width */
00514   icon_cache->ideal_height = -1;
00515   icon_cache->ideal_mini_width = -1;
00516   icon_cache->ideal_mini_height = -1;
00517 #endif
00518   icon_cache->want_fallback = TRUE;
00519   icon_cache->wm_hints_dirty = TRUE;
00520   icon_cache->kwm_win_icon_dirty = TRUE;
00521   icon_cache->net_wm_icon_dirty = TRUE;
00522 }
00523 
00524 static void
00525 clear_icon_cache (MetaIconCache *icon_cache,
00526                   gboolean       dirty_all)
00527 {
00528 #if 0
00529   if (icon_cache->icon)
00530     g_object_unref (G_OBJECT (icon_cache->icon));
00531   icon_cache->icon = NULL;
00532 
00533   if (icon_cache->mini_icon)
00534     g_object_unref (G_OBJECT (icon_cache->mini_icon));
00535   icon_cache->mini_icon = NULL;
00536 #endif
00537   
00538   icon_cache->origin = USING_NO_ICON;
00539 
00540   if (dirty_all)
00541     {
00542       icon_cache->wm_hints_dirty = TRUE;
00543       icon_cache->kwm_win_icon_dirty = TRUE;
00544       icon_cache->net_wm_icon_dirty = TRUE;
00545     }
00546 }
00547 
00548 void
00549 meta_icon_cache_free (MetaIconCache *icon_cache)
00550 {
00551   clear_icon_cache (icon_cache, FALSE);
00552 }
00553 
00554 void
00555 meta_icon_cache_property_changed (MetaIconCache *icon_cache,
00556                                   MetaDisplay   *display,
00557                                   Atom           atom)
00558 {
00559   if (atom == display->atom__NET_WM_ICON)
00560     icon_cache->net_wm_icon_dirty = TRUE;
00561   else if (atom == display->atom__KWM_WIN_ICON)
00562     icon_cache->kwm_win_icon_dirty = TRUE;
00563   else if (atom == XA_WM_HINTS)
00564     icon_cache->wm_hints_dirty = TRUE;
00565 }
00566 
00567 gboolean
00568 meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache)
00569 {
00570   if (icon_cache->origin <= USING_KWM_WIN_ICON &&
00571       icon_cache->kwm_win_icon_dirty)
00572     return TRUE;
00573   else if (icon_cache->origin <= USING_WM_HINTS &&
00574            icon_cache->wm_hints_dirty)
00575     return TRUE;
00576   else if (icon_cache->origin <= USING_NET_WM_ICON &&
00577            icon_cache->net_wm_icon_dirty)
00578     return TRUE;
00579   else if (icon_cache->origin < USING_FALLBACK_ICON &&
00580            icon_cache->want_fallback)
00581     return TRUE;
00582   else if (icon_cache->origin == USING_NO_ICON)
00583     return TRUE;
00584   else if (icon_cache->origin == USING_FALLBACK_ICON &&
00585            !icon_cache->want_fallback)
00586     return TRUE;
00587   else
00588     return FALSE;
00589 }
00590 
00591 static void
00592 replace_cache (MetaIconCache *icon_cache,
00593                IconOrigin     origin,
00594                GdkPixbuf     *new_icon,
00595                GdkPixbuf     *new_mini_icon)
00596 {
00597   clear_icon_cache (icon_cache, FALSE);
00598 
00599   icon_cache->origin = origin;
00600 
00601 #if 0
00602   if (new_icon)
00603     g_object_ref (G_OBJECT (new_icon));
00604 
00605   icon_cache->icon = new_icon;
00606 
00607   if (new_mini_icon)
00608     g_object_ref (G_OBJECT (new_mini_icon));
00609 
00610   icon_cache->mini_icon = new_mini_icon;
00611 #endif
00612 }
00613 
00614 static GdkPixbuf*
00615 scaled_from_pixdata (guchar *pixdata,
00616                      int     w,
00617                      int     h,
00618                      int     new_w,
00619                      int     new_h)
00620 {
00621   GdkPixbuf *src;
00622   GdkPixbuf *dest;
00623   
00624   src = gdk_pixbuf_new_from_data (pixdata,
00625                                   GDK_COLORSPACE_RGB,
00626                                   TRUE,
00627                                   8,
00628                                   w, h, w * 4,
00629                                   free_pixels, 
00630                                   NULL);
00631 
00632   if (src == NULL)
00633     return NULL;
00634 
00635   if (w != h)
00636     {
00637       GdkPixbuf *tmp;
00638       int size;
00639 
00640       size = MAX (w, h);
00641       
00642       tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
00643 
00644       if (tmp)
00645         {
00646           gdk_pixbuf_fill (tmp, 0);
00647           gdk_pixbuf_copy_area (src, 0, 0, w, h,
00648                                 tmp,
00649                                 (size - w) / 2, (size - h) / 2);
00650           
00651           g_object_unref (src);
00652           src = tmp;
00653         }
00654     }
00655   
00656   if (w != new_w || h != new_h)
00657     {
00658       dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR);
00659       
00660       g_object_unref (G_OBJECT (src));
00661     }
00662   else
00663     {
00664       dest = src;
00665     }
00666 
00667   return dest;
00668 }
00669 
00670 gboolean
00671 meta_read_icons (MetaScreen     *screen,
00672                  Window          xwindow,
00673                  MetaIconCache  *icon_cache,
00674                  Pixmap          wm_hints_pixmap,
00675                  Pixmap          wm_hints_mask,
00676                  GdkPixbuf     **iconp,
00677                  int             ideal_width,
00678                  int             ideal_height,
00679                  GdkPixbuf     **mini_iconp,
00680                  int             ideal_mini_width,
00681                  int             ideal_mini_height)
00682 {
00683   guchar *pixdata;
00684   int w, h;
00685   guchar *mini_pixdata;
00686   int mini_w, mini_h;
00687   Pixmap pixmap;
00688   Pixmap mask;
00689 
00690   /* Return value is whether the icon changed */
00691 
00692   g_return_val_if_fail (icon_cache != NULL, FALSE);
00693 
00694   *iconp = NULL;
00695   *mini_iconp = NULL;
00696 
00697 #if 0
00698   if (ideal_width != icon_cache->ideal_width ||
00699       ideal_height != icon_cache->ideal_height ||
00700       ideal_mini_width != icon_cache->ideal_mini_width ||
00701       ideal_mini_height != icon_cache->ideal_mini_height)
00702     clear_icon_cache (icon_cache, TRUE);
00703 
00704   icon_cache->ideal_width = ideal_width;
00705   icon_cache->ideal_height = ideal_height;
00706   icon_cache->ideal_mini_width = ideal_mini_width;
00707   icon_cache->ideal_mini_height = ideal_mini_height;
00708 #endif
00709   
00710   if (!meta_icon_cache_get_icon_invalidated (icon_cache))
00711     return FALSE; /* we have no new info to use */
00712 
00713   pixdata = NULL;
00714 
00715   /* Our algorithm here assumes that we can't have for example origin
00716    * < USING_NET_WM_ICON and icon_cache->net_wm_icon_dirty == FALSE
00717    * unless we have tried to read NET_WM_ICON.
00718    *
00719    * Put another way, if an icon origin is not dirty, then we have
00720    * tried to read it at the current size. If it is dirty, then
00721    * we haven't done that since the last change.
00722    */
00723 
00724   if (icon_cache->origin <= USING_NET_WM_ICON &&
00725       icon_cache->net_wm_icon_dirty)
00726 
00727     {
00728       icon_cache->net_wm_icon_dirty = FALSE;
00729 
00730       if (read_rgb_icon (screen->display, xwindow,
00731                          ideal_width, ideal_height,
00732                          ideal_mini_width, ideal_mini_height,
00733                          &w, &h, &pixdata,
00734                          &mini_w, &mini_h, &mini_pixdata))
00735         {
00736           *iconp = scaled_from_pixdata (pixdata, w, h,
00737                                         ideal_width, ideal_height);
00738 
00739           *mini_iconp = scaled_from_pixdata (mini_pixdata, mini_w, mini_h,
00740                                              ideal_mini_width, ideal_mini_height);
00741 
00742           if (*iconp && *mini_iconp)
00743             {
00744               replace_cache (icon_cache, USING_NET_WM_ICON,
00745                              *iconp, *mini_iconp);
00746               
00747               return TRUE;
00748             }
00749           else
00750             {
00751               if (*iconp)
00752                 g_object_unref (G_OBJECT (*iconp));
00753               if (*mini_iconp)
00754                 g_object_unref (G_OBJECT (*mini_iconp));
00755             }
00756         }
00757     }
00758 
00759   if (icon_cache->origin <= USING_WM_HINTS &&
00760       icon_cache->wm_hints_dirty)
00761     {
00762       icon_cache->wm_hints_dirty = FALSE;
00763 
00764       pixmap = wm_hints_pixmap;
00765       mask = wm_hints_mask;
00766 
00767       /* We won't update if pixmap is unchanged;
00768        * avoids a get_from_drawable() on every geometry
00769        * hints change
00770        */
00771       if ((pixmap != icon_cache->prev_pixmap ||
00772            mask != icon_cache->prev_mask) &&
00773           pixmap != None)
00774         {
00775           if (try_pixmap_and_mask (screen->display,
00776                                    pixmap, mask,
00777                                    iconp, ideal_width, ideal_height,
00778                                    mini_iconp, ideal_mini_width, ideal_mini_height))
00779             {
00780               icon_cache->prev_pixmap = pixmap;
00781               icon_cache->prev_mask = mask;
00782 
00783               replace_cache (icon_cache, USING_WM_HINTS,
00784                              *iconp, *mini_iconp);
00785 
00786               return TRUE;
00787             }
00788         }
00789     }
00790 
00791   if (icon_cache->origin <= USING_KWM_WIN_ICON &&
00792       icon_cache->kwm_win_icon_dirty)
00793     {
00794       icon_cache->kwm_win_icon_dirty = FALSE;
00795 
00796       get_kwm_win_icon (screen->display, xwindow, &pixmap, &mask);
00797 
00798       if ((pixmap != icon_cache->prev_pixmap ||
00799            mask != icon_cache->prev_mask) &&
00800           pixmap != None)
00801         {
00802           if (try_pixmap_and_mask (screen->display, pixmap, mask,
00803                                    iconp, ideal_width, ideal_height,
00804                                    mini_iconp, ideal_mini_width, ideal_mini_height))
00805             {
00806               icon_cache->prev_pixmap = pixmap;
00807               icon_cache->prev_mask = mask;
00808 
00809               replace_cache (icon_cache, USING_KWM_WIN_ICON,
00810                              *iconp, *mini_iconp);
00811 
00812               return TRUE;
00813             }
00814         }
00815     }
00816 
00817   if (icon_cache->want_fallback &&
00818       icon_cache->origin < USING_FALLBACK_ICON)
00819     {
00820       GdkPixbuf *fallback_icon;
00821       GdkPixbuf *fallback_mini_icon;
00822       
00823       fallback_icon = NULL;
00824       fallback_mini_icon = NULL;
00825 
00826       meta_ui_get_fallback_icons(&fallback_icon, &fallback_mini_icon);
00827 
00828       if (fallback_icon == NULL || fallback_mini_icon == NULL)
00829         {
00830           get_fallback_icons (screen,
00831                               iconp,
00832                               ideal_width,
00833                               ideal_height,
00834                               mini_iconp,
00835                               ideal_mini_width,
00836                               ideal_mini_height);
00837         }
00838 
00839       if (fallback_icon != NULL)
00840         *iconp = fallback_icon;
00841       if (fallback_mini_icon != NULL)
00842         *mini_iconp = fallback_mini_icon;
00843       
00844       replace_cache (icon_cache, USING_FALLBACK_ICON,
00845                      *iconp, *mini_iconp);
00846       
00847       return TRUE;
00848     }
00849 
00850   if (!icon_cache->want_fallback &&
00851       icon_cache->origin == USING_FALLBACK_ICON)
00852     {
00853       /* Get rid of current icon */
00854       clear_icon_cache (icon_cache, FALSE);
00855 
00856       return TRUE;
00857     }
00858 
00859   /* found nothing new */
00860   return FALSE;
00861 }

Generated on Sat Aug 23 22:04:16 2008 for metacity by  doxygen 1.5.5