diff options
author | Thomas James Alexander Thurman <tthurman@src.gnome.org> | 2009-01-22 05:14:00 +0000 |
---|---|---|
committer | Thomas James Alexander Thurman <tthurman@src.gnome.org> | 2009-01-22 05:14:00 +0000 |
commit | 3945cdefdaad26979226be0940a7758fad41874e (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/core/iconcache.c | |
parent | 1b35154e2baec3f0a6854a2f5538444bcebac1d0 (diff) | |
download | metacity-git-migration-mbus.tar.gz |
Fix typogit-migration-mbus
svn path=/tags/git-migration-mbus; revision=4083
Diffstat (limited to 'src/core/iconcache.c')
-rw-r--r-- | src/core/iconcache.c | 849 |
1 files changed, 0 insertions, 849 deletions
diff --git a/src/core/iconcache.c b/src/core/iconcache.c deleted file mode 100644 index 7fa21840..00000000 --- a/src/core/iconcache.c +++ /dev/null @@ -1,849 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window icons */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "iconcache.h" -#include "ui.h" -#include "errors.h" - -#include <X11/Xatom.h> - -/* The icon-reading code is also in libwnck, please sync bugfixes */ - -static void -get_fallback_icons (MetaScreen *screen, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - /* we don't scale, should be fixed if we ever un-hardcode the icon - * size - */ - *iconp = meta_ui_get_default_window_icon (screen->ui); - *mini_iconp = meta_ui_get_default_mini_icon (screen->ui); -} - -static gboolean -find_largest_sizes (gulong *data, - gulong nitems, - int *width, - int *height) -{ - *width = 0; - *height = 0; - - while (nitems > 0) - { - int w, h; - - if (nitems < 3) - return FALSE; /* no space for w, h */ - - w = data[0]; - h = data[1]; - - if (nitems < ((gulong)(w * h) + 2)) - return FALSE; /* not enough data */ - - *width = MAX (w, *width); - *height = MAX (h, *height); - - data += (w * h) + 2; - nitems -= (w * h) + 2; - } - - return TRUE; -} - -static gboolean -find_best_size (gulong *data, - gulong nitems, - int ideal_width, - int ideal_height, - int *width, - int *height, - gulong **start) -{ - int best_w; - int best_h; - gulong *best_start; - int max_width, max_height; - - *width = 0; - *height = 0; - *start = NULL; - - if (!find_largest_sizes (data, nitems, &max_width, &max_height)) - return FALSE; - - if (ideal_width < 0) - ideal_width = max_width; - if (ideal_height < 0) - ideal_height = max_height; - - best_w = 0; - best_h = 0; - best_start = NULL; - - while (nitems > 0) - { - int w, h; - gboolean replace; - - replace = FALSE; - - if (nitems < 3) - return FALSE; /* no space for w, h */ - - w = data[0]; - h = data[1]; - - if (nitems < ((gulong)(w * h) + 2)) - break; /* not enough data */ - - if (best_start == NULL) - { - replace = TRUE; - } - else - { - /* work with averages */ - const int ideal_size = (ideal_width + ideal_height) / 2; - int best_size = (best_w + best_h) / 2; - int this_size = (w + h) / 2; - - /* larger than desired is always better than smaller */ - if (best_size < ideal_size && - this_size >= ideal_size) - replace = TRUE; - /* if we have too small, pick anything bigger */ - else if (best_size < ideal_size && - this_size > best_size) - replace = TRUE; - /* if we have too large, pick anything smaller - * but still >= the ideal - */ - else if (best_size > ideal_size && - this_size >= ideal_size && - this_size < best_size) - replace = TRUE; - } - - if (replace) - { - best_start = data + 2; - best_w = w; - best_h = h; - } - - data += (w * h) + 2; - nitems -= (w * h) + 2; - } - - if (best_start) - { - *start = best_start; - *width = best_w; - *height = best_h; - return TRUE; - } - else - return FALSE; -} - -static void -argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata) -{ - guchar *p; - int i; - - *pixdata = g_new (guchar, len * 4); - p = *pixdata; - - /* One could speed this up a lot. */ - i = 0; - while (i < len) - { - guint argb; - guint rgba; - - argb = argb_data[i]; - rgba = (argb << 8) | (argb >> 24); - - *p = rgba >> 24; - ++p; - *p = (rgba >> 16) & 0xff; - ++p; - *p = (rgba >> 8) & 0xff; - ++p; - *p = rgba & 0xff; - ++p; - - ++i; - } -} - -static gboolean -read_rgb_icon (MetaDisplay *display, - Window xwindow, - int ideal_width, - int ideal_height, - int ideal_mini_width, - int ideal_mini_height, - int *width, - int *height, - guchar **pixdata, - int *mini_width, - int *mini_height, - guchar **mini_pixdata) -{ - Atom type; - int format; - gulong nitems; - gulong bytes_after; - int result, err; - guchar *data; - gulong *best; - int w, h; - gulong *best_mini; - int mini_w, mini_h; - gulong *data_as_long; - - meta_error_trap_push_with_return (display); - type = None; - data = NULL; - result = XGetWindowProperty (display->xdisplay, - xwindow, - display->atom__NET_WM_ICON, - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, &data); - err = meta_error_trap_pop_with_return (display, TRUE); - - if (err != Success || - result != Success) - return FALSE; - - if (type != XA_CARDINAL) - { - XFree (data); - return FALSE; - } - - data_as_long = (gulong *)data; - - if (!find_best_size (data_as_long, nitems, - ideal_width, ideal_height, - &w, &h, &best)) - { - XFree (data); - return FALSE; - } - - if (!find_best_size (data_as_long, nitems, - ideal_mini_width, ideal_mini_height, - &mini_w, &mini_h, &best_mini)) - { - XFree (data); - return FALSE; - } - - *width = w; - *height = h; - - *mini_width = mini_w; - *mini_height = mini_h; - - argbdata_to_pixdata (best, w * h, pixdata); - argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata); - - XFree (data); - - return TRUE; -} - -static void -free_pixels (guchar *pixels, gpointer data) -{ - g_free (pixels); -} - -static void -get_pixmap_geometry (MetaDisplay *display, - Pixmap pixmap, - int *w, - int *h, - int *d) -{ - Window root_ignored; - int x_ignored, y_ignored; - guint width, height; - guint border_width_ignored; - guint depth; - - if (w) - *w = 1; - if (h) - *h = 1; - if (d) - *d = 1; - - XGetGeometry (display->xdisplay, - pixmap, &root_ignored, &x_ignored, &y_ignored, - &width, &height, &border_width_ignored, &depth); - - if (w) - *w = width; - if (h) - *h = height; - if (d) - *d = depth; -} - -static GdkPixbuf* -apply_mask (GdkPixbuf *pixbuf, - GdkPixbuf *mask) -{ - int w, h; - int i, j; - GdkPixbuf *with_alpha; - guchar *src; - guchar *dest; - int src_stride; - int dest_stride; - - w = MIN (gdk_pixbuf_get_width (mask), gdk_pixbuf_get_width (pixbuf)); - h = MIN (gdk_pixbuf_get_height (mask), gdk_pixbuf_get_height (pixbuf)); - - with_alpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); - - dest = gdk_pixbuf_get_pixels (with_alpha); - src = gdk_pixbuf_get_pixels (mask); - - dest_stride = gdk_pixbuf_get_rowstride (with_alpha); - src_stride = gdk_pixbuf_get_rowstride (mask); - - i = 0; - while (i < h) - { - j = 0; - while (j < w) - { - guchar *s = src + i * src_stride + j * 3; - guchar *d = dest + i * dest_stride + j * 4; - - /* s[0] == s[1] == s[2], they are 255 if the bit was set, 0 - * otherwise - */ - if (s[0] == 0) - d[3] = 0; /* transparent */ - else - d[3] = 255; /* opaque */ - - ++j; - } - - ++i; - } - - return with_alpha; -} - -static gboolean -try_pixmap_and_mask (MetaDisplay *display, - Pixmap src_pixmap, - Pixmap src_mask, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - GdkPixbuf *unscaled = NULL; - GdkPixbuf *mask = NULL; - int w, h; - - if (src_pixmap == None) - return FALSE; - - meta_error_trap_push (display); - - get_pixmap_geometry (display, src_pixmap, &w, &h, NULL); - - unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL, - src_pixmap, - 0, 0, 0, 0, - w, h); - - if (unscaled && src_mask != None) - { - get_pixmap_geometry (display, src_mask, &w, &h, NULL); - mask = meta_gdk_pixbuf_get_from_pixmap (NULL, - src_mask, - 0, 0, 0, 0, - w, h); - } - - meta_error_trap_pop (display, FALSE); - - if (mask) - { - GdkPixbuf *masked; - - masked = apply_mask (unscaled, mask); - g_object_unref (G_OBJECT (unscaled)); - unscaled = masked; - - g_object_unref (G_OBJECT (mask)); - mask = NULL; - } - - if (unscaled) - { - *iconp = - gdk_pixbuf_scale_simple (unscaled, - ideal_width > 0 ? ideal_width : - gdk_pixbuf_get_width (unscaled), - ideal_height > 0 ? ideal_height : - gdk_pixbuf_get_height (unscaled), - GDK_INTERP_BILINEAR); - *mini_iconp = - gdk_pixbuf_scale_simple (unscaled, - ideal_mini_width > 0 ? ideal_mini_width : - gdk_pixbuf_get_width (unscaled), - ideal_mini_height > 0 ? ideal_mini_height : - gdk_pixbuf_get_height (unscaled), - GDK_INTERP_BILINEAR); - - g_object_unref (G_OBJECT (unscaled)); - - if (*iconp && *mini_iconp) - return TRUE; - else - { - if (*iconp) - g_object_unref (G_OBJECT (*iconp)); - if (*mini_iconp) - g_object_unref (G_OBJECT (*mini_iconp)); - return FALSE; - } - } - else - return FALSE; -} - -static void -get_kwm_win_icon (MetaDisplay *display, - Window xwindow, - Pixmap *pixmap, - Pixmap *mask) -{ - Atom type; - int format; - gulong nitems; - gulong bytes_after; - guchar *data; - Pixmap *icons; - int err, result; - - *pixmap = None; - *mask = None; - - meta_error_trap_push_with_return (display); - icons = NULL; - result = XGetWindowProperty (display->xdisplay, xwindow, - display->atom__KWM_WIN_ICON, - 0, G_MAXLONG, - False, - display->atom__KWM_WIN_ICON, - &type, &format, &nitems, - &bytes_after, &data); - icons = (Pixmap *)data; - - err = meta_error_trap_pop_with_return (display, TRUE); - if (err != Success || - result != Success) - return; - - if (type != display->atom__KWM_WIN_ICON) - { - XFree (icons); - return; - } - - *pixmap = icons[0]; - *mask = icons[1]; - - XFree (icons); - - return; -} - -void -meta_icon_cache_init (MetaIconCache *icon_cache) -{ - g_return_if_fail (icon_cache != NULL); - - icon_cache->origin = USING_NO_ICON; - icon_cache->prev_pixmap = None; - icon_cache->prev_mask = None; -#if 0 - icon_cache->icon = NULL; - icon_cache->mini_icon = NULL; - icon_cache->ideal_width = -1; /* won't be a legit width */ - icon_cache->ideal_height = -1; - icon_cache->ideal_mini_width = -1; - icon_cache->ideal_mini_height = -1; -#endif - icon_cache->want_fallback = TRUE; - icon_cache->wm_hints_dirty = TRUE; - icon_cache->kwm_win_icon_dirty = TRUE; - icon_cache->net_wm_icon_dirty = TRUE; -} - -static void -clear_icon_cache (MetaIconCache *icon_cache, - gboolean dirty_all) -{ -#if 0 - if (icon_cache->icon) - g_object_unref (G_OBJECT (icon_cache->icon)); - icon_cache->icon = NULL; - - if (icon_cache->mini_icon) - g_object_unref (G_OBJECT (icon_cache->mini_icon)); - icon_cache->mini_icon = NULL; -#endif - - icon_cache->origin = USING_NO_ICON; - - if (dirty_all) - { - icon_cache->wm_hints_dirty = TRUE; - icon_cache->kwm_win_icon_dirty = TRUE; - icon_cache->net_wm_icon_dirty = TRUE; - } -} - -void -meta_icon_cache_free (MetaIconCache *icon_cache) -{ - clear_icon_cache (icon_cache, FALSE); -} - -void -meta_icon_cache_property_changed (MetaIconCache *icon_cache, - MetaDisplay *display, - Atom atom) -{ - if (atom == display->atom__NET_WM_ICON) - icon_cache->net_wm_icon_dirty = TRUE; - else if (atom == display->atom__KWM_WIN_ICON) - icon_cache->kwm_win_icon_dirty = TRUE; - else if (atom == XA_WM_HINTS) - icon_cache->wm_hints_dirty = TRUE; -} - -gboolean -meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache) -{ - if (icon_cache->origin <= USING_KWM_WIN_ICON && - icon_cache->kwm_win_icon_dirty) - return TRUE; - else if (icon_cache->origin <= USING_WM_HINTS && - icon_cache->wm_hints_dirty) - return TRUE; - else if (icon_cache->origin <= USING_NET_WM_ICON && - icon_cache->net_wm_icon_dirty) - return TRUE; - else if (icon_cache->origin < USING_FALLBACK_ICON && - icon_cache->want_fallback) - return TRUE; - else if (icon_cache->origin == USING_NO_ICON) - return TRUE; - else if (icon_cache->origin == USING_FALLBACK_ICON && - !icon_cache->want_fallback) - return TRUE; - else - return FALSE; -} - -static void -replace_cache (MetaIconCache *icon_cache, - IconOrigin origin, - GdkPixbuf *new_icon, - GdkPixbuf *new_mini_icon) -{ - clear_icon_cache (icon_cache, FALSE); - - icon_cache->origin = origin; - -#if 0 - if (new_icon) - g_object_ref (G_OBJECT (new_icon)); - - icon_cache->icon = new_icon; - - if (new_mini_icon) - g_object_ref (G_OBJECT (new_mini_icon)); - - icon_cache->mini_icon = new_mini_icon; -#endif -} - -static GdkPixbuf* -scaled_from_pixdata (guchar *pixdata, - int w, - int h, - int new_w, - int new_h) -{ - GdkPixbuf *src; - GdkPixbuf *dest; - - src = gdk_pixbuf_new_from_data (pixdata, - GDK_COLORSPACE_RGB, - TRUE, - 8, - w, h, w * 4, - free_pixels, - NULL); - - if (src == NULL) - return NULL; - - if (w != h) - { - GdkPixbuf *tmp; - int size; - - size = MAX (w, h); - - tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size); - - if (tmp) - { - gdk_pixbuf_fill (tmp, 0); - gdk_pixbuf_copy_area (src, 0, 0, w, h, - tmp, - (size - w) / 2, (size - h) / 2); - - g_object_unref (src); - src = tmp; - } - } - - if (w != new_w || h != new_h) - { - dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR); - - g_object_unref (G_OBJECT (src)); - } - else - { - dest = src; - } - - return dest; -} - -gboolean -meta_read_icons (MetaScreen *screen, - Window xwindow, - MetaIconCache *icon_cache, - Pixmap wm_hints_pixmap, - Pixmap wm_hints_mask, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - guchar *pixdata; - int w, h; - guchar *mini_pixdata; - int mini_w, mini_h; - Pixmap pixmap; - Pixmap mask; - - /* Return value is whether the icon changed */ - - g_return_val_if_fail (icon_cache != NULL, FALSE); - - *iconp = NULL; - *mini_iconp = NULL; - -#if 0 - if (ideal_width != icon_cache->ideal_width || - ideal_height != icon_cache->ideal_height || - ideal_mini_width != icon_cache->ideal_mini_width || - ideal_mini_height != icon_cache->ideal_mini_height) - clear_icon_cache (icon_cache, TRUE); - - icon_cache->ideal_width = ideal_width; - icon_cache->ideal_height = ideal_height; - icon_cache->ideal_mini_width = ideal_mini_width; - icon_cache->ideal_mini_height = ideal_mini_height; -#endif - - if (!meta_icon_cache_get_icon_invalidated (icon_cache)) - return FALSE; /* we have no new info to use */ - - pixdata = NULL; - - /* Our algorithm here assumes that we can't have for example origin - * < USING_NET_WM_ICON and icon_cache->net_wm_icon_dirty == FALSE - * unless we have tried to read NET_WM_ICON. - * - * Put another way, if an icon origin is not dirty, then we have - * tried to read it at the current size. If it is dirty, then - * we haven't done that since the last change. - */ - - if (icon_cache->origin <= USING_NET_WM_ICON && - icon_cache->net_wm_icon_dirty) - - { - icon_cache->net_wm_icon_dirty = FALSE; - - if (read_rgb_icon (screen->display, xwindow, - ideal_width, ideal_height, - ideal_mini_width, ideal_mini_height, - &w, &h, &pixdata, - &mini_w, &mini_h, &mini_pixdata)) - { - *iconp = scaled_from_pixdata (pixdata, w, h, - ideal_width, ideal_height); - - *mini_iconp = scaled_from_pixdata (mini_pixdata, mini_w, mini_h, - ideal_mini_width, ideal_mini_height); - - if (*iconp && *mini_iconp) - { - replace_cache (icon_cache, USING_NET_WM_ICON, - *iconp, *mini_iconp); - - return TRUE; - } - else - { - if (*iconp) - g_object_unref (G_OBJECT (*iconp)); - if (*mini_iconp) - g_object_unref (G_OBJECT (*mini_iconp)); - } - } - } - - if (icon_cache->origin <= USING_WM_HINTS && - icon_cache->wm_hints_dirty) - { - icon_cache->wm_hints_dirty = FALSE; - - pixmap = wm_hints_pixmap; - mask = wm_hints_mask; - - /* We won't update if pixmap is unchanged; - * avoids a get_from_drawable() on every geometry - * hints change - */ - if ((pixmap != icon_cache->prev_pixmap || - mask != icon_cache->prev_mask) && - pixmap != None) - { - if (try_pixmap_and_mask (screen->display, - pixmap, mask, - iconp, ideal_width, ideal_height, - mini_iconp, ideal_mini_width, ideal_mini_height)) - { - icon_cache->prev_pixmap = pixmap; - icon_cache->prev_mask = mask; - - replace_cache (icon_cache, USING_WM_HINTS, - *iconp, *mini_iconp); - - return TRUE; - } - } - } - - if (icon_cache->origin <= USING_KWM_WIN_ICON && - icon_cache->kwm_win_icon_dirty) - { - icon_cache->kwm_win_icon_dirty = FALSE; - - get_kwm_win_icon (screen->display, xwindow, &pixmap, &mask); - - if ((pixmap != icon_cache->prev_pixmap || - mask != icon_cache->prev_mask) && - pixmap != None) - { - if (try_pixmap_and_mask (screen->display, pixmap, mask, - iconp, ideal_width, ideal_height, - mini_iconp, ideal_mini_width, ideal_mini_height)) - { - icon_cache->prev_pixmap = pixmap; - icon_cache->prev_mask = mask; - - replace_cache (icon_cache, USING_KWM_WIN_ICON, - *iconp, *mini_iconp); - - return TRUE; - } - } - } - - if (icon_cache->want_fallback && - icon_cache->origin < USING_FALLBACK_ICON) - { - get_fallback_icons (screen, - iconp, - ideal_width, - ideal_height, - mini_iconp, - ideal_mini_width, - ideal_mini_height); - - replace_cache (icon_cache, USING_FALLBACK_ICON, - *iconp, *mini_iconp); - - return TRUE; - } - - if (!icon_cache->want_fallback && - icon_cache->origin == USING_FALLBACK_ICON) - { - /* Get rid of current icon */ - clear_icon_cache (icon_cache, FALSE); - - return TRUE; - } - - /* found nothing new */ - return FALSE; -} |