From 6e007baaa82aa033ad2470551812b42907256b77 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Sat, 31 Mar 2007 05:19:41 +0000 Subject: [PATCH] Add support for _NET_WM_USER_TIME_WINDOW in order to cut down on context 2007-03-30 Elijah Newren 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 --- ChangeLog | 32 ++++++++++++++++ src/display.c | 32 ++++++++++++++-- src/display.h | 2 + src/screen.c | 3 +- src/window-props.c | 93 +++++++++++++++++++++++++++++++++++++++++++++- src/window-props.h | 9 +++++ src/window.c | 30 +++++++++++++-- src/window.h | 3 ++ 8 files changed, 193 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 78a301699..78279422d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2007-03-30 Elijah Newren + + 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 * src/session.c (meta_session_init): if previous client ID diff --git a/src/display.c b/src/display.c index 754f01927..ca8e82f57 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 1d837a4ff..5afc58209 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 dbf3cf982..3cd4cb7ce 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 2506e6257..ff087340c 100644 --- a/src/window-props.c +++ b/src/window-props.c @@ -69,6 +69,26 @@ void 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 815955dae..de3aca94d 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 626a875b8..0f2ac2366 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 580b8cbed..0dac50d20 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