summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--rationales.txt2
-rw-r--r--src/main.c19
-rw-r--r--src/window-props.c393
-rw-r--r--src/window.c514
-rw-r--r--src/window.h14
6 files changed, 562 insertions, 393 deletions
diff --git a/ChangeLog b/ChangeLog
index 11b8f9c5..7b74aeb3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2003-02-27 Havoc Pennington <hp@pobox.com>
+
+ * src/main.c (main): add more debug spew about conditional
+ build stuff
+ (main): panic to "Simple" theme
+
+ * src/window.c, src/window-props.c: move WM_NORMAL_HINTS and
+ WM_PROTOCOLS to new property system; don't queue move resize on
+ updating WM_PROTOCOLS; move WM_HINTS to new property system;
+ reload icon in an idle handler.
+
+ Changes made on plane from FOSDEM, syncing from laptop.
+
2003-02-28 Mark McLoughlin <mark@skynet.ie>
Give me back my keys.
diff --git a/rationales.txt b/rationales.txt
index f13b1dab..9f0de294 100644
--- a/rationales.txt
+++ b/rationales.txt
@@ -14,3 +14,5 @@ configure click actions, alt+click:
http://bugzilla.gnome.org/show_bug.cgi?id=83210
system modal dialogs: http://bugzilla.gnome.org/show_bug.cgi?id=83357
+
+workspace wrapping: http://bugzilla.gnome.org/show_bug.cgi?id=89315
diff --git a/src/main.c b/src/main.c
index f9902ff7..8ea67f57 100644
--- a/src/main.c
+++ b/src/main.c
@@ -271,6 +271,22 @@ main (int argc, char **argv)
#else
meta_topic (META_DEBUG_XINERAMA, " (not using Solaris Xinerama)\n");
#endif
+#ifdef HAVE_XSYNC
+ meta_verbose ("Compiled with sync extension\n");
+#else
+ meta_verbose ("Compiled without sync extension\n");
+#endif
+#ifdef HAVE_RANDR
+ meta_verbose ("Compiled with randr extension\n");
+#else
+ meta_verbose ("Compiled without randr extension\n");
+#endif
+#ifdef HAVE_STARTUP_NOTIFICATION
+ meta_verbose ("Compiled with startup notification\n");
+#else
+ meta_verbose ("Compiled without startup notification\n");
+#endif
+
/* Load prefs */
meta_prefs_init ();
@@ -317,6 +333,9 @@ main (int argc, char **argv)
* don't want users to lose their WM :-/
*/
if (!meta_ui_have_a_theme ())
+ meta_ui_set_current_theme ("Simple", FALSE);
+
+ if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Atlanta", FALSE);
if (!meta_ui_have_a_theme ())
diff --git a/src/window-props.c b/src/window-props.c
index c4b62552..1e334be1 100644
--- a/src/window-props.c
+++ b/src/window-props.c
@@ -1,7 +1,7 @@
/* MetaWindow property handling */
/*
- * Copyright (C) 2001, 2002 Red Hat, Inc.
+ * Copyright (C) 2001, 2002, 2003 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -23,6 +23,7 @@
#include "window-props.h"
#include "xprops.h"
#include "frame.h"
+#include "group.h"
#include <X11/Xatom.h>
typedef void (* InitValueFunc) (MetaDisplay *display,
@@ -437,7 +438,370 @@ reload_update_counter (MetaWindow *window,
}
}
-#define N_HOOKS 24
+
+static void
+init_normal_hints (MetaDisplay *display,
+ Atom property,
+ MetaPropValue *value)
+{
+ value->type = META_PROP_VALUE_SIZE_HINTS;
+ value->atom = XA_WM_NORMAL_HINTS;
+}
+
+
+#define FLAG_TOGGLED_ON(old,new,flag) \
+ (((old)->flags & (flag)) == 0 && \
+ ((new)->flags & (flag)) != 0)
+
+#define FLAG_TOGGLED_OFF(old,new,flag) \
+ (((old)->flags & (flag)) != 0 && \
+ ((new)->flags & (flag)) == 0)
+
+#define FLAG_CHANGED(old,new,flag) \
+ (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag))
+
+static void
+spew_size_hints_differences (const XSizeHints *old,
+ const XSizeHints *new)
+{
+ if (FLAG_CHANGED (old, new, USPosition))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USPosition now %s\n",
+ FLAG_TOGGLED_ON (old, new, USPosition) ? "set" : "unset");
+ if (FLAG_CHANGED (old, new, USSize))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USSize now %s\n",
+ FLAG_TOGGLED_ON (old, new, USSize) ? "set" : "unset");
+ if (FLAG_CHANGED (old, new, PPosition))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PPosition now %s\n",
+ FLAG_TOGGLED_ON (old, new, PPosition) ? "set" : "unset");
+ if (FLAG_CHANGED (old, new, PSize))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PSize now %s\n",
+ FLAG_TOGGLED_ON (old, new, PSize) ? "set" : "unset");
+ if (FLAG_CHANGED (old, new, PMinSize))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMinSize now %s (%d x %d -> %d x %d)\n",
+ FLAG_TOGGLED_ON (old, new, PMinSize) ? "set" : "unset",
+ old->min_width, old->min_height,
+ new->min_width, new->min_height);
+ if (FLAG_CHANGED (old, new, PMaxSize))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMaxSize now %s (%d x %d -> %d x %d)\n",
+ FLAG_TOGGLED_ON (old, new, PMaxSize) ? "set" : "unset",
+ old->max_width, old->max_height,
+ new->max_width, new->max_height);
+ if (FLAG_CHANGED (old, new, PResizeInc))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PResizeInc now %s (width_inc %d -> %d height_inc %d -> %d)\n",
+ FLAG_TOGGLED_ON (old, new, PResizeInc) ? "set" : "unset",
+ old->width_inc, new->width_inc,
+ old->height_inc, new->height_inc);
+ if (FLAG_CHANGED (old, new, PAspect))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PAspect now %s (min %d/%d -> %d/%d max %d/%d -> %d/%d)\n",
+ FLAG_TOGGLED_ON (old, new, PAspect) ? "set" : "unset",
+ old->min_aspect.x, old->min_aspect.y,
+ new->min_aspect.x, new->min_aspect.y,
+ old->max_aspect.x, old->max_aspect.y,
+ new->max_aspect.x, new->max_aspect.y);
+ if (FLAG_CHANGED (old, new, PBaseSize))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PBaseSize now %s (%d x %d -> %d x %d)\n",
+ FLAG_TOGGLED_ON (old, new, PBaseSize) ? "set" : "unset",
+ old->base_width, old->base_height,
+ new->base_width, new->base_height);
+ if (FLAG_CHANGED (old, new, PWinGravity))
+ meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PWinGravity now %s (%d -> %d)\n",
+ FLAG_TOGGLED_ON (old, new, PWinGravity) ? "set" : "unset",
+ old->win_gravity, new->win_gravity);
+}
+
+static void
+reload_normal_hints (MetaWindow *window,
+ MetaPropValue *value)
+{
+ if (value->type != META_PROP_VALUE_INVALID)
+ {
+ int x, y, w, h;
+ XSizeHints old_hints;
+
+ meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s\n", window->desc);
+
+ old_hints = window->size_hints;
+
+ /* Save the last ConfigureRequest, which we put here.
+ * Values here set in the hints are supposed to
+ * be ignored.
+ */
+ x = window->size_hints.x;
+ y = window->size_hints.y;
+ w = window->size_hints.width;
+ h = window->size_hints.height;
+
+ /* as far as I can tell, value->v.size_hints.flags is just to
+ * check whether we had old-style normal hints without gravity,
+ * base size as returned by XGetNormalHints(), so we don't
+ * really use it as we fixup window->size_hints to have those
+ * fields if they're missing.
+ */
+
+ window->size_hints.flags = 0; /* pointless right? why did I have this here */
+ window->size_hints = * value->v.size_hints.hints;
+
+ /* Put back saved ConfigureRequest. */
+ window->size_hints.x = x;
+ window->size_hints.y = y;
+ window->size_hints.width = w;
+ window->size_hints.height = h;
+
+ if (window->size_hints.flags & PBaseSize)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets base size %d x %d\n",
+ window->desc,
+ window->size_hints.base_width,
+ window->size_hints.base_height);
+ }
+ else if (window->size_hints.flags & PMinSize)
+ {
+ window->size_hints.base_width = window->size_hints.min_width;
+ window->size_hints.base_height = window->size_hints.min_height;
+ }
+ else
+ {
+ window->size_hints.base_width = 0;
+ window->size_hints.base_height = 0;
+ }
+ window->size_hints.flags |= PBaseSize;
+
+ if (window->size_hints.flags & PMinSize)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d\n",
+ window->desc,
+ window->size_hints.min_width,
+ window->size_hints.min_height);
+ }
+ else if (window->size_hints.flags & PBaseSize)
+ {
+ window->size_hints.min_width = window->size_hints.base_width;
+ window->size_hints.min_height = window->size_hints.base_height;
+ }
+ else
+ {
+ window->size_hints.min_width = 0;
+ window->size_hints.min_height = 0;
+ }
+ window->size_hints.flags |= PMinSize;
+
+ if (window->size_hints.flags & PMaxSize)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d\n",
+ window->desc,
+ window->size_hints.max_width,
+ window->size_hints.max_height);
+ }
+ else
+ {
+ window->size_hints.max_width = G_MAXINT;
+ window->size_hints.max_height = G_MAXINT;
+ window->size_hints.flags |= PMaxSize;
+ }
+
+ if (window->size_hints.max_width < window->size_hints.min_width)
+ {
+ /* someone is on crack */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets max width %d less than min width %d, disabling resize\n",
+ window->desc,
+ window->size_hints.max_width,
+ window->size_hints.min_width);
+ window->size_hints.max_width = window->size_hints.min_width;
+ }
+
+ if (window->size_hints.max_height < window->size_hints.min_height)
+ {
+ /* another cracksmoker */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets max height %d less than min height %d, disabling resize\n",
+ window->desc,
+ window->size_hints.max_height,
+ window->size_hints.min_height);
+ window->size_hints.max_height = window->size_hints.min_height;
+ }
+
+ if (window->size_hints.flags & PResizeInc)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets resize width inc: %d height inc: %d\n",
+ window->desc,
+ window->size_hints.width_inc,
+ window->size_hints.height_inc);
+ if (window->size_hints.width_inc == 0)
+ {
+ window->size_hints.width_inc = 1;
+ meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1\n");
+ }
+ if (window->size_hints.height_inc == 0)
+ {
+ window->size_hints.height_inc = 1;
+ meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1\n");
+ }
+ }
+ else
+ {
+ window->size_hints.width_inc = 1;
+ window->size_hints.height_inc = 1;
+ window->size_hints.flags |= PResizeInc;
+ }
+
+ if (window->size_hints.flags & PAspect)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n",
+ window->desc,
+ window->size_hints.min_aspect.x,
+ window->size_hints.min_aspect.y,
+ window->size_hints.max_aspect.x,
+ window->size_hints.max_aspect.y);
+
+ /* don't divide by 0 */
+ if (window->size_hints.min_aspect.y < 1)
+ window->size_hints.min_aspect.y = 1;
+ if (window->size_hints.max_aspect.y < 1)
+ window->size_hints.max_aspect.y = 1;
+ }
+ else
+ {
+ window->size_hints.min_aspect.x = 1;
+ window->size_hints.min_aspect.y = G_MAXINT;
+ window->size_hints.max_aspect.x = G_MAXINT;
+ window->size_hints.max_aspect.y = 1;
+ window->size_hints.flags |= PAspect;
+ }
+
+ if (window->size_hints.flags & PWinGravity)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d\n",
+ window->desc,
+ window->size_hints.win_gravity);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s doesn't set gravity, using NW\n",
+ window->desc);
+ window->size_hints.win_gravity = NorthWestGravity;
+ window->size_hints.flags |= PWinGravity;
+ }
+
+ spew_size_hints_differences (&old_hints, &window->size_hints);
+
+ meta_window_recalc_features (window);
+ }
+}
+
+
+static void
+init_wm_protocols (MetaDisplay *display,
+ Atom property,
+ MetaPropValue *value)
+{
+ value->type = META_PROP_VALUE_ATOM_LIST;
+ value->atom = display->atom_wm_protocols;
+}
+
+static void
+reload_wm_protocols (MetaWindow *window,
+ MetaPropValue *value)
+{
+ int i;
+
+ window->take_focus = FALSE;
+ window->delete_window = FALSE;
+ window->net_wm_ping = FALSE;
+
+ if (value->type == META_PROP_VALUE_INVALID)
+ return;
+
+ i = 0;
+ while (i < value->v.atom_list.n_atoms)
+ {
+ if (value->v.atom_list.atoms[i] ==
+ window->display->atom_wm_take_focus)
+ window->take_focus = TRUE;
+ else if (value->v.atom_list.atoms[i] ==
+ window->display->atom_wm_delete_window)
+ window->delete_window = TRUE;
+ else if (value->v.atom_list.atoms[i] ==
+ window->display->atom_net_wm_ping)
+ window->net_wm_ping = TRUE;
+ ++i;
+ }
+
+ meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s\n",
+ window->startup_id ? window->startup_id : "unset",
+ window->desc);
+}
+
+static void
+init_wm_hints (MetaDisplay *display,
+ Atom property,
+ MetaPropValue *value)
+{
+ value->type = META_PROP_VALUE_WM_HINTS;
+ value->atom = XA_WM_HINTS;
+}
+
+static void
+reload_wm_hints (MetaWindow *window,
+ MetaPropValue *value)
+{
+ Window old_group_leader;
+
+ old_group_leader = window->xgroup_leader;
+
+ /* Fill in defaults */
+ window->input = TRUE;
+ window->initially_iconic = FALSE;
+ window->xgroup_leader = None;
+ window->wm_hints_pixmap = None;
+ window->wm_hints_mask = None;
+
+ if (value->type != META_PROP_VALUE_INVALID)
+ {
+ const XWMHints *hints = value->v.wm_hints;
+
+ if (hints->flags & InputHint)
+ window->input = hints->input;
+
+ if (hints->flags & StateHint)
+ window->initially_iconic = (hints->initial_state == IconicState);
+
+ if (hints->flags & WindowGroupHint)
+ window->xgroup_leader = hints->window_group;
+
+ if (hints->flags & IconPixmapHint)
+ window->wm_hints_pixmap = hints->icon_pixmap;
+
+ if (hints->flags & IconMaskHint)
+ window->wm_hints_mask = hints->icon_mask;
+
+ meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
+ window->input, window->initially_iconic,
+ window->xgroup_leader,
+ window->wm_hints_pixmap,
+ window->wm_hints_mask);
+ }
+
+ if (window->xgroup_leader != old_group_leader)
+ {
+ meta_verbose ("Window %s changed its group leader to 0x%lx\n",
+ window->desc, window->xgroup_leader);
+
+ meta_window_group_leader_changed (window);
+ }
+
+ meta_icon_cache_property_changed (&window->icon_cache,
+ window->display,
+ XA_WM_HINTS);
+
+ meta_window_queue_update_icon (window);
+
+ meta_window_queue_move_resize (window);
+}
+
+
+
+#define N_HOOKS 25
void
meta_display_init_window_prop_hooks (MetaDisplay *display)
@@ -467,11 +831,6 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
hooks[i].reload_func = reload_net_wm_pid;
++i;
- hooks[i].property = XA_WM_NORMAL_HINTS;
- hooks[i].init_func = NULL;
- hooks[i].reload_func = NULL;
- ++i;
-
hooks[i].property = display->atom_net_wm_name;
hooks[i].init_func = init_net_wm_name;
hooks[i].reload_func = reload_net_wm_name;
@@ -491,11 +850,6 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
hooks[i].init_func = init_wm_icon_name;
hooks[i].reload_func = reload_wm_icon_name;
++i;
-
- hooks[i].property = XA_WM_HINTS;
- hooks[i].init_func = NULL;
- hooks[i].reload_func = NULL;
- ++i;
hooks[i].property = display->atom_net_wm_state;
hooks[i].init_func = NULL;
@@ -571,6 +925,21 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
hooks[i].init_func = init_update_counter;
hooks[i].reload_func = reload_update_counter;
++i;
+
+ hooks[i].property = XA_WM_NORMAL_HINTS;
+ hooks[i].init_func = init_normal_hints;
+ hooks[i].reload_func = reload_normal_hints;
+ ++i;
+
+ hooks[i].property = display->atom_wm_protocols;
+ hooks[i].init_func = init_wm_protocols;
+ hooks[i].reload_func = reload_wm_protocols;
+ ++i;
+
+ hooks[i].property = XA_WM_HINTS;
+ hooks[i].init_func = init_wm_hints;
+ hooks[i].reload_func = reload_wm_hints;
+ ++i;
if (i != N_HOOKS)
g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS);
diff --git a/src/window.c b/src/window.c
index 62c48c18..2c3bc862 100644
--- a/src/window.c
+++ b/src/window.c
@@ -78,9 +78,6 @@ static void constrain_position (MetaWindow *window,
int *new_x,
int *new_y);
-static void update_size_hints (MetaWindow *window);
-static void update_protocols (MetaWindow *window);
-static void update_wm_hints (MetaWindow *window);
static void update_net_wm_state (MetaWindow *window);
static void update_mwm_hints (MetaWindow *window);
static void update_wm_class (MetaWindow *window);
@@ -88,13 +85,11 @@ static void update_transient_for (MetaWindow *window);
static void update_sm_hints (MetaWindow *window);
static void update_role (MetaWindow *window);
static void update_net_wm_type (MetaWindow *window);
-static void update_icon (MetaWindow *window);
-static void redraw_icon (MetaWindow *window);
static void update_struts (MetaWindow *window);
static void recalc_window_type (MetaWindow *window);
static void recalc_window_features (MetaWindow *window);
static void recalc_do_not_cover_struts(MetaWindow *window);
-static void invalidate_work_areas (MetaWindow *window);
+static void invalidate_work_areas (MetaWindow *window);
static void set_wm_state (MetaWindow *window,
int state);
static void set_net_wm_state (MetaWindow *window);
@@ -127,12 +122,18 @@ static void meta_window_move_resize_internal (MetaWindow *window,
void meta_window_move_resize_now (MetaWindow *window);
+/* FIXME we need an abstraction that covers all these queues. */
+
void meta_window_unqueue_calc_showing (MetaWindow *window);
void meta_window_flush_calc_showing (MetaWindow *window);
void meta_window_unqueue_move_resize (MetaWindow *window);
void meta_window_flush_move_resize (MetaWindow *window);
+static void meta_window_update_icon_now (MetaWindow *window);
+void meta_window_unqueue_update_icon (MetaWindow *window);
+void meta_window_flush_update_icon (MetaWindow *window);
+
static void meta_window_apply_session_info (MetaWindow *window,
const MetaWindowSessionInfo *info);
@@ -165,7 +166,7 @@ meta_window_new (MetaDisplay *display,
MetaWorkspace *space;
gulong existing_wm_state;
gulong event_mask;
-#define N_INITIAL_PROPS 10
+#define N_INITIAL_PROPS 13
Atom initial_props[N_INITIAL_PROPS];
int i;
gboolean has_shape;
@@ -465,6 +466,8 @@ meta_window_new (MetaDisplay *display,
window->using_net_wm_name = FALSE;
window->using_net_wm_icon_name = FALSE;
+
+ window->need_reread_icon = TRUE;
window->layer = META_LAYER_LAST; /* invalid value */
window->stack_position = -1;
@@ -486,13 +489,13 @@ meta_window_new (MetaDisplay *display,
initial_props[i++] = display->atom_win_workspace;
initial_props[i++] = display->atom_net_startup_id;
initial_props[i++] = display->atom_metacity_update_counter;
+ initial_props[i++] = XA_WM_NORMAL_HINTS;
+ initial_props[i++] = display->atom_wm_protocols;
+ initial_props[i++] = XA_WM_HINTS;
g_assert (N_INITIAL_PROPS == i);
meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS);
- update_size_hints (window);
- update_protocols (window);
- update_wm_hints (window);
update_struts (window);
update_net_wm_state (window);
@@ -503,7 +506,7 @@ meta_window_new (MetaDisplay *display,
update_sm_hints (window); /* must come after transient_for */
update_role (window);
update_net_wm_type (window);
- update_icon (window);
+ meta_window_update_icon_now (window);
if (window->initially_iconic)
{
@@ -930,6 +933,7 @@ meta_window_free (MetaWindow *window)
meta_window_unqueue_calc_showing (window);
meta_window_unqueue_move_resize (window);
+ meta_window_unqueue_update_icon (window);
meta_window_free_delete_dialog (window);
tmp = window->workspaces;
@@ -4071,7 +4075,7 @@ process_property_notify (MetaWindow *window,
{
meta_verbose ("Property notify on %s for WM_NORMAL_HINTS\n", window->desc);
- update_size_hints (window);
+ meta_window_reload_property (window, XA_WM_NORMAL_HINTS);
/* See if we need to constrain current size */
meta_window_queue_move_resize (window);
@@ -4080,23 +4084,13 @@ process_property_notify (MetaWindow *window,
{
meta_verbose ("Property notify on %s for WM_PROTOCOLS\n", window->desc);
- update_protocols (window);
-
- meta_window_queue_move_resize (window);
+ meta_window_reload_property (window, window->display->atom_wm_protocols);
}
else if (event->atom == XA_WM_HINTS)
{
meta_verbose ("Property notify on %s for WM_HINTS\n", window->desc);
- meta_icon_cache_property_changed (&window->icon_cache,
- window->display,
- event->atom);
-
- update_wm_hints (window);
- update_icon (window);
- redraw_icon (window);
-
- meta_window_queue_move_resize (window);
+ meta_window_reload_property (window, XA_WM_HINTS);
}
else if (event->atom == window->display->atom_motif_wm_hints)
{
@@ -4155,8 +4149,7 @@ process_property_notify (MetaWindow *window,
meta_icon_cache_property_changed (&window->icon_cache,
window->display,
event->atom);
- update_icon (window);
- redraw_icon (window);
+ meta_window_queue_update_icon (window);
}
else if (event->atom == window->display->atom_kwm_win_icon)
{
@@ -4165,8 +4158,7 @@ process_property_notify (MetaWindow *window,
meta_icon_cache_property_changed (&window->icon_cache,
window->display,
event->atom);
- update_icon (window);
- redraw_icon (window);
+ meta_window_queue_update_icon (window);
}
else if (event->atom == window->display->atom_net_wm_strut)
{
@@ -4234,353 +4226,6 @@ send_configure_notify (MetaWindow *window)
meta_error_trap_pop (window->display, FALSE);
}
-#define FLAG_TOGGLED_ON(old,new,flag) \
- (((old)->flags & (flag)) == 0 && \
- ((new)->flags & (flag)) != 0)
-
-#define FLAG_TOGGLED_OFF(old,new,flag) \
- (((old)->flags & (flag)) != 0 && \
- ((new)->flags & (flag)) == 0)
-
-#define FLAG_CHANGED(old,new,flag) \
- (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag))
-
-static void
-spew_size_hints_differences (const XSizeHints *old,
- const XSizeHints *new)
-{
- if (FLAG_CHANGED (old, new, USPosition))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USPosition now %s\n",
- FLAG_TOGGLED_ON (old, new, USPosition) ? "set" : "unset");
- if (FLAG_CHANGED (old, new, USSize))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USSize now %s\n",
- FLAG_TOGGLED_ON (old, new, USSize) ? "set" : "unset");
- if (FLAG_CHANGED (old, new, PPosition))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PPosition now %s\n",
- FLAG_TOGGLED_ON (old, new, PPosition) ? "set" : "unset");
- if (FLAG_CHANGED (old, new, PSize))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PSize now %s\n",
- FLAG_TOGGLED_ON (old, new, PSize) ? "set" : "unset");
- if (FLAG_CHANGED (old, new, PMinSize))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMinSize now %s (%d x %d -> %d x %d)\n",
- FLAG_TOGGLED_ON (old, new, PMinSize) ? "set" : "unset",
- old->min_width, old->min_height,
- new->min_width, new->min_height);
- if (FLAG_CHANGED (old, new, PMaxSize))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMaxSize now %s (%d x %d -> %d x %d)\n",
- FLAG_TOGGLED_ON (old, new, PMaxSize) ? "set" : "unset",
- old->max_width, old->max_height,
- new->max_width, new->max_height);
- if (FLAG_CHANGED (old, new, PResizeInc))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PResizeInc now %s (width_inc %d -> %d height_inc %d -> %d)\n",
- FLAG_TOGGLED_ON (old, new, PResizeInc) ? "set" : "unset",
- old->width_inc, new->width_inc,
- old->height_inc, new->height_inc);
- if (FLAG_CHANGED (old, new, PAspect))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PAspect now %s (min %d/%d -> %d/%d max %d/%d -> %d/%d)\n",
- FLAG_TOGGLED_ON (old, new, PAspect) ? "set" : "unset",
- old->min_aspect.x, old->min_aspect.y,
- new->min_aspect.x, new->min_aspect.y,
- old->max_aspect.x, old->max_aspect.y,
- new->max_aspect.x, new->max_aspect.y);
- if (FLAG_CHANGED (old, new, PBaseSize))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PBaseSize now %s (%d x %d -> %d x %d)\n",
- FLAG_TOGGLED_ON (old, new, PBaseSize) ? "set" : "unset",
- old->base_width, old->base_height,
- new->base_width, new->base_height);
- if (FLAG_CHANGED (old, new, PWinGravity))
- meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PWinGravity now %s (%d -> %d)\n",
- FLAG_TOGGLED_ON (old, new, PWinGravity) ? "set" : "unset",
- old->win_gravity, new->win_gravity);
-}
-
-static void
-update_size_hints (MetaWindow *window)
-{
- int x, y, w, h;
- gulong supplied;
- XSizeHints old_hints;
- XSizeHints *new_hints;
-
- meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s\n", window->desc);
-
- old_hints = window->size_hints;
-
- /* Save the last ConfigureRequest, which we put here.
- * Values here set in the hints are supposed to
- * be ignored.
- */
- x = window->size_hints.x;
- y = window->size_hints.y;
- w = window->size_hints.width;
- h = window->size_hints.height;
-
- window->size_hints.flags = 0;
- supplied = 0;
- new_hints = NULL;
-
- meta_prop_get_size_hints (window->display,
- window->xwindow,
- XA_WM_NORMAL_HINTS,
- &new_hints,
- &supplied);
-
- /* as far as I can tell, "supplied" is just to check whether we had
- * old-style normal hints without gravity, base size as returned by
- * XGetNormalHints(), so we don't really use it as we fixup
- * window->size_hints to have those fields if they're missing.
- */
-
- if (new_hints != NULL)
- {
- window->size_hints = *new_hints;
- XFree (new_hints);
- new_hints = NULL;
- }
-
- /* Put back saved ConfigureRequest. */
- window->size_hints.x = x;
- window->size_hints.y = y;
- window->size_hints.width = w;
- window->size_hints.height = h;
-
- if (window->size_hints.flags & PBaseSize)
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets base size %d x %d\n",
- window->desc,
- window->size_hints.base_width,
- window->size_hints.base_height);
- }
- else if (window->size_hints.flags & PMinSize)
- {
- window->size_hints.base_width = window->size_hints.min_width;
- window->size_hints.base_height = window->size_hints.min_height;
- }
- else
- {
- window->size_hints.base_width = 0;
- window->size_hints.base_height = 0;
- }
- window->size_hints.flags |= PBaseSize;
-
- if (window->size_hints.flags & PMinSize)
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d\n",
- window->desc,
- window->size_hints.min_width,
- window->size_hints.min_height);
- }
- else if (window->size_hints.flags & PBaseSize)
- {
- window->size_hints.min_width = window->size_hints.base_width;
- window->size_hints.min_height = window->size_hints.base_height;
- }
- else
- {
- window->size_hints.min_width = 0;
- window->size_hints.min_height = 0;
- }
- window->size_hints.flags |= PMinSize;
-
- if (window->size_hints.flags & PMaxSize)
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d\n",
- window->desc,
- window->size_hints.max_width,
- window->size_hints.max_height);
- }
- else
- {
- window->size_hints.max_width = G_MAXINT;
- window->size_hints.max_height = G_MAXINT;
- window->size_hints.flags |= PMaxSize;
- }
-
- if (window->size_hints.max_width < window->size_hints.min_width)
- {
- /* someone is on crack */
- meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets max width %d less than min width %d, disabling resize\n",
- window->desc,
- window->size_hints.max_width,
- window->size_hints.min_width);
- window->size_hints.max_width = window->size_hints.min_width;
- }
-
- if (window->size_hints.max_height < window->size_hints.min_height)
- {
- /* another cracksmoker */
- meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets max height %d less than min height %d, disabling resize\n",
- window->desc,
- window->size_hints.max_height,
- window->size_hints.min_height);
- window->size_hints.max_height = window->size_hints.min_height;
- }
-
- if (window->size_hints.flags & PResizeInc)
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets resize width inc: %d height inc: %d\n",
- window->desc,
- window->size_hints.width_inc,
- window->size_hints.height_inc);
- if (window->size_hints.width_inc == 0)
- {
- window->size_hints.width_inc = 1;
- meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1\n");
- }
- if (window->size_hints.height_inc == 0)
- {
- window->size_hints.height_inc = 1;
- meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1\n");
- }
- }
- else
- {
- window->size_hints.width_inc = 1;
- window->size_hints.height_inc = 1;
- window->size_hints.flags |= PResizeInc;
- }
-
- if (window->size_hints.flags & PAspect)
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n",
- window->desc,
- window->size_hints.min_aspect.x,
- window->size_hints.min_aspect.y,
- window->size_hints.max_aspect.x,
- window->size_hints.max_aspect.y);
-
- /* don't divide by 0 */
- if (window->size_hints.min_aspect.y < 1)
- window->size_hints.min_aspect.y = 1;
- if (window->size_hints.max_aspect.y < 1)
- window->size_hints.max_aspect.y = 1;
- }
- else
- {
- window->size_hints.min_aspect.x = 1;
- window->size_hints.min_aspect.y = G_MAXINT;
- window->size_hints.max_aspect.x = G_MAXINT;
- window->size_hints.max_aspect.y = 1;
- window->size_hints.flags |= PAspect;
- }
-
- if (window->size_hints.flags & PWinGravity)
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d\n",
- window->desc,
- window->size_hints.win_gravity);
- }
- else
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s doesn't set gravity, using NW\n",
- window->desc);
- window->size_hints.win_gravity = NorthWestGravity;
- window->size_hints.flags |= PWinGravity;
- }
-
- recalc_window_features (window);
-
- spew_size_hints_differences (&old_hints, &window->size_hints);
-}
-
-static void
-update_protocols (MetaWindow *window)
-{
- Atom *protocols = NULL;
- int n_protocols = 0;
- int i;
-
- window->take_focus = FALSE;
- window->delete_window = FALSE;
- window->net_wm_ping = FALSE;
-
- meta_error_trap_push (window->display);
-
- if (XGetWMProtocols (window->display->xdisplay,
- window->xwindow,
- &protocols,
- &n_protocols))
- {
- i = 0;
- while (i < n_protocols)
- {
- if (protocols[i] == window->display->atom_wm_take_focus)
- window->take_focus = TRUE;
- else if (protocols[i] == window->display->atom_wm_delete_window)
- window->delete_window = TRUE;
- else if (protocols[i] == window->display->atom_net_wm_ping)
- window->net_wm_ping = TRUE;
- ++i;
- }
-
- meta_XFree (protocols);
- }
-
- meta_verbose ("Window %s has take_focus = %d delete_window = %d net_wm_ping = %d\n",
- window->desc, window->take_focus, window->delete_window,
- window->net_wm_ping);
-
- meta_error_trap_pop (window->display, TRUE);
-}
-
-static void
-update_wm_hints (MetaWindow *window)
-{
- XWMHints *hints;
- Window old_group_leader;
-
- old_group_leader = window->xgroup_leader;
-
- /* Fill in defaults */
- window->input = TRUE;
- window->initially_iconic = FALSE;
- window->xgroup_leader = None;
- window->wm_hints_pixmap = None;
- window->wm_hints_mask = None;
-
- hints = NULL;
- meta_prop_get_wm_hints (window->display,
- window->xwindow,
- XA_WM_HINTS,
- &hints);
-
- if (hints)
- {
- if (hints->flags & InputHint)
- window->input = hints->input;
-
- if (hints->flags & StateHint)
- window->initially_iconic = (hints->initial_state == IconicState);
-
- if (hints->flags & WindowGroupHint)
- window->xgroup_leader = hints->window_group;
-
- if (hints->flags & IconPixmapHint)
- window->wm_hints_pixmap = hints->icon_pixmap;
-
- if (hints->flags & IconMaskHint)
- window->wm_hints_mask = hints->icon_mask;
-
- meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
- window->input, window->initially_iconic,
- window->xgroup_leader,
- window->wm_hints_pixmap,
- window->wm_hints_mask);
-
- meta_XFree (hints);
- }
-
- if (window->xgroup_leader != old_group_leader)
- {
- meta_verbose ("Window %s changed its group leader to 0x%lx\n",
- window->desc, window->xgroup_leader);
-
- meta_window_group_leader_changed (window);
- }
-}
-
static void
update_net_wm_state (MetaWindow *window)
{
@@ -5067,7 +4712,17 @@ update_net_wm_type (MetaWindow *window)
}
static void
-update_icon (MetaWindow *window)
+redraw_icon (MetaWindow *window)
+{
+ /* We could probably be smart and just redraw the icon here,
+ * instead of the whole frame.
+ */
+ if (window->frame && window->mapped)
+ meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
+}
+
+static void
+meta_window_update_icon_now (MetaWindow *window)
{
GdkPixbuf *icon;
GdkPixbuf *mini_icon;
@@ -5094,18 +4749,109 @@ update_icon (MetaWindow *window)
window->icon = icon;
window->mini_icon = mini_icon;
+
+ redraw_icon (window);
}
g_assert (window->icon);
g_assert (window->mini_icon);
}
-static void
-redraw_icon (MetaWindow *window)
+static guint update_icon_idle = 0;
+static GSList *update_icon_pending = NULL;
+
+static gboolean
+idle_update_icon (gpointer data)
{
- /* We could probably be smart and just redraw the icon here. */
- if (window->frame)
- meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
+ GSList *tmp;
+ GSList *copy;
+
+ meta_topic (META_DEBUG_GEOMETRY, "Clearing the update_icon queue\n");
+
+ /* Work with a copy, for reentrancy. The allowed reentrancy isn't
+ * complete; destroying a window while we're in here would result in
+ * badness. But it's OK to queue/unqueue update_icons.
+ */
+ copy = g_slist_copy (update_icon_pending);
+ g_slist_free (update_icon_pending);
+ update_icon_pending = NULL;
+ update_icon_idle = 0;
+
+ destroying_windows_disallowed += 1;
+
+ tmp = copy;
+ while (tmp != NULL)
+ {
+ MetaWindow *window;
+
+ window = tmp->data;
+
+ /* As a side effect, sets window->update_icon_queued = FALSE */
+ meta_window_update_icon_now (window);
+
+ tmp = tmp->next;
+ }
+
+ g_slist_free (copy);
+
+ destroying_windows_disallowed -= 1;
+
+ return FALSE;
+}
+
+void
+meta_window_unqueue_update_icon (MetaWindow *window)
+{
+ if (!window->update_icon_queued)
+ return;
+
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Removing %s from the update_icon queue\n",
+ window->desc);
+
+ /* Note that window may not actually be in update_icon_pending
+ * because it may have been in "copy" inside the idle handler
+ */
+ update_icon_pending = g_slist_remove (update_icon_pending, window);
+ window->update_icon_queued = FALSE;
+
+ if (update_icon_pending == NULL &&
+ update_icon_idle != 0)
+ {
+ g_source_remove (update_icon_idle);
+ update_icon_idle = 0;
+ }
+}
+
+void
+meta_window_flush_update_icon (MetaWindow *window)
+{
+ if (window->update_icon_queued)
+ {
+ meta_window_unqueue_update_icon (window);
+ meta_window_update_icon_now (window);
+ }
+}
+
+void
+meta_window_queue_update_icon (MetaWindow *window)
+{
+ if (window->unmanaging)
+ return;
+
+ if (window->update_icon_queued)
+ return;
+
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Putting %s in the update_icon queue\n",
+ window->desc);
+
+ window->update_icon_queued = TRUE;
+
+ if (update_icon_idle == 0)
+ update_icon_idle = g_idle_add (idle_update_icon, NULL);
+
+ update_icon_pending = g_slist_prepend (update_icon_pending, window);
}
static GList*
@@ -5433,6 +5179,12 @@ set_allowed_actions_hint (MetaWindow *window)
#undef MAX_N_ACTIONS
}
+void
+meta_window_recalc_features (MetaWindow *window)
+{
+ recalc_window_features (window);
+}
+
static void
recalc_window_features (MetaWindow *window)
{
diff --git a/src/window.h b/src/window.h
index 9eb94a7a..59ae9986 100644
--- a/src/window.h
+++ b/src/window.h
@@ -191,6 +191,9 @@ struct _MetaWindow
/* Are we in the move_resize queue? */
guint move_resize_queued : 1;
+
+ /* Are we in the update_icon queue? */
+ guint update_icon_queued : 1;
/* Used by keybindings.c */
guint keys_grabbed : 1; /* normal keybindings grabbed */
@@ -221,6 +224,9 @@ struct _MetaWindow
/* has a shape mask */
guint has_shape : 1;
+
+ /* icon props have changed */
+ guint need_reread_icon : 1;
#ifdef HAVE_XSYNC
/* XSync update counter */
@@ -457,4 +463,12 @@ gboolean meta_window_get_icon_geometry (MetaWindow *window,
const char* meta_window_get_startup_id (MetaWindow *window);
+void meta_window_recalc_features (MetaWindow *window);
+
+void meta_window_queue_update_icon (MetaWindow *window);
+
#endif
+
+
+
+