mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
we support _NET_WM_ICON
2001-08-19 Havoc Pennington <hp@pobox.com> * src/screen.c (set_supported_hint): we support _NET_WM_ICON * src/wm-tester/main.c: add stuff to test _NET_WM_ICON (but it doesn't work, so it isn't tested yet) * src/window.c (update_icon): read _NET_WM_ICON * src/screen.c (meta_screen_new): set the WM_ICON_SIZE hint * src/tabpopup.c (meta_ui_tab_popup_select): remove assertion * src/window.c (meta_window_get_icon_geometry): fix obscure memleak
This commit is contained in:
parent
78a68f3e10
commit
04e09d4c56
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
|||||||
|
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
|
* src/screen.c (set_supported_hint): we support _NET_WM_ICON
|
||||||
|
|
||||||
|
* src/wm-tester/main.c: add stuff to test _NET_WM_ICON
|
||||||
|
(but it doesn't work, so it isn't tested yet)
|
||||||
|
|
||||||
|
* src/window.c (update_icon): read _NET_WM_ICON
|
||||||
|
|
||||||
|
* src/screen.c (meta_screen_new): set the WM_ICON_SIZE hint
|
||||||
|
|
||||||
|
* src/tabpopup.c (meta_ui_tab_popup_select): remove assertion
|
||||||
|
|
||||||
|
* src/window.c (meta_window_get_icon_geometry): fix obscure
|
||||||
|
memleak
|
||||||
|
|
||||||
2001-08-19 Havoc Pennington <hp@pobox.com>
|
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
* src/display.c (meta_display_grab_window_buttons): remove XSync,
|
* src/display.c (meta_display_grab_window_buttons): remove XSync,
|
||||||
|
@ -132,7 +132,8 @@ meta_display_open (const char *name)
|
|||||||
"_NET_WM_ICON_NAME",
|
"_NET_WM_ICON_NAME",
|
||||||
"_NET_WM_ICON",
|
"_NET_WM_ICON",
|
||||||
"_NET_WM_ICON_GEOMETRY",
|
"_NET_WM_ICON_GEOMETRY",
|
||||||
"UTF8_STRING"
|
"UTF8_STRING",
|
||||||
|
"WM_ICON_SIZE"
|
||||||
};
|
};
|
||||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||||
|
|
||||||
@ -216,6 +217,7 @@ meta_display_open (const char *name)
|
|||||||
display->atom_net_wm_icon = atoms[37];
|
display->atom_net_wm_icon = atoms[37];
|
||||||
display->atom_net_wm_icon_geometry = atoms[38];
|
display->atom_net_wm_icon_geometry = atoms[38];
|
||||||
display->atom_utf8_string = atoms[39];
|
display->atom_utf8_string = atoms[39];
|
||||||
|
display->atom_wm_icon_size = atoms[40];
|
||||||
|
|
||||||
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
||||||
* created in screen_new
|
* created in screen_new
|
||||||
|
@ -97,6 +97,7 @@ struct _MetaDisplay
|
|||||||
Atom atom_net_wm_icon;
|
Atom atom_net_wm_icon;
|
||||||
Atom atom_net_wm_icon_geometry;
|
Atom atom_net_wm_icon_geometry;
|
||||||
Atom atom_utf8_string;
|
Atom atom_utf8_string;
|
||||||
|
Atom atom_wm_icon_size;
|
||||||
|
|
||||||
/* This is the actual window from focus events,
|
/* This is the actual window from focus events,
|
||||||
* not the one we last set
|
* not the one we last set
|
||||||
|
@ -22,6 +22,10 @@ if test -n "$EVIL_TEST"; then
|
|||||||
TEST_CLIENT='./wm-tester/wm-tester --evil'
|
TEST_CLIENT='./wm-tester/wm-tester --evil'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test -n "$ICON_TEST"; then
|
||||||
|
TEST_CLIENT='./wm-tester/wm-tester --icon-windows'
|
||||||
|
fi
|
||||||
|
|
||||||
if test -z "$ONLY_WM"; then
|
if test -z "$ONLY_WM"; then
|
||||||
Xnest -ac :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
|
Xnest -ac :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
|
||||||
## usleep 800000
|
## usleep 800000
|
||||||
|
28
src/screen.c
28
src/screen.c
@ -72,7 +72,7 @@ set_wm_check_hint (MetaScreen *screen)
|
|||||||
static int
|
static int
|
||||||
set_supported_hint (MetaScreen *screen)
|
set_supported_hint (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
#define N_SUPPORTED 21
|
#define N_SUPPORTED 22
|
||||||
#define N_WIN_SUPPORTED 1
|
#define N_WIN_SUPPORTED 1
|
||||||
Atom atoms[N_SUPPORTED];
|
Atom atoms[N_SUPPORTED];
|
||||||
|
|
||||||
@ -97,6 +97,7 @@ set_supported_hint (MetaScreen *screen)
|
|||||||
atoms[18] = screen->display->atom_net_client_list_stacking;
|
atoms[18] = screen->display->atom_net_client_list_stacking;
|
||||||
atoms[19] = screen->display->atom_net_wm_state_skip_taskbar;
|
atoms[19] = screen->display->atom_net_wm_state_skip_taskbar;
|
||||||
atoms[20] = screen->display->atom_net_wm_state_skip_pager;
|
atoms[20] = screen->display->atom_net_wm_state_skip_pager;
|
||||||
|
atoms[21] = screen->display->atom_net_wm_icon;
|
||||||
|
|
||||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||||
screen->display->atom_net_wm_supported,
|
screen->display->atom_net_wm_supported,
|
||||||
@ -115,6 +116,29 @@ set_supported_hint (MetaScreen *screen)
|
|||||||
#undef N_SUPPORTED
|
#undef N_SUPPORTED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_wm_icon_size_hint (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
#define N_VALS 6
|
||||||
|
gulong vals[N_VALS];
|
||||||
|
|
||||||
|
/* min width, min height, max w, max h, width inc, height inc */
|
||||||
|
vals[0] = META_ICON_WIDTH;
|
||||||
|
vals[1] = META_ICON_HEIGHT;
|
||||||
|
vals[2] = META_ICON_WIDTH;
|
||||||
|
vals[3] = META_ICON_HEIGHT;
|
||||||
|
vals[4] = 0;
|
||||||
|
vals[5] = 0;
|
||||||
|
|
||||||
|
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||||
|
screen->display->atom_wm_icon_size,
|
||||||
|
XA_CARDINAL,
|
||||||
|
32, PropModeReplace, (guchar*) vals, N_VALS);
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
#undef N_VALS
|
||||||
|
}
|
||||||
|
|
||||||
MetaScreen*
|
MetaScreen*
|
||||||
meta_screen_new (MetaDisplay *display,
|
meta_screen_new (MetaDisplay *display,
|
||||||
int number)
|
int number)
|
||||||
@ -178,6 +202,8 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->xroot,
|
screen->xroot,
|
||||||
-100, -100, 1, 1, 0, 0, 0);
|
-100, -100, 1, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
set_wm_icon_size_hint (screen);
|
||||||
|
|
||||||
set_supported_hint (screen);
|
set_supported_hint (screen);
|
||||||
|
|
||||||
set_wm_check_hint (screen);
|
set_wm_check_hint (screen);
|
||||||
|
@ -26,6 +26,11 @@
|
|||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* should investigate changing these to whatever most apps use */
|
||||||
|
#define META_ICON_WIDTH 32
|
||||||
|
#define META_ICON_HEIGHT 32
|
||||||
|
|
||||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
@ -287,6 +287,4 @@ meta_ui_tab_popup_select (MetaTabPopup *popup,
|
|||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_bug ("Selected nonexistent entry 0x%lx in tab popup\n", xwindow);
|
|
||||||
}
|
}
|
||||||
|
35
src/ui.c
35
src/ui.c
@ -333,6 +333,41 @@ meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest,
|
||||||
|
Pixmap xpixmap,
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dest_x,
|
||||||
|
int dest_y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
GdkDrawable *drawable;
|
||||||
|
GdkPixbuf *retval;
|
||||||
|
|
||||||
|
retval = NULL;
|
||||||
|
|
||||||
|
drawable = gdk_xid_table_lookup (xpixmap);
|
||||||
|
|
||||||
|
if (drawable)
|
||||||
|
g_object_ref (G_OBJECT (drawable));
|
||||||
|
else
|
||||||
|
drawable = gdk_pixmap_foreign_new (xpixmap);
|
||||||
|
|
||||||
|
retval = gdk_pixbuf_get_from_drawable (dest,
|
||||||
|
drawable,
|
||||||
|
/* We assume root window cmap */
|
||||||
|
gdk_colormap_get_system (),
|
||||||
|
src_x, src_y,
|
||||||
|
dest_x, dest_y,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
g_object_unref (G_OBJECT (drawable));
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_ui_push_delay_exposes (MetaUI *ui)
|
meta_ui_push_delay_exposes (MetaUI *ui)
|
||||||
{
|
{
|
||||||
|
9
src/ui.h
9
src/ui.h
@ -110,6 +110,15 @@ GdkPixbuf* meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
|
|||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
|
|
||||||
|
GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest,
|
||||||
|
Pixmap xpixmap,
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dest_x,
|
||||||
|
int dest_y,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
/* Used when we have a server grab and draw all over everything,
|
/* Used when we have a server grab and draw all over everything,
|
||||||
* then we need to handle exposes after doing that, instead of
|
* then we need to handle exposes after doing that, instead of
|
||||||
* during it
|
* during it
|
||||||
|
290
src/window.c
290
src/window.c
@ -59,7 +59,8 @@ static int update_role (MetaWindow *window);
|
|||||||
static int update_net_wm_type (MetaWindow *window);
|
static int update_net_wm_type (MetaWindow *window);
|
||||||
static int update_initial_workspace (MetaWindow *window);
|
static int update_initial_workspace (MetaWindow *window);
|
||||||
static int update_icon_name (MetaWindow *window);
|
static int update_icon_name (MetaWindow *window);
|
||||||
static int update_icon (MetaWindow *window);
|
static int update_icon (MetaWindow *window,
|
||||||
|
gboolean reread_rgb_icon);
|
||||||
static void recalc_window_type (MetaWindow *window);
|
static void recalc_window_type (MetaWindow *window);
|
||||||
static void recalc_window_features (MetaWindow *window);
|
static void recalc_window_features (MetaWindow *window);
|
||||||
static int set_wm_state (MetaWindow *window,
|
static int set_wm_state (MetaWindow *window,
|
||||||
@ -318,6 +319,8 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
|||||||
window->icon_pixmap = None;
|
window->icon_pixmap = None;
|
||||||
window->icon_mask = None;
|
window->icon_mask = None;
|
||||||
|
|
||||||
|
window->using_rgb_icon = FALSE;
|
||||||
|
|
||||||
window->type = META_WINDOW_NORMAL;
|
window->type = META_WINDOW_NORMAL;
|
||||||
window->type_atom = None;
|
window->type_atom = None;
|
||||||
|
|
||||||
@ -339,7 +342,8 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
|||||||
update_net_wm_type (window);
|
update_net_wm_type (window);
|
||||||
update_initial_workspace (window);
|
update_initial_workspace (window);
|
||||||
update_icon_name (window);
|
update_icon_name (window);
|
||||||
update_icon (window);
|
/* should come after wm_hints */
|
||||||
|
update_icon (window, TRUE);
|
||||||
|
|
||||||
if (!window->mapped &&
|
if (!window->mapped &&
|
||||||
(window->size_hints.flags & PPosition) == 0 &&
|
(window->size_hints.flags & PPosition) == 0 &&
|
||||||
@ -2331,7 +2335,6 @@ process_property_notify (MetaWindow *window,
|
|||||||
meta_verbose ("Property notify on %s for WM_HINTS\n", window->desc);
|
meta_verbose ("Property notify on %s for WM_HINTS\n", window->desc);
|
||||||
|
|
||||||
update_wm_hints (window);
|
update_wm_hints (window);
|
||||||
update_icon (window);
|
|
||||||
|
|
||||||
meta_window_queue_move_resize (window);
|
meta_window_queue_move_resize (window);
|
||||||
}
|
}
|
||||||
@ -2395,7 +2398,7 @@ process_property_notify (MetaWindow *window,
|
|||||||
else if (event->atom == window->display->atom_net_wm_icon)
|
else if (event->atom == window->display->atom_net_wm_icon)
|
||||||
{
|
{
|
||||||
meta_verbose ("Property notify on %s for NET_WM_ICON\n", window->desc);
|
meta_verbose ("Property notify on %s for NET_WM_ICON\n", window->desc);
|
||||||
update_icon (window);
|
update_icon (window, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -2742,6 +2745,11 @@ static int
|
|||||||
update_wm_hints (MetaWindow *window)
|
update_wm_hints (MetaWindow *window)
|
||||||
{
|
{
|
||||||
XWMHints *hints;
|
XWMHints *hints;
|
||||||
|
Pixmap old_icon;
|
||||||
|
Pixmap old_mask;
|
||||||
|
|
||||||
|
old_icon = window->icon_pixmap;
|
||||||
|
old_mask = window->icon_mask;
|
||||||
|
|
||||||
/* Fill in defaults */
|
/* Fill in defaults */
|
||||||
window->input = FALSE;
|
window->input = FALSE;
|
||||||
@ -2770,6 +2778,14 @@ update_wm_hints (MetaWindow *window)
|
|||||||
if (hints->flags & IconMaskHint)
|
if (hints->flags & IconMaskHint)
|
||||||
window->icon_mask = hints->icon_mask;
|
window->icon_mask = hints->icon_mask;
|
||||||
|
|
||||||
|
if (window->icon_pixmap != old_icon ||
|
||||||
|
window->icon_mask != old_mask)
|
||||||
|
{
|
||||||
|
meta_verbose ("Icon pixmap or mask changed in WM_HINTS for %s\n",
|
||||||
|
window->desc);
|
||||||
|
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%ld\n",
|
||||||
window->input, window->initially_iconic,
|
window->input, window->initially_iconic,
|
||||||
window->xgroup_leader);
|
window->xgroup_leader);
|
||||||
@ -3025,9 +3041,15 @@ meta_window_get_icon_geometry (MetaWindow *window,
|
|||||||
|
|
||||||
result = meta_error_trap_pop (window->display);
|
result = meta_error_trap_pop (window->display);
|
||||||
|
|
||||||
if (result != Success || type != XA_CARDINAL || nitems != 4)
|
if (result != Success || type != XA_CARDINAL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (nitems != 4)
|
||||||
|
{
|
||||||
|
XFree (geometry);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (rect)
|
if (rect)
|
||||||
{
|
{
|
||||||
rect->x = geometry[0];
|
rect->x = geometry[0];
|
||||||
@ -3442,7 +3464,7 @@ update_icon_name (MetaWindow *window)
|
|||||||
text.format == 8 &&
|
text.format == 8 &&
|
||||||
g_utf8_validate (text.value, text.nitems, NULL))
|
g_utf8_validate (text.value, text.nitems, NULL))
|
||||||
{
|
{
|
||||||
meta_verbose ("Using _NET_WM_ICON_NAME for new title of %s: '%s'\n",
|
meta_verbose ("Using _NET_WM_ICON_NAME for new icon name of %s: '%s'\n",
|
||||||
window->desc, text.value);
|
window->desc, text.value);
|
||||||
|
|
||||||
window->icon_name = g_strdup (text.value);
|
window->icon_name = g_strdup (text.value);
|
||||||
@ -3498,26 +3520,266 @@ update_icon_name (MetaWindow *window)
|
|||||||
return meta_error_trap_pop (window->display);
|
return meta_error_trap_pop (window->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static gboolean
|
||||||
update_icon (MetaWindow *window)
|
find_best_size (gulong *data,
|
||||||
|
gulong nitems,
|
||||||
|
int *width,
|
||||||
|
int *height,
|
||||||
|
gulong **start)
|
||||||
{
|
{
|
||||||
meta_error_trap_push (window->display);
|
int best_w;
|
||||||
|
int best_h;
|
||||||
|
gulong *best_start;
|
||||||
|
|
||||||
#if 0
|
best_w = 0;
|
||||||
|
best_h = 0;
|
||||||
|
best_start = NULL;
|
||||||
|
|
||||||
|
while (nitems > 0)
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
gboolean replace;
|
||||||
|
|
||||||
|
replace = FALSE;
|
||||||
|
|
||||||
|
if (nitems < 3)
|
||||||
|
{
|
||||||
|
meta_verbose ("_NET_WM_ICON contained too little data\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = data[0];
|
||||||
|
h = data[1];
|
||||||
|
|
||||||
|
if (nitems < ((w * h) + 2))
|
||||||
|
{
|
||||||
|
meta_verbose ("_NET_WM_ICON contained too little data\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best_start == NULL)
|
||||||
|
{
|
||||||
|
replace = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* work with averages */
|
||||||
|
const int ideal_size = META_ICON_WIDTH * META_ICON_HEIGHT;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
nitems -= (w * h) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best_start)
|
||||||
|
{
|
||||||
|
*start = best_start;
|
||||||
|
*width = best_w;
|
||||||
|
*height = best_h;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
read_rgb_icon (MetaWindow *window,
|
||||||
|
int *width,
|
||||||
|
int *height,
|
||||||
|
guchar **pixdata)
|
||||||
|
{
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
gulong nitems;
|
||||||
|
gulong bytes_after;
|
||||||
|
int result;
|
||||||
|
gulong *data; /* FIXME should be guint? */
|
||||||
|
gulong *best;
|
||||||
|
int i;
|
||||||
|
int w, h;
|
||||||
|
guchar *p;
|
||||||
|
|
||||||
|
if (sizeof (gulong) != 4)
|
||||||
|
meta_warning ("%s: Whoops, I think this function may be broken on 64-bit\n",
|
||||||
|
__FUNCTION__);
|
||||||
|
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
type = None;
|
||||||
|
data = NULL;
|
||||||
|
XGetWindowProperty (window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
window->display->atom_net_wm_icon,
|
||||||
|
0, G_MAXLONG,
|
||||||
|
False, XA_CARDINAL, &type, &format, &nitems,
|
||||||
|
&bytes_after, ((guchar **)&data));
|
||||||
|
|
||||||
|
result = meta_error_trap_pop (window->display);
|
||||||
|
|
||||||
|
if (result != Success || type != XA_CARDINAL)
|
||||||
|
{
|
||||||
|
meta_verbose ("%s doesn't seem to set _NET_WM_ICON\n",
|
||||||
|
window->desc);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!find_best_size (data, nitems, &w, &h, &best))
|
||||||
|
{
|
||||||
|
XFree (data);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*width = w;
|
||||||
|
*height = h;
|
||||||
|
|
||||||
|
*pixdata = g_new (guchar, w * h);
|
||||||
|
p = *pixdata;
|
||||||
|
|
||||||
|
/* One could speed this up a lot. */
|
||||||
|
i = 0;
|
||||||
|
while (i < w * h)
|
||||||
|
{
|
||||||
|
guint argb;
|
||||||
|
guint rgba;
|
||||||
|
|
||||||
|
argb = best[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;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree (data);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_icon (MetaWindow *window)
|
||||||
|
{
|
||||||
if (window->icon)
|
if (window->icon)
|
||||||
{
|
{
|
||||||
g_object_unref (G_OBJECT (window->icon));
|
g_object_unref (G_OBJECT (window->icon));
|
||||||
window->icon = NULL;
|
window->icon = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
/* FIXME */
|
static void
|
||||||
|
free_pixels (guchar *pixels, gpointer data)
|
||||||
|
{
|
||||||
|
g_free (pixels);
|
||||||
|
}
|
||||||
|
|
||||||
/* Fallback */
|
static int
|
||||||
|
update_icon (MetaWindow *window,
|
||||||
|
gboolean reload_rgb_icon)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (reload_rgb_icon)
|
||||||
|
{
|
||||||
|
guchar *pixdata;
|
||||||
|
int w, h;
|
||||||
|
|
||||||
|
pixdata = NULL;
|
||||||
|
|
||||||
|
if (read_rgb_icon (window, &w, &h, &pixdata))
|
||||||
|
{
|
||||||
|
GdkPixbuf *unscaled;
|
||||||
|
|
||||||
|
meta_verbose ("successfully read RGBA icon fro _NET_WM_ICON\n");
|
||||||
|
|
||||||
|
window->using_rgb_icon = TRUE;
|
||||||
|
|
||||||
|
clear_icon (window);
|
||||||
|
|
||||||
|
unscaled = gdk_pixbuf_new_from_data (pixdata,
|
||||||
|
GDK_COLORSPACE_RGB,
|
||||||
|
TRUE,
|
||||||
|
8,
|
||||||
|
w, h, w,
|
||||||
|
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);
|
||||||
|
|
||||||
|
g_object_unref (G_OBJECT (unscaled));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->icon = unscaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (window->using_rgb_icon)
|
||||||
|
clear_icon (window);
|
||||||
|
window->using_rgb_icon = FALSE;
|
||||||
|
|
||||||
|
/* We'll try to fall back to something else below. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (window->using_rgb_icon)
|
||||||
|
{
|
||||||
|
/* There's no way we want to use the fallbacks,
|
||||||
|
* keep using this.
|
||||||
|
*/
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Fallback to a default icon */
|
||||||
if (window->icon == NULL)
|
if (window->icon == NULL)
|
||||||
window->icon = meta_ui_get_default_window_icon (window->screen->ui);
|
window->icon = meta_ui_get_default_window_icon (window->screen->ui);
|
||||||
|
|
||||||
return meta_error_trap_pop (window->display);
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -70,11 +70,14 @@ struct _MetaWindow
|
|||||||
Window xgroup_leader;
|
Window xgroup_leader;
|
||||||
Window xclient_leader;
|
Window xclient_leader;
|
||||||
|
|
||||||
|
/* Initial workspace property */
|
||||||
|
int initial_workspace;
|
||||||
|
|
||||||
Pixmap icon_pixmap;
|
Pixmap icon_pixmap;
|
||||||
Pixmap icon_mask;
|
Pixmap icon_mask;
|
||||||
|
|
||||||
/* Initial workspace property */
|
/* Whether ->icon is from NET_WM_ICON instead of pixmap */
|
||||||
int initial_workspace;
|
guint using_rgb_icon : 1;
|
||||||
|
|
||||||
/* Whether we're maximized */
|
/* Whether we're maximized */
|
||||||
guint maximized : 1;
|
guint maximized : 1;
|
||||||
|
@ -28,11 +28,12 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static void set_up_the_evil (void);
|
static void set_up_the_evil (void);
|
||||||
|
static void set_up_icon_windows (void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage (void)
|
usage (void)
|
||||||
{
|
{
|
||||||
g_print ("wm-tester [--evil]\n");
|
g_print ("wm-tester [--evil] [--icon-windows]\n");
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,10 +42,12 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gboolean do_evil;
|
gboolean do_evil;
|
||||||
|
gboolean do_icon_windows;
|
||||||
|
|
||||||
gtk_init (&argc, &argv);
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
do_evil = FALSE;
|
do_evil = FALSE;
|
||||||
|
do_icon_windows = FALSE;
|
||||||
|
|
||||||
i = 1;
|
i = 1;
|
||||||
while (i < argc)
|
while (i < argc)
|
||||||
@ -57,6 +60,8 @@ main (int argc, char **argv)
|
|||||||
usage ();
|
usage ();
|
||||||
else if (strcmp (arg, "--evil") == 0)
|
else if (strcmp (arg, "--evil") == 0)
|
||||||
do_evil = TRUE;
|
do_evil = TRUE;
|
||||||
|
else if (strcmp (arg, "--icon-windows") == 0)
|
||||||
|
do_icon_windows = TRUE;
|
||||||
else
|
else
|
||||||
usage ();
|
usage ();
|
||||||
|
|
||||||
@ -64,12 +69,15 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Be sure some option was provided */
|
/* Be sure some option was provided */
|
||||||
if (! (do_evil))
|
if (! (do_evil || do_icon_windows))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (do_evil)
|
if (do_evil)
|
||||||
set_up_the_evil ();
|
set_up_the_evil ();
|
||||||
|
|
||||||
|
if (do_icon_windows)
|
||||||
|
set_up_icon_windows ();
|
||||||
|
|
||||||
gtk_main ();
|
gtk_main ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -156,3 +164,64 @@ set_up_the_evil (void)
|
|||||||
g_timeout_add (40, evil_timeout, NULL);
|
g_timeout_add (40, evil_timeout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_up_icon_windows (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n_windows;
|
||||||
|
|
||||||
|
/* Create some windows */
|
||||||
|
n_windows = 9;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < n_windows)
|
||||||
|
{
|
||||||
|
GtkWidget *w;
|
||||||
|
GtkWidget *c;
|
||||||
|
GList *icons;
|
||||||
|
GdkPixbuf *pix;
|
||||||
|
|
||||||
|
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||||
|
c = gtk_button_new_with_label ("Icon window");
|
||||||
|
gtk_container_add (GTK_CONTAINER (w), c);
|
||||||
|
|
||||||
|
gtk_widget_realize (w);
|
||||||
|
|
||||||
|
icons = NULL;
|
||||||
|
|
||||||
|
pix = gtk_widget_render_icon (w,
|
||||||
|
GTK_STOCK_SAVE,
|
||||||
|
GTK_ICON_SIZE_LARGE_TOOLBAR,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
icons = g_list_append (icons, pix);
|
||||||
|
|
||||||
|
if (i % 2)
|
||||||
|
{
|
||||||
|
pix = gtk_widget_render_icon (w,
|
||||||
|
GTK_STOCK_SAVE,
|
||||||
|
GTK_ICON_SIZE_DIALOG,
|
||||||
|
NULL);
|
||||||
|
icons = g_list_append (icons, pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i % 3)
|
||||||
|
{
|
||||||
|
pix = gtk_widget_render_icon (w,
|
||||||
|
GTK_STOCK_SAVE,
|
||||||
|
GTK_ICON_SIZE_MENU,
|
||||||
|
NULL);
|
||||||
|
icons = g_list_append (icons, pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gdk_window_set_icon_list (w->window, icons))
|
||||||
|
g_warning ("_NET_WM_ICON not supported?");
|
||||||
|
|
||||||
|
g_list_foreach (icons, (GFunc) g_object_unref, NULL);
|
||||||
|
g_list_free (icons);
|
||||||
|
|
||||||
|
gtk_widget_show_all (w);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user