x11: Change the iconcache / window icons to being cairo surfaces
This simplifies the drawing codepath and makes us able to delete a bunch of GdkPixbuf manipulation.
This commit is contained in:
parent
f3d30d897f
commit
af7f51b992
@ -120,7 +120,7 @@ meta_core_get (Display *xdisplay,
|
||||
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
|
||||
break;
|
||||
case META_CORE_GET_MINI_ICON:
|
||||
*((GdkPixbuf**)answer) = window->mini_icon;
|
||||
*((cairo_surface_t**)answer) = window->mini_icon;
|
||||
break;
|
||||
case META_CORE_GET_FRAME_RECT:
|
||||
meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
|
||||
|
@ -106,8 +106,8 @@ struct _MetaWindow
|
||||
char *desc; /* used in debug spew */
|
||||
char *title;
|
||||
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
cairo_surface_t *icon;
|
||||
cairo_surface_t *mini_icon;
|
||||
|
||||
MetaWindowType type;
|
||||
|
||||
@ -479,9 +479,9 @@ struct _MetaWindowClass
|
||||
void (*get_default_skip_hints) (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
gboolean *skip_pager_out);
|
||||
gboolean (*update_icon) (MetaWindow *window,
|
||||
GdkPixbuf **icon,
|
||||
GdkPixbuf **mini_icon);
|
||||
gboolean (*update_icon) (MetaWindow *window,
|
||||
cairo_surface_t **icon,
|
||||
cairo_surface_t **mini_icon);
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
|
@ -244,9 +244,9 @@ meta_window_real_get_default_skip_hints (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_window_real_update_icon (MetaWindow *window,
|
||||
GdkPixbuf **icon,
|
||||
GdkPixbuf **mini_icon)
|
||||
meta_window_real_update_icon (MetaWindow *window,
|
||||
cairo_surface_t **icon,
|
||||
cairo_surface_t **mini_icon)
|
||||
{
|
||||
*icon = NULL;
|
||||
*mini_icon = NULL;
|
||||
@ -259,10 +259,10 @@ meta_window_finalize (GObject *object)
|
||||
MetaWindow *window = META_WINDOW (object);
|
||||
|
||||
if (window->icon)
|
||||
g_object_unref (G_OBJECT (window->icon));
|
||||
cairo_surface_destroy (window->icon);
|
||||
|
||||
if (window->mini_icon)
|
||||
g_object_unref (G_OBJECT (window->mini_icon));
|
||||
cairo_surface_destroy (window->mini_icon);
|
||||
|
||||
if (window->frame_bounds)
|
||||
cairo_region_destroy (window->frame_bounds);
|
||||
@ -4890,10 +4890,11 @@ redraw_icon (MetaWindow *window)
|
||||
meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
static cairo_surface_t *
|
||||
load_default_window_icon (int size)
|
||||
{
|
||||
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||
GdkPixbuf *pixbuf;
|
||||
const char *icon_name;
|
||||
|
||||
if (gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME))
|
||||
@ -4901,13 +4902,14 @@ load_default_window_icon (int size)
|
||||
else
|
||||
icon_name = "image-missing";
|
||||
|
||||
return gtk_icon_theme_load_icon (theme, icon_name, size, 0, NULL);
|
||||
pixbuf = gtk_icon_theme_load_icon (theme, icon_name, size, 0, NULL);
|
||||
return gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
static cairo_surface_t *
|
||||
get_default_window_icon (void)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
static cairo_surface_t *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
@ -4915,13 +4917,13 @@ get_default_window_icon (void)
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
return g_object_ref (default_icon);
|
||||
return cairo_surface_reference (default_icon);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
static cairo_surface_t *
|
||||
get_default_mini_icon (void)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
static cairo_surface_t *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
@ -4929,7 +4931,7 @@ get_default_mini_icon (void)
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
return g_object_ref (default_icon);
|
||||
return cairo_surface_reference (default_icon);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4937,8 +4939,8 @@ meta_window_update_icon_now (MetaWindow *window,
|
||||
gboolean force)
|
||||
{
|
||||
gboolean changed;
|
||||
GdkPixbuf *icon = NULL;
|
||||
GdkPixbuf *mini_icon;
|
||||
cairo_surface_t *icon = NULL;
|
||||
cairo_surface_t *mini_icon;
|
||||
|
||||
g_return_if_fail (!window->override_redirect);
|
||||
|
||||
@ -4947,14 +4949,14 @@ meta_window_update_icon_now (MetaWindow *window,
|
||||
if (changed || force)
|
||||
{
|
||||
if (window->icon)
|
||||
g_object_unref (window->icon);
|
||||
cairo_surface_destroy (window->icon);
|
||||
if (icon)
|
||||
window->icon = icon;
|
||||
else
|
||||
window->icon = get_default_window_icon ();
|
||||
|
||||
if (window->mini_icon)
|
||||
g_object_unref (window->mini_icon);
|
||||
cairo_surface_destroy (window->mini_icon);
|
||||
if (mini_icon)
|
||||
window->mini_icon = mini_icon;
|
||||
else
|
||||
|
@ -1673,7 +1673,7 @@ meta_frames_paint (MetaFrames *frames,
|
||||
{
|
||||
MetaFrameFlags flags;
|
||||
MetaFrameType type;
|
||||
GdkPixbuf *mini_icon;
|
||||
cairo_surface_t *mini_icon;
|
||||
int w, h;
|
||||
MetaButtonState button_states[META_BUTTON_TYPE_LAST];
|
||||
int i;
|
||||
|
@ -265,7 +265,7 @@ void meta_theme_draw_frame (MetaTheme *theme,
|
||||
int text_height,
|
||||
const MetaButtonLayout *button_layout,
|
||||
MetaButtonState button_states[META_BUTTON_TYPE_LAST],
|
||||
GdkPixbuf *mini_icon);
|
||||
cairo_surface_t *mini_icon);
|
||||
|
||||
void meta_theme_get_frame_borders (MetaTheme *theme,
|
||||
MetaStyleInfo *style_info,
|
||||
|
@ -725,7 +725,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
|
||||
PangoLayout *title_layout,
|
||||
MetaFrameFlags flags,
|
||||
MetaButtonState button_states[META_BUTTON_TYPE_LAST],
|
||||
GdkPixbuf *mini_icon)
|
||||
cairo_surface_t *mini_icon)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GtkStateFlags state;
|
||||
@ -810,7 +810,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
|
||||
|
||||
if (gdk_cairo_get_clip_rectangle (cr, NULL))
|
||||
{
|
||||
GdkPixbuf *pixbuf = NULL;
|
||||
cairo_surface_t *surface = NULL;
|
||||
const char *icon_name = NULL;
|
||||
|
||||
gtk_render_background (style, cr,
|
||||
@ -838,7 +838,7 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
|
||||
icon_name = "open-menu-symbolic";
|
||||
break;
|
||||
case META_BUTTON_TYPE_APPMENU:
|
||||
pixbuf = g_object_ref (mini_icon);
|
||||
surface = cairo_surface_reference (mini_icon);
|
||||
break;
|
||||
default:
|
||||
icon_name = NULL;
|
||||
@ -849,18 +849,20 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
|
||||
{
|
||||
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||
GtkIconInfo *info;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
info = gtk_icon_theme_lookup_icon (theme, icon_name, layout->icon_size, 0);
|
||||
pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, NULL, NULL);
|
||||
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
|
||||
}
|
||||
|
||||
if (pixbuf)
|
||||
if (surface)
|
||||
{
|
||||
float width, height;
|
||||
int x, y;
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
width = cairo_image_surface_get_width (surface);
|
||||
height = cairo_image_surface_get_height (surface);
|
||||
x = button_rect.x + (button_rect.width - width) / 2;
|
||||
y = button_rect.y + (button_rect.height - height) / 2;
|
||||
|
||||
@ -868,11 +870,10 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
|
||||
cairo_scale (cr,
|
||||
width / layout->icon_size,
|
||||
height / layout->icon_size);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
}
|
||||
cairo_restore (cr);
|
||||
@ -1180,7 +1181,7 @@ meta_theme_draw_frame (MetaTheme *theme,
|
||||
int text_height,
|
||||
const MetaButtonLayout *button_layout,
|
||||
MetaButtonState button_states[META_BUTTON_TYPE_LAST],
|
||||
GdkPixbuf *mini_icon)
|
||||
cairo_surface_t *mini_icon)
|
||||
{
|
||||
MetaFrameGeometry fgeom;
|
||||
MetaFrameLayout *layout;
|
||||
|
50
src/ui/ui.c
50
src/ui/ui.c
@ -500,56 +500,6 @@ meta_ui_set_frame_title (MetaUI *ui,
|
||||
meta_frames_set_title (ui->frames, xwindow, title);
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
Display *display;
|
||||
Window root_return;
|
||||
int x_ret, y_ret;
|
||||
unsigned int w_ret, h_ret, bw_ret, depth_ret;
|
||||
XWindowAttributes attrs;
|
||||
GdkPixbuf *retval;
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
if (!XGetGeometry (display, xpixmap, &root_return,
|
||||
&x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
|
||||
return NULL;
|
||||
|
||||
if (depth_ret == 1)
|
||||
{
|
||||
surface = cairo_xlib_surface_create_for_bitmap (display,
|
||||
xpixmap,
|
||||
GDK_SCREEN_XSCREEN (gdk_screen_get_default ()),
|
||||
w_ret,
|
||||
h_ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!XGetWindowAttributes (display, root_return, &attrs))
|
||||
return NULL;
|
||||
|
||||
surface = cairo_xlib_surface_create (display,
|
||||
xpixmap,
|
||||
attrs.visual,
|
||||
w_ret, h_ret);
|
||||
}
|
||||
|
||||
retval = gdk_pixbuf_get_from_surface (surface,
|
||||
src_x,
|
||||
src_y,
|
||||
width,
|
||||
height);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow)
|
||||
|
@ -101,13 +101,6 @@ void meta_ui_repaint_frame (MetaUI *ui,
|
||||
Window xwindow);
|
||||
|
||||
|
||||
/* FIXME these lack a display arg */
|
||||
GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow);
|
||||
|
||||
|
@ -19,14 +19,16 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "iconcache.h"
|
||||
#include "ui.h"
|
||||
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo-xlib.h>
|
||||
|
||||
/* The icon-reading code is also in libwnck, please sync bugfixes */
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
static gboolean
|
||||
find_largest_sizes (gulong *data,
|
||||
@ -156,51 +158,40 @@ find_best_size (gulong *data,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata)
|
||||
static cairo_surface_t *
|
||||
argbdata_to_surface (gulong *argb_data, int w, int h)
|
||||
{
|
||||
guchar *p;
|
||||
int i;
|
||||
cairo_surface_t *surface;
|
||||
int y, x, stride;
|
||||
uint8_t *data;
|
||||
|
||||
*pixdata = g_new (guchar, len * 4);
|
||||
p = *pixdata;
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
|
||||
stride = cairo_image_surface_get_stride (surface);
|
||||
data = cairo_image_surface_get_data (surface);
|
||||
|
||||
/* One could speed this up a lot. */
|
||||
i = 0;
|
||||
while (i < len)
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
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;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
uint32_t *p = (uint32_t *) &data[y * stride + x];
|
||||
gulong *d = &argb_data[y * w + x];
|
||||
*p = *d;
|
||||
}
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
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)
|
||||
read_rgb_icon (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
int ideal_width,
|
||||
int ideal_height,
|
||||
int ideal_mini_width,
|
||||
int ideal_mini_height,
|
||||
cairo_surface_t **icon,
|
||||
cairo_surface_t **mini_icon)
|
||||
{
|
||||
Atom type;
|
||||
int format;
|
||||
@ -253,26 +244,14 @@ read_rgb_icon (MetaDisplay *display,
|
||||
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);
|
||||
*icon = argbdata_to_surface (best, w, h);
|
||||
*mini_icon = argbdata_to_surface (best_mini, mini_w, mini_h);
|
||||
|
||||
XFree (data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pixels (guchar *pixels, gpointer data)
|
||||
{
|
||||
g_free (pixels);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixmap_geometry (MetaDisplay *display,
|
||||
Pixmap pixmap,
|
||||
@ -305,96 +284,44 @@ get_pixmap_geometry (MetaDisplay *display,
|
||||
*d = depth;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_foreground_background (GdkPixbuf *pixbuf)
|
||||
static cairo_surface_t *
|
||||
surface_from_pixmap (Display *xdisplay, Pixmap xpixmap,
|
||||
int width, int height)
|
||||
{
|
||||
int w, h;
|
||||
int i, j;
|
||||
guchar *pixels;
|
||||
int stride;
|
||||
cairo_surface_t *surface;
|
||||
Window root_return;
|
||||
int x_ret, y_ret;
|
||||
unsigned int w_ret, h_ret, bw_ret, depth_ret;
|
||||
XWindowAttributes attrs;
|
||||
|
||||
w = gdk_pixbuf_get_width (pixbuf);
|
||||
h = gdk_pixbuf_get_height (pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
stride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
if (!XGetGeometry (xdisplay, xpixmap, &root_return,
|
||||
&x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < h)
|
||||
if (depth_ret == 1)
|
||||
{
|
||||
j = 0;
|
||||
while (j < w)
|
||||
{
|
||||
guchar *p = pixels + i * stride + j * 4;
|
||||
if (p[3] == 0)
|
||||
p[0] = p[1] = p[2] = 0xff; /* white background */
|
||||
else
|
||||
p[0] = p[1] = p[2] = 0x00; /* black foreground */
|
||||
|
||||
p[3] = 0xff;
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
++i;
|
||||
surface = cairo_xlib_surface_create_for_bitmap (xdisplay, xpixmap, DefaultScreenOfDisplay (xdisplay),
|
||||
w_ret, h_ret);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
else
|
||||
{
|
||||
j = 0;
|
||||
while (j < w)
|
||||
{
|
||||
guchar *s = src + i * src_stride + j * 4;
|
||||
guchar *d = dest + i * dest_stride + j * 4;
|
||||
if (!XGetWindowAttributes (xdisplay, root_return, &attrs))
|
||||
return NULL;
|
||||
|
||||
d[3] = s[3];
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
++i;
|
||||
surface = cairo_xlib_surface_create (xdisplay, xpixmap, attrs.visual, w_ret, h_ret);
|
||||
}
|
||||
|
||||
return with_alpha;
|
||||
return surface;
|
||||
}
|
||||
|
||||
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)
|
||||
try_pixmap_and_mask (MetaDisplay *display,
|
||||
Pixmap src_pixmap,
|
||||
Pixmap src_mask,
|
||||
cairo_surface_t **iconp)
|
||||
{
|
||||
GdkPixbuf *unscaled = NULL;
|
||||
GdkPixbuf *mask = NULL;
|
||||
Display *xdisplay = display->xdisplay;
|
||||
cairo_surface_t *icon, *mask = NULL;
|
||||
int w, h, d;
|
||||
|
||||
if (src_pixmap == None)
|
||||
@ -403,72 +330,48 @@ try_pixmap_and_mask (MetaDisplay *display,
|
||||
meta_error_trap_push (display);
|
||||
|
||||
get_pixmap_geometry (display, src_pixmap, &w, &h, &d);
|
||||
icon = surface_from_pixmap (xdisplay, src_pixmap, w, h);
|
||||
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
|
||||
0, 0,
|
||||
w, h);
|
||||
|
||||
/* A depth 1 pixmap has 0 background, and 1 foreground, but
|
||||
* cairo and meta_gdk_pixbuf_get_from_pixmap consider it
|
||||
* to be 0 transparent, 1 opaque */
|
||||
if (d == 1)
|
||||
apply_foreground_background (unscaled);
|
||||
|
||||
if (unscaled && src_mask != None)
|
||||
if (icon && src_mask != None)
|
||||
{
|
||||
get_pixmap_geometry (display, src_mask, &w, &h, &d);
|
||||
|
||||
if (d == 1)
|
||||
mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
|
||||
0, 0,
|
||||
w, h);
|
||||
mask = surface_from_pixmap (xdisplay, src_mask, w, h);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (mask)
|
||||
if (icon && mask)
|
||||
{
|
||||
GdkPixbuf *masked;
|
||||
cairo_surface_t *masked;
|
||||
cairo_t *cr;
|
||||
|
||||
masked = apply_mask (unscaled, mask);
|
||||
g_object_unref (G_OBJECT (unscaled));
|
||||
unscaled = masked;
|
||||
masked = cairo_surface_create_similar_image (icon,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
cairo_image_surface_get_width (icon),
|
||||
cairo_image_surface_get_height (icon));
|
||||
cr = cairo_create (masked);
|
||||
|
||||
g_object_unref (G_OBJECT (mask));
|
||||
mask = NULL;
|
||||
cairo_set_source_surface (cr, icon, 0, 0);
|
||||
cairo_mask_surface (cr, mask, 0, 0);
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (icon);
|
||||
cairo_surface_destroy (mask);
|
||||
|
||||
icon = masked;
|
||||
}
|
||||
|
||||
if (unscaled)
|
||||
if (icon)
|
||||
{
|
||||
*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;
|
||||
}
|
||||
*iconp = icon;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -562,74 +465,18 @@ meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
meta_read_icons (MetaScreen *screen,
|
||||
Window xwindow,
|
||||
MetaIconCache *icon_cache,
|
||||
Pixmap wm_hints_pixmap,
|
||||
Pixmap wm_hints_mask,
|
||||
cairo_surface_t **iconp,
|
||||
int ideal_width,
|
||||
int ideal_height,
|
||||
cairo_surface_t **mini_iconp,
|
||||
int ideal_mini_width,
|
||||
int ideal_mini_height)
|
||||
{
|
||||
/* Return value is whether the icon changed */
|
||||
|
||||
@ -653,37 +500,15 @@ meta_read_icons (MetaScreen *screen,
|
||||
if (icon_cache->origin <= USING_NET_WM_ICON &&
|
||||
icon_cache->net_wm_icon_dirty)
|
||||
{
|
||||
guchar *pixdata;
|
||||
int w, h;
|
||||
guchar *mini_pixdata;
|
||||
int mini_w, mini_h;
|
||||
|
||||
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, mini_iconp))
|
||||
{
|
||||
*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)
|
||||
{
|
||||
icon_cache->origin = USING_NET_WM_ICON;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*iconp)
|
||||
g_object_unref (G_OBJECT (*iconp));
|
||||
if (*mini_iconp)
|
||||
g_object_unref (G_OBJECT (*mini_iconp));
|
||||
}
|
||||
icon_cache->origin = USING_NET_WM_ICON;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,11 +531,9 @@ meta_read_icons (MetaScreen *screen,
|
||||
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))
|
||||
if (try_pixmap_and_mask (screen->display, pixmap, mask, iconp))
|
||||
{
|
||||
*mini_iconp = cairo_surface_reference (*iconp);
|
||||
icon_cache->prev_pixmap = pixmap;
|
||||
icon_cache->prev_mask = mask;
|
||||
icon_cache->origin = USING_WM_HINTS;
|
||||
@ -733,10 +556,9 @@ meta_read_icons (MetaScreen *screen,
|
||||
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))
|
||||
if (try_pixmap_and_mask (screen->display, pixmap, mask, iconp))
|
||||
{
|
||||
*mini_iconp = cairo_surface_reference (*iconp);
|
||||
icon_cache->prev_pixmap = pixmap;
|
||||
icon_cache->prev_mask = mask;
|
||||
icon_cache->origin = USING_KWM_WIN_ICON;
|
||||
|
@ -56,17 +56,17 @@ void meta_icon_cache_property_changed (MetaIconCache *icon_cache,
|
||||
Atom atom);
|
||||
gboolean meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache);
|
||||
|
||||
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);
|
||||
gboolean meta_read_icons (MetaScreen *screen,
|
||||
Window xwindow,
|
||||
MetaIconCache *icon_cache,
|
||||
Pixmap wm_hints_pixmap,
|
||||
Pixmap wm_hints_mask,
|
||||
cairo_surface_t **iconp,
|
||||
int ideal_width,
|
||||
int ideal_height,
|
||||
cairo_surface_t **mini_iconp,
|
||||
int ideal_mini_width,
|
||||
int ideal_mini_height);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1459,9 +1459,9 @@ meta_window_x11_get_default_skip_hints (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_window_x11_update_icon (MetaWindow *window,
|
||||
GdkPixbuf **icon,
|
||||
GdkPixbuf **mini_icon)
|
||||
meta_window_x11_update_icon (MetaWindow *window,
|
||||
cairo_surface_t **icon,
|
||||
cairo_surface_t **mini_icon)
|
||||
{
|
||||
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
|
||||
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
|
||||
|
Loading…
Reference in New Issue
Block a user