summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElijah Newren <newren gmail com>2007-03-31 05:19:41 +0000
committerElijah Newren <newren@src.gnome.org>2007-03-31 05:19:41 +0000
commit6e007baaa82aa033ad2470551812b42907256b77 (patch)
treeae8bccbe6183b317b40b9f3d2ad5ab21b64c7169
parent55899b5ab7dc3a115ac9204689a0b669c0e12688 (diff)
downloadmetacity-6e007baaa82aa033ad2470551812b42907256b77.tar.gz
Add support for _NET_WM_USER_TIME_WINDOW in order to cut down on context
2007-03-30 Elijah Newren <newren gmail com> Add support for _NET_WM_USER_TIME_WINDOW in order to cut down on context switches. * src/display.c (meta_display_open): * src/display.h (struct _MetaDisplay): * src/screen.c (set_supported_hint): new atom * src/display.c (meta_display_open, meta_display_get_current_time_roundtrip): * src/display.h (struct _MetaDisplay): create a dedicated timestamp pinging window instead of reusing display->leader_window * src/display.c (event_callback): * src/window-props.c (reload_net_wm_user_time_window): * src/window.c (meta_window_new_with_attrs, meta_window_free, process_property_notify): * src/window.h (struct _MetaWindow): monitor property notify events on _NET_WM_USER_TIME_WINDOW windows too * src/window-props.[ch]: new meta_window_reload_propert(y|ies)_from_xwindow() functions * src/window-props.[ch] (init_net_wm_user_time_window, reload_net_wm_user_time_window, meta_display_init_window_prop_hooks): * src/window.c (meta_window_new_with_attrs): new hooks to handle new atom svn path=/trunk/; revision=3134
-rw-r--r--ChangeLog32
-rw-r--r--src/display.c32
-rw-r--r--src/display.h2
-rw-r--r--src/screen.c3
-rw-r--r--src/window-props.c93
-rw-r--r--src/window-props.h9
-rw-r--r--src/window.c30
-rw-r--r--src/window.h3
8 files changed, 193 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 78a30169..78279422 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2007-03-30 Elijah Newren <newren gmail com>
+
+ Add support for _NET_WM_USER_TIME_WINDOW in order to cut down on
+ context switches.
+
+ * src/display.c (meta_display_open):
+ * src/display.h (struct _MetaDisplay):
+ * src/screen.c (set_supported_hint):
+ new atom
+
+ * src/display.c (meta_display_open,
+ meta_display_get_current_time_roundtrip):
+ * src/display.h (struct _MetaDisplay):
+ create a dedicated timestamp pinging window instead of reusing
+ display->leader_window
+
+ * src/display.c (event_callback):
+ * src/window-props.c (reload_net_wm_user_time_window):
+ * src/window.c (meta_window_new_with_attrs, meta_window_free,
+ process_property_notify):
+ * src/window.h (struct _MetaWindow):
+ monitor property notify events on _NET_WM_USER_TIME_WINDOW windows too
+
+ * src/window-props.[ch]:
+ new meta_window_reload_propert(y|ies)_from_xwindow() functions
+
+ * src/window-props.[ch]
+ (init_net_wm_user_time_window, reload_net_wm_user_time_window,
+ meta_display_init_window_prop_hooks):
+ * src/window.c (meta_window_new_with_attrs):
+ new hooks to handle new atom
+
2007-03-26 Josselin Mouette <joss@malsain.org>
* src/session.c (meta_session_init): if previous client ID
diff --git a/src/display.c b/src/display.c
index 754f0192..ca8e82f5 100644
--- a/src/display.c
+++ b/src/display.c
@@ -333,7 +333,8 @@ meta_display_open (void)
"_NET_DESKTOP_VIEWPORT",
"_METACITY_VERSION",
"_NET_WM_VISIBLE_NAME",
- "_NET_WM_VISIBLE_ICON_NAME"
+ "_NET_WM_VISIBLE_ICON_NAME",
+ "_NET_WM_USER_TIME_WINDOW"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -492,6 +493,7 @@ meta_display_open (void)
display->atom_metacity_version = atoms[91];
display->atom_net_wm_visible_name = atoms[92];
display->atom_net_wm_visible_icon_name = atoms[93];
+ display->atom_net_wm_user_time_window = atoms[94];
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
@@ -502,6 +504,7 @@ meta_display_open (void)
* created in screen_new
*/
display->leader_window = None;
+ display->timestamp_pinging_window = None;
display->xinerama_cache_invalidated = TRUE;
@@ -685,6 +688,13 @@ meta_display_open (void)
timestamp = event.xproperty.time;
}
+ /* Make a little window used only for pinging the server for timestamps; note
+ * that meta_create_offscreen_window already selects for PropertyChangeMask.
+ */
+ display->timestamp_pinging_window =
+ meta_create_offscreen_window (display->xdisplay,
+ DefaultRootWindow (display->xdisplay));
+
display->last_focus_time = timestamp;
display->last_user_time = timestamp;
display->compositor = NULL;
@@ -1192,14 +1202,13 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
* would use it as a property. The type doesn't matter.
*/
XChangeProperty (display->xdisplay,
- display->leader_window,
+ display->timestamp_pinging_window,
XA_PRIMARY, XA_STRING, 8,
PropModeAppend, NULL, 0);
XWindowEvent (display->xdisplay,
- display->leader_window,
+ display->timestamp_pinging_window,
PropertyChangeMask,
&property_event);
-
timestamp = property_event.xproperty.time;
}
@@ -1457,6 +1466,7 @@ event_callback (XEvent *event,
gpointer data)
{
MetaWindow *window;
+ MetaWindow *property_for_window;
MetaDisplay *display;
Window modified;
gboolean frame_was_receiver;
@@ -1510,6 +1520,18 @@ event_callback (XEvent *event,
else
window = NULL;
+ /* We only want to respond to _NET_WM_USER_TIME property notify
+ * events on _NET_WM_USER_TIME_WINDOW windows; in particular,
+ * responding to UnmapNotify events is kind of bad.
+ */
+ property_for_window = NULL;
+ if (window && modified == window->user_time_window)
+ {
+ property_for_window = window;
+ window = NULL;
+ }
+
+
frame_was_receiver = FALSE;
if (window &&
window->frame &&
@@ -2173,6 +2195,8 @@ event_callback (XEvent *event,
if (window && !frame_was_receiver)
meta_window_property_notify (window, event);
+ else if (property_for_window && !frame_was_receiver)
+ meta_window_property_notify (property_for_window, event);
group = meta_display_lookup_group (display,
event->xproperty.window);
diff --git a/src/display.h b/src/display.h
index 1d837a4f..5afc5820 100644
--- a/src/display.h
+++ b/src/display.h
@@ -85,6 +85,7 @@ struct _MetaDisplay
Display *xdisplay;
Window leader_window;
+ Window timestamp_pinging_window;
Atom atom_net_wm_name;
Atom atom_wm_protocols;
@@ -180,6 +181,7 @@ struct _MetaDisplay
Atom atom_metacity_version;
Atom atom_net_wm_visible_name;
Atom atom_net_wm_visible_icon_name;
+ Atom atom_net_wm_user_time_window;
/* This is the actual window from focus events,
* not the one we last set
diff --git a/src/screen.c b/src/screen.c
index dbf3cf98..3cd4cb7c 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -89,7 +89,7 @@ set_wm_check_hint (MetaScreen *screen)
static int
set_supported_hint (MetaScreen *screen)
{
-#define N_SUPPORTED 58
+#define N_SUPPORTED 59
Atom atoms[N_SUPPORTED];
atoms[0] = screen->display->atom_net_wm_name;
@@ -150,6 +150,7 @@ set_supported_hint (MetaScreen *screen)
atoms[55] = screen->display->atom_net_wm_state_demands_attention;
atoms[56] = screen->display->atom_net_desktop_geometry;
atoms[57] = screen->display->atom_net_desktop_viewport;
+ atoms[58] = screen->display->atom_net_wm_user_time_window;
//atoms[58] = screen->display->atom_net_restack_window;
//atoms[59] = screen->display->atom_net_moveresize_window;
diff --git a/src/window-props.c b/src/window-props.c
index 2506e625..ff087340 100644
--- a/src/window-props.c
+++ b/src/window-props.c
@@ -70,6 +70,26 @@ meta_window_reload_properties (MetaWindow *window,
const Atom *properties,
int n_properties)
{
+ meta_window_reload_properties_from_xwindow (window,
+ window->xwindow,
+ properties,
+ n_properties);
+}
+
+void
+meta_window_reload_property_from_xwindow (MetaWindow *window,
+ Window xwindow,
+ Atom property)
+{
+ meta_window_reload_properties_from_xwindow (window, xwindow, &property, 1);
+}
+
+void
+meta_window_reload_properties_from_xwindow (MetaWindow *window,
+ Window xwindow,
+ const Atom *properties,
+ int n_properties)
+{
int i;
MetaPropValue *values;
@@ -85,7 +105,7 @@ meta_window_reload_properties (MetaWindow *window,
++i;
}
- meta_prop_get_values (window->display, window->xwindow,
+ meta_prop_get_values (window->display, xwindow,
values, n_properties);
i = 0;
@@ -200,6 +220,70 @@ reload_net_wm_user_time (MetaWindow *window,
}
}
+static void
+init_net_wm_user_time_window (MetaDisplay *display,
+ Atom property,
+ MetaPropValue *value)
+{
+ value->type = META_PROP_VALUE_WINDOW;
+ value->atom = display->atom_net_wm_user_time_window;
+}
+
+static void
+reload_net_wm_user_time_window (MetaWindow *window,
+ MetaPropValue *value)
+{
+ if (value->type != META_PROP_VALUE_INVALID)
+ {
+ /* Unregister old NET_WM_USER_TIME_WINDOW */
+ if (window->user_time_window != None)
+ {
+ /* See the comment to the meta_display_register_x_window call below. */
+ meta_display_unregister_x_window (window->display,
+ window->user_time_window);
+ /* Don't get events on not-managed windows */
+ XSelectInput (window->display->xdisplay,
+ window->user_time_window,
+ NoEventMask);
+ }
+
+
+ /* Obtain the new NET_WM_USER_TIME_WINDOW and register it */
+ window->user_time_window = value->v.xwindow;
+ if (window->user_time_window != None)
+ {
+ /* Kind of a hack; display.c:event_callback() ignores events
+ * for unknown windows. We make window->user_time_window
+ * known by registering it with window (despite the fact
+ * that window->xwindow is already registered with window).
+ * This basically means that property notifies to either the
+ * window->user_time_window or window->xwindow will be
+ * treated identically and will result in functions for
+ * window being called to update it. Maybe we should ignore
+ * any property notifies to window->user_time_window other
+ * than atom_net_wm_user_time ones, but I just don't care
+ * and it's not specified in the spec anyway.
+ */
+ meta_display_register_x_window (window->display,
+ &window->user_time_window,
+ window);
+ /* Just listen for property notify events */
+ XSelectInput (window->display->xdisplay,
+ window->user_time_window,
+ PropertyChangeMask);
+
+ /* Manually load the _NET_WM_USER_TIME field from the given window
+ * at this time as well. If the user_time_window ever broadens in
+ * scope, we'll probably want to load all relevant properties here.
+ */
+ meta_window_reload_property_from_xwindow (
+ window,
+ window->display->atom_net_wm_user_time,
+ window->user_time_window);
+ }
+ }
+}
+
#define MAX_TITLE_LENGTH 512
/**
@@ -1217,7 +1301,7 @@ reload_transient_for (MetaWindow *window,
meta_window_queue_move_resize (window);
}
-#define N_HOOKS 25
+#define N_HOOKS 26
void
meta_display_init_window_prop_hooks (MetaDisplay *display)
@@ -1357,6 +1441,11 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
hooks[i].reload_func = reload_transient_for;
++i;
+ hooks[i].property = display->atom_net_wm_user_time_window;
+ hooks[i].init_func = init_net_wm_user_time_window;
+ hooks[i].reload_func = reload_net_wm_user_time_window;
+ ++i;
+
if (i != N_HOOKS)
g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS);
}
diff --git a/src/window-props.h b/src/window-props.h
index 815955da..de3aca94 100644
--- a/src/window-props.h
+++ b/src/window-props.h
@@ -31,6 +31,15 @@ void meta_window_reload_property (MetaWindow *window,
void meta_window_reload_properties (MetaWindow *window,
const Atom *properties,
int n_properties);
+void meta_window_reload_property_from_xwindow
+ (MetaWindow *window,
+ Window xwindow,
+ Atom property);
+void meta_window_reload_properties_from_xwindow
+ (MetaWindow *window,
+ Window xwindow,
+ const Atom *properties,
+ int n_properties);
void meta_display_init_window_prop_hooks (MetaDisplay *display);
void meta_display_free_window_prop_hooks (MetaDisplay *display);
diff --git a/src/window.c b/src/window.c
index 626a875b..0f2ac236 100644
--- a/src/window.c
+++ b/src/window.c
@@ -234,7 +234,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
gulong existing_wm_state;
gulong event_mask;
MetaMoveResizeFlags flags;
-#define N_INITIAL_PROPS 17
+#define N_INITIAL_PROPS 18
Atom initial_props[N_INITIAL_PROPS];
int i;
gboolean has_shape;
@@ -478,6 +478,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->initial_workspace_set = FALSE;
window->initial_timestamp_set = FALSE;
window->net_wm_user_time_set = FALSE;
+ window->user_time_window = None;
window->calc_placement = FALSE;
window->shaken_loose = FALSE;
window->have_focus_click_grab = FALSE;
@@ -577,6 +578,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
initial_props[i++] = display->atom_net_wm_state;
initial_props[i++] = display->atom_motif_wm_hints;
initial_props[i++] = XA_WM_TRANSIENT_FOR;
+ initial_props[i++] = display->atom_net_wm_user_time_window;
g_assert (N_INITIAL_PROPS == i);
meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS);
@@ -1103,6 +1105,17 @@ meta_window_free (MetaWindow *window,
window->xwindow,
NoEventMask);
+ /* Stop getting events for the window's _NET_WM_USER_TIME_WINDOW too */
+ if (window->user_time_window != None)
+ {
+ meta_display_unregister_x_window (window->display,
+ window->user_time_window);
+ XSelectInput (window->display->xdisplay,
+ window->user_time_window,
+ NoEventMask);
+ window->user_time_window = None;
+ }
+
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (window->display))
XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
@@ -5229,10 +5242,19 @@ process_property_notify (MetaWindow *window,
}
else if (event->atom == window->display->atom_net_wm_user_time)
{
+ Window xid;
+ Atom atom_net_wm_user_time;
+
meta_verbose ("Property notify on %s for _NET_WM_USER_TIME\n", window->desc);
-
- meta_window_reload_property (window,
- window->display->atom_net_wm_user_time);
+
+ atom_net_wm_user_time = window->display->atom_net_wm_user_time;
+ if (window->user_time_window)
+ xid = window->user_time_window;
+ else
+ xid = window->xwindow;
+ meta_window_reload_property_from_xwindow (window,
+ xid,
+ atom_net_wm_user_time);
}
return TRUE;
diff --git a/src/window.h b/src/window.h
index 580b8cbe..0dac50d2 100644
--- a/src/window.h
+++ b/src/window.h
@@ -318,6 +318,9 @@ struct _MetaWindow
/* set to the most recent user-interaction event timestamp that we
know about for this window */
guint32 net_wm_user_time;
+
+ /* window that gets updated net_wm_user_time values */
+ Window user_time_window;
/* The size we set the window to last (i.e. what we believe
* to be its actual size on the server). The x, y are