mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
half-ass implementation of getting pixmap icons (WM_NORMAL_HINTS and
2001-08-22 Havoc Pennington <hp@pobox.com> * src/window.c (update_icon): half-ass implementation of getting pixmap icons (WM_NORMAL_HINTS and KWM_WIN_ICON). Ignores mask for now, with possibly ugly results for some apps. (read_rgb_icon): fixage
This commit is contained in:
parent
f562e65d5f
commit
e51c12d1cd
@ -1,3 +1,11 @@
|
||||
2001-08-22 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (update_icon): half-ass implementation of
|
||||
getting pixmap icons (WM_NORMAL_HINTS and KWM_WIN_ICON).
|
||||
Ignores mask for now, with possibly ugly results for
|
||||
some apps.
|
||||
(read_rgb_icon): fixage
|
||||
|
||||
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c: add a "fullscreen" semantic type; if a window
|
||||
|
@ -133,7 +133,8 @@ meta_display_open (const char *name)
|
||||
"_NET_WM_ICON",
|
||||
"_NET_WM_ICON_GEOMETRY",
|
||||
"UTF8_STRING",
|
||||
"WM_ICON_SIZE"
|
||||
"WM_ICON_SIZE",
|
||||
"_KWM_WIN_ICON"
|
||||
};
|
||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||
|
||||
@ -218,6 +219,7 @@ meta_display_open (const char *name)
|
||||
display->atom_net_wm_icon_geometry = atoms[38];
|
||||
display->atom_utf8_string = atoms[39];
|
||||
display->atom_wm_icon_size = atoms[40];
|
||||
display->atom_kwm_win_icon = atoms[41];
|
||||
|
||||
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
||||
* created in screen_new
|
||||
|
@ -98,6 +98,7 @@ struct _MetaDisplay
|
||||
Atom atom_net_wm_icon_geometry;
|
||||
Atom atom_utf8_string;
|
||||
Atom atom_wm_icon_size;
|
||||
Atom atom_kwm_win_icon;
|
||||
|
||||
/* This is the actual window from focus events,
|
||||
* not the one we last set
|
||||
|
221
src/window.c
221
src/window.c
@ -61,6 +61,7 @@ static int update_initial_workspace (MetaWindow *window);
|
||||
static int update_icon_name (MetaWindow *window);
|
||||
static int update_icon (MetaWindow *window,
|
||||
gboolean reread_rgb_icon);
|
||||
static int update_kwm_icon (MetaWindow *window);
|
||||
static void recalc_window_type (MetaWindow *window);
|
||||
static void recalc_window_features (MetaWindow *window);
|
||||
static int set_wm_state (MetaWindow *window,
|
||||
@ -319,6 +320,9 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
||||
window->icon_pixmap = None;
|
||||
window->icon_mask = None;
|
||||
|
||||
window->kwm_pixmap = None;
|
||||
window->kwm_mask = None;
|
||||
|
||||
window->using_rgb_icon = FALSE;
|
||||
|
||||
window->type = META_WINDOW_NORMAL;
|
||||
@ -342,7 +346,8 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
||||
update_net_wm_type (window);
|
||||
update_initial_workspace (window);
|
||||
update_icon_name (window);
|
||||
/* should come after wm_hints */
|
||||
update_kwm_icon (window);
|
||||
/* should come after wm_hints and kwm_icon updates */
|
||||
update_icon (window, TRUE);
|
||||
|
||||
if (!window->mapped &&
|
||||
@ -2335,6 +2340,7 @@ process_property_notify (MetaWindow *window,
|
||||
meta_verbose ("Property notify on %s for WM_HINTS\n", window->desc);
|
||||
|
||||
update_wm_hints (window);
|
||||
update_icon (window, FALSE);
|
||||
|
||||
meta_window_queue_move_resize (window);
|
||||
}
|
||||
@ -2400,6 +2406,12 @@ process_property_notify (MetaWindow *window,
|
||||
meta_verbose ("Property notify on %s for NET_WM_ICON\n", window->desc);
|
||||
update_icon (window, TRUE);
|
||||
}
|
||||
else if (event->atom == window->display->atom_kwm_win_icon)
|
||||
{
|
||||
meta_verbose ("Property notify on %s for KWM_WIN_ICON\n", window->desc);
|
||||
update_kwm_icon (window);
|
||||
update_icon (window, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -2786,9 +2798,9 @@ update_wm_hints (MetaWindow *window)
|
||||
update_icon (window, FALSE);
|
||||
}
|
||||
|
||||
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%ld\n",
|
||||
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx icon: 0x%lx\n",
|
||||
window->input, window->initially_iconic,
|
||||
window->xgroup_leader);
|
||||
window->xgroup_leader, window->icon_pixmap);
|
||||
|
||||
XFree (hints);
|
||||
}
|
||||
@ -3522,7 +3534,7 @@ update_icon_name (MetaWindow *window)
|
||||
|
||||
static gboolean
|
||||
find_best_size (gulong *data,
|
||||
gulong nitems,
|
||||
int nitems,
|
||||
int *width,
|
||||
int *height,
|
||||
gulong **start)
|
||||
@ -3531,6 +3543,10 @@ find_best_size (gulong *data,
|
||||
int best_h;
|
||||
gulong *best_start;
|
||||
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
*start = NULL;
|
||||
|
||||
best_w = 0;
|
||||
best_h = 0;
|
||||
best_start = NULL;
|
||||
@ -3540,6 +3556,8 @@ find_best_size (gulong *data,
|
||||
int w, h;
|
||||
gboolean replace;
|
||||
|
||||
meta_debug_spew ("n_items = %d\n", nitems);
|
||||
|
||||
replace = FALSE;
|
||||
|
||||
if (nitems < 3)
|
||||
@ -3551,10 +3569,12 @@ find_best_size (gulong *data,
|
||||
w = data[0];
|
||||
h = data[1];
|
||||
|
||||
meta_debug_spew ("w = %d h = %d\n", w, h);
|
||||
|
||||
if (nitems < ((w * h) + 2))
|
||||
{
|
||||
meta_verbose ("_NET_WM_ICON contained too little data\n");
|
||||
return FALSE;
|
||||
meta_verbose ("_NET_WM_ICON contained too little data?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (best_start == NULL)
|
||||
@ -3592,6 +3612,7 @@ find_best_size (gulong *data,
|
||||
best_h = h;
|
||||
}
|
||||
|
||||
data += (w * h) + 2;
|
||||
nitems -= (w * h) + 2;
|
||||
}
|
||||
|
||||
@ -3655,7 +3676,7 @@ read_rgb_icon (MetaWindow *window,
|
||||
*width = w;
|
||||
*height = h;
|
||||
|
||||
*pixdata = g_new (guchar, w * h);
|
||||
*pixdata = g_new (guchar, w * h * 4);
|
||||
p = *pixdata;
|
||||
|
||||
/* One could speed this up a lot. */
|
||||
@ -3666,7 +3687,7 @@ read_rgb_icon (MetaWindow *window,
|
||||
guint rgba;
|
||||
|
||||
argb = best[i];
|
||||
rgba = (argb << 8) & (argb >> 24);
|
||||
rgba = (argb << 8) | (argb >> 24);
|
||||
|
||||
*p = rgba >> 24;
|
||||
++p;
|
||||
@ -3701,6 +3722,60 @@ free_pixels (guchar *pixels, gpointer data)
|
||||
g_free (pixels);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_icon (MetaWindow *window,
|
||||
GdkPixbuf *unscaled)
|
||||
{
|
||||
if (gdk_pixbuf_get_width (unscaled) != META_ICON_WIDTH ||
|
||||
gdk_pixbuf_get_height (unscaled) != META_ICON_HEIGHT)
|
||||
{
|
||||
/* FIXME should keep aspect ratio, but for now assuming
|
||||
* a square source icon
|
||||
*/
|
||||
window->icon = gdk_pixbuf_scale_simple (unscaled,
|
||||
META_ICON_WIDTH,
|
||||
META_ICON_HEIGHT,
|
||||
GDK_INTERP_BILINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_ref (G_OBJECT (unscaled));
|
||||
window->icon = unscaled;
|
||||
}
|
||||
}
|
||||
|
||||
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 int
|
||||
update_icon (MetaWindow *window,
|
||||
gboolean reload_rgb_icon)
|
||||
@ -3717,36 +3792,21 @@ update_icon (MetaWindow *window,
|
||||
{
|
||||
GdkPixbuf *unscaled;
|
||||
|
||||
meta_verbose ("successfully read RGBA icon fro _NET_WM_ICON\n");
|
||||
meta_verbose ("successfully read RGBA icon from _NET_WM_ICON, using w = %d h = %d\n", w, h);
|
||||
|
||||
window->using_rgb_icon = TRUE;
|
||||
|
||||
clear_icon (window);
|
||||
|
||||
unscaled = gdk_pixbuf_new_from_data (pixdata,
|
||||
GDK_COLORSPACE_RGB,
|
||||
TRUE,
|
||||
8,
|
||||
w, h, w,
|
||||
w, h, w * 4,
|
||||
free_pixels,
|
||||
NULL);
|
||||
|
||||
if (w != META_ICON_WIDTH || h != META_ICON_HEIGHT)
|
||||
{
|
||||
/* FIXME should keep aspect ratio, but for now assuming
|
||||
* a square source icon
|
||||
*/
|
||||
window->icon = gdk_pixbuf_scale_simple (unscaled,
|
||||
META_ICON_WIDTH,
|
||||
META_ICON_HEIGHT,
|
||||
GDK_INTERP_BILINEAR);
|
||||
replace_icon (window, unscaled);
|
||||
|
||||
g_object_unref (G_OBJECT (unscaled));
|
||||
}
|
||||
else
|
||||
{
|
||||
window->icon = unscaled;
|
||||
}
|
||||
g_object_unref (G_OBJECT (unscaled));
|
||||
|
||||
return Success;
|
||||
}
|
||||
@ -3768,12 +3828,68 @@ update_icon (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* Fallback to pixmap + mask */
|
||||
/* FIXME well, I'm not sure how to deal with the mask */
|
||||
/* FIXME for that matter, I don't know how we get the
|
||||
* icon pixmap as pixbuf without knowing if it's a bitmap,
|
||||
* so we may be entirely hosed. I guess we can try to get it
|
||||
* with a nice error trap.
|
||||
*/
|
||||
|
||||
if (window->icon_pixmap != None)
|
||||
{
|
||||
GdkPixbuf *unscaled;
|
||||
int w, h;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
|
||||
get_pixmap_geometry (window->display, window->icon_pixmap,
|
||||
&w, &h, NULL);
|
||||
|
||||
/* FIXME get mask and copy it to alpha channel of pixmap */
|
||||
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
|
||||
window->icon_pixmap,
|
||||
0, 0, 0, 0,
|
||||
w, h);
|
||||
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
if (unscaled)
|
||||
{
|
||||
meta_verbose ("Used pixmap icon\n");
|
||||
replace_icon (window, unscaled);
|
||||
return Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Failed to get pixmap icon as pixbuf\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (window->kwm_pixmap != None)
|
||||
{
|
||||
GdkPixbuf *unscaled;
|
||||
int w, h;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
|
||||
get_pixmap_geometry (window->display, window->kwm_pixmap,
|
||||
&w, &h, NULL);
|
||||
|
||||
/* FIXME get mask and copy it to alpha channel of pixmap */
|
||||
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
|
||||
window->kwm_pixmap,
|
||||
0, 0, 0, 0,
|
||||
w, h);
|
||||
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
if (unscaled)
|
||||
{
|
||||
meta_verbose ("Used kwm icon\n");
|
||||
replace_icon (window, unscaled);
|
||||
return Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Failed to get kwm icon as pixbuf\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback to a default icon */
|
||||
if (window->icon == NULL)
|
||||
@ -3782,6 +3898,45 @@ update_icon (MetaWindow *window,
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
update_kwm_icon (MetaWindow *window)
|
||||
{
|
||||
Atom type;
|
||||
int format;
|
||||
gulong nitems;
|
||||
gulong bytes_after;
|
||||
Pixmap *icons;
|
||||
int result;
|
||||
|
||||
window->kwm_pixmap = None;
|
||||
window->kwm_mask = None;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
icons = NULL;
|
||||
XGetWindowProperty (window->display->xdisplay, window->xwindow,
|
||||
window->display->atom_kwm_win_icon,
|
||||
0, G_MAXLONG,
|
||||
False, window->display->atom_kwm_win_icon,
|
||||
&type, &format, &nitems,
|
||||
&bytes_after, (guchar **)&icons);
|
||||
|
||||
result = meta_error_trap_pop (window->display);
|
||||
if (result != Success)
|
||||
return None;
|
||||
|
||||
if (type != window->display->atom_kwm_win_icon)
|
||||
return None;
|
||||
|
||||
window->kwm_pixmap = icons[0];
|
||||
window->kwm_mask = icons[1];
|
||||
|
||||
meta_verbose ("Found KWM_WIN_ICON 0x%lx\n", window->kwm_pixmap);
|
||||
|
||||
XFree (icons);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void
|
||||
recalc_window_type (MetaWindow *window)
|
||||
{
|
||||
|
@ -77,6 +77,12 @@ struct _MetaWindow
|
||||
Pixmap icon_pixmap;
|
||||
Pixmap icon_mask;
|
||||
|
||||
/* these are legacy and should die once we have _NET_WM_ICON in
|
||||
* most apps
|
||||
*/
|
||||
Pixmap kwm_pixmap;
|
||||
Pixmap kwm_mask;
|
||||
|
||||
/* Whether ->icon is from NET_WM_ICON instead of pixmap */
|
||||
guint using_rgb_icon : 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user