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