From 7743c70d4753e1bd299f59e3f252257464031ff2 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Wed, 8 Jun 2011 11:26:03 -0400 Subject: [PATCH] Move sync alarms to be per-window and permanent Instead of creating a new alarm each time we resize a window interactively, create an alarm the first time we resize a window and keep it around permanently until we unmanage the window. Doing it this way will be useful when we allow the application to spontaneously generate sync request updates to indicate frames it is drawing. https://bugzilla.gnome.org/show_bug.cgi?id=685463 --- src/core/display-private.h | 14 +++-- src/core/display.c | 119 ++++++++++++++++--------------------- src/core/window-private.h | 4 ++ src/core/window-props.c | 2 + src/core/window.c | 80 ++++++++++++++++++++++++- 5 files changed, 143 insertions(+), 76 deletions(-) diff --git a/src/core/display-private.h b/src/core/display-private.h index e7a74aa2e..75351129d 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -222,10 +222,6 @@ struct _MetaDisplay #ifdef HAVE_XKB int xkb_base_event_type; guint32 last_bell_time; -#endif -#ifdef HAVE_XSYNC - /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ - XSyncAlarm grab_sync_request_alarm; #endif int grab_resize_timeout_id; @@ -375,6 +371,16 @@ void meta_display_register_x_window (MetaDisplay *display, void meta_display_unregister_x_window (MetaDisplay *display, Window xwindow); +#ifdef HAVE_XSYNC +MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display, + XSyncAlarm alarm); +void meta_display_register_sync_alarm (MetaDisplay *display, + XSyncAlarm *alarmp, + MetaWindow *window); +void meta_display_unregister_sync_alarm (MetaDisplay *display, + XSyncAlarm alarm); +#endif /* HAVE_XSYNC */ + void meta_display_notify_window_created (MetaDisplay *display, MetaWindow *window); diff --git a/src/core/display.c b/src/core/display.c index 92e9f5382..dd45633b9 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -525,10 +525,6 @@ meta_display_open (void) the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a terminal has the focus */ -#ifdef HAVE_XSYNC - the_display->grab_sync_request_alarm = None; -#endif - /* FIXME copy the checks from GDK probably */ the_display->static_gravity_works = g_getenv ("MUTTER_USE_STATIC_GRAVITY") != NULL; @@ -1953,15 +1949,20 @@ event_callback (XEvent *event, } #ifdef HAVE_XSYNC - if (META_DISPLAY_HAS_XSYNC (display) && - event->type == (display->xsync_event_base + XSyncAlarmNotify) && - ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_sync_request_alarm) + if (META_DISPLAY_HAS_XSYNC (display) && + event->type == (display->xsync_event_base + XSyncAlarmNotify)) { - XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value; - guint64 new_counter_value; - new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32); - meta_window_update_sync_request_counter (display->grab_window, new_counter_value); - filter_out_event = TRUE; /* GTK doesn't want to see this really */ + MetaWindow *alarm_window = meta_display_lookup_sync_alarm (display, + ((XSyncAlarmNotifyEvent*)event)->alarm); + + if (alarm_window != NULL) + { + XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value; + guint64 new_counter_value; + new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32); + meta_window_update_sync_request_counter (alarm_window, new_counter_value); + filter_out_event = TRUE; /* GTK doesn't want to see this really */ + } } #endif /* HAVE_XSYNC */ @@ -3589,6 +3590,39 @@ meta_display_unregister_x_window (MetaDisplay *display, remove_pending_pings_for_window (display, xwindow); } +#ifdef HAVE_XSYNC +/* We store sync alarms in the window ID hash table, because they are + * just more types of XIDs in the same global space, but we have + * typesafe functions to register/unregister for readability. + */ + +MetaWindow* +meta_display_lookup_sync_alarm (MetaDisplay *display, + XSyncAlarm alarm) +{ + return g_hash_table_lookup (display->xids, &alarm); +} + +void +meta_display_register_sync_alarm (MetaDisplay *display, + XSyncAlarm *alarmp, + MetaWindow *window) +{ + g_return_if_fail (g_hash_table_lookup (display->xids, alarmp) == NULL); + + g_hash_table_insert (display->xids, alarmp, window); +} + +void +meta_display_unregister_sync_alarm (MetaDisplay *display, + XSyncAlarm alarm) +{ + g_return_if_fail (g_hash_table_lookup (display->xids, &alarm) != NULL); + + g_hash_table_remove (display->xids, &alarm); +} +#endif /* HAVE_XSYNC */ + void meta_display_notify_window_created (MetaDisplay *display, MetaWindow *window) @@ -3902,7 +3936,6 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_motion_notify_time = 0; display->grab_old_window_stacking = NULL; #ifdef HAVE_XSYNC - display->grab_sync_request_alarm = None; display->grab_last_user_action_was_snap = FALSE; #endif display->grab_frame_action = frame_action; @@ -3923,55 +3956,11 @@ meta_display_begin_grab_op (MetaDisplay *display, #ifdef HAVE_XSYNC if ( meta_grab_op_is_resizing (display->grab_op) && - display->grab_window->sync_request_counter != None) + display->grab_window->sync_request_counter != None) { - XSyncAlarmAttributes values; - XSyncValue init; - - meta_error_trap_push_with_return (display); - - /* Set the counter to 0, so we know that the application's - * responses to the client messages will always trigger - * a PositiveTransition - */ - - XSyncIntToValue (&init, 0); - XSyncSetCounter (display->xdisplay, - display->grab_window->sync_request_counter, init); - - display->grab_window->sync_request_serial = 0; - display->grab_window->sync_request_time.tv_sec = 0; - display->grab_window->sync_request_time.tv_usec = 0; - - values.trigger.counter = display->grab_window->sync_request_counter; - values.trigger.value_type = XSyncAbsolute; - values.trigger.test_type = XSyncPositiveTransition; - XSyncIntToValue (&values.trigger.wait_value, - display->grab_window->sync_request_serial + 1); - - /* After triggering, increment test_value by this. - * (NOT wait_value above) - */ - XSyncIntToValue (&values.delta, 1); - - /* we want events (on by default anyway) */ - values.events = True; - - display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay, - XSyncCACounter | - XSyncCAValueType | - XSyncCAValue | - XSyncCATestType | - XSyncCADelta | - XSyncCAEvents, - &values); - - if (meta_error_trap_pop_with_return (display) != Success) - display->grab_sync_request_alarm = None; - - meta_topic (META_DEBUG_RESIZING, - "Created update alarm 0x%lx\n", - display->grab_sync_request_alarm); + meta_window_create_sync_request_alarm (display->grab_window); + window->sync_request_time.tv_sec = 0; + window->sync_request_time.tv_usec = 0; } #endif } @@ -4084,14 +4073,6 @@ meta_display_end_grab_op (MetaDisplay *display, meta_screen_ungrab_all_keys (display->grab_screen, timestamp); } -#ifdef HAVE_XSYNC - if (display->grab_sync_request_alarm != None) - { - XSyncDestroyAlarm (display->xdisplay, - display->grab_sync_request_alarm); - display->grab_sync_request_alarm = None; - } -#endif /* HAVE_XSYNC */ display->grab_timestamp = 0; display->grab_window = NULL; diff --git a/src/core/window-private.h b/src/core/window-private.h index ffbe4be04..00f1c7a10 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -360,6 +360,8 @@ struct _MetaWindow XSyncCounter sync_request_counter; guint sync_request_serial; GTimeVal sync_request_time; + /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ + XSyncAlarm sync_request_alarm; #endif /* Number of UnmapNotify that are caused by us, if @@ -633,6 +635,8 @@ void meta_window_refresh_resize_popup (MetaWindow *window); void meta_window_free_delete_dialog (MetaWindow *window); +void meta_window_create_sync_request_alarm (MetaWindow *window); +void meta_window_destroy_sync_request_alarm (MetaWindow *window); void meta_window_update_keyboard_resize (MetaWindow *window, gboolean update_cursor); diff --git a/src/core/window-props.c b/src/core/window-props.c index 64bbdb28e..1637c2d63 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -920,6 +920,8 @@ reload_update_counter (MetaWindow *window, { if (value->type != META_PROP_VALUE_INVALID) { + meta_window_destroy_sync_request_alarm (window); + #ifdef HAVE_XSYNC XSyncCounter counter = value->v.xcounter; diff --git a/src/core/window.c b/src/core/window.c index 1e8083954..af7cdb085 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -1021,6 +1021,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->sync_request_serial = 0; window->sync_request_time.tv_sec = 0; window->sync_request_time.tv_usec = 0; + window->sync_request_alarm = None; #endif window->screen = screen; @@ -1824,6 +1825,8 @@ meta_window_unmanage (MetaWindow *window, if (!window->override_redirect) meta_stack_remove (window->screen->stack, window); + meta_window_destroy_sync_request_alarm (window); + if (window->frame) meta_window_destroy_frame (window); @@ -4437,6 +4440,76 @@ static_gravity_works (MetaDisplay *display) return display->static_gravity_works; } +void +meta_window_create_sync_request_alarm (MetaWindow *window) +{ +#ifdef HAVE_XSYNC + XSyncAlarmAttributes values; + XSyncValue init; + + if (window->sync_request_counter == None || + window->sync_request_alarm != None) + return; + + meta_error_trap_push_with_return (window->display); + + /* Set the counter to 0, so we know that the application's + * responses to the client messages will always trigger + * a PositiveTransition + */ + XSyncIntToValue (&init, 0); + XSyncSetCounter (window->display->xdisplay, + window->sync_request_counter, init); + window->sync_request_serial = 0; + + values.trigger.counter = window->sync_request_counter; + values.trigger.test_type = XSyncPositiveTransition; + + /* Initialize to one greater than the current value */ + values.trigger.value_type = XSyncRelative; + XSyncIntToValue (&values.trigger.wait_value, 1); + + /* After triggering, increment test_value by this until + * until the test condition is false */ + XSyncIntToValue (&values.delta, 1); + + /* we want events (on by default anyway) */ + values.events = True; + + window->sync_request_alarm = XSyncCreateAlarm (window->display->xdisplay, + XSyncCACounter | + XSyncCAValueType | + XSyncCAValue | + XSyncCATestType | + XSyncCADelta | + XSyncCAEvents, + &values); + + if (meta_error_trap_pop_with_return (window->display) == Success) + meta_display_register_sync_alarm (window->display, &window->sync_request_alarm, window); + else + { + window->sync_request_alarm = None; + window->sync_request_counter = None; + } +#endif +} + +void +meta_window_destroy_sync_request_alarm (MetaWindow *window) +{ +#ifdef HAVE_XSYNC + if (window->sync_request_alarm != None) + { + /* Has to be unregistered _before_ clearing the structure field */ + meta_display_unregister_sync_alarm (window->display, window->sync_request_alarm); + XSyncDestroyAlarm (window->display->xdisplay, + window->sync_request_alarm); + window->sync_request_alarm = None; + } +#endif /* HAVE_XSYNC */ +} + #ifdef HAVE_XSYNC static void send_sync_request (MetaWindow *window) @@ -4997,8 +5070,9 @@ meta_window_move_resize_internal (MetaWindow *window, meta_error_trap_push (window->display); #ifdef HAVE_XSYNC - if (window->sync_request_counter != None && - window->display->grab_sync_request_alarm != None && + if (window == window->display->grab_window && + window->sync_request_counter != None && + window->sync_request_alarm != None && window->sync_request_time.tv_usec == 0 && window->sync_request_time.tv_sec == 0) { @@ -8618,7 +8692,7 @@ check_moveresize_frequency (MetaWindow *window, #ifdef HAVE_XSYNC if (!window->disable_sync && - window->display->grab_sync_request_alarm != None) + window->sync_request_alarm != None) { if (window->sync_request_time.tv_sec != 0 || window->sync_request_time.tv_usec != 0)