diff --git a/src/core/display-private.h b/src/core/display-private.h index f4f4077ea..251b6a80b 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -221,6 +221,9 @@ struct _MetaDisplay #ifdef HAVE_XKB int xkb_base_event_type; guint32 last_bell_time; +#endif +#ifdef HAVE_XSYNC + gint64 grab_sync_counter_wait_serial; #endif int grab_resize_timeout_id; diff --git a/src/core/display.c b/src/core/display.c index 9a9de7fa3..a17d9d198 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -1944,7 +1944,7 @@ event_callback (XEvent *event, if (alarm_window != NULL) { XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value; - guint64 new_counter_value; + gint64 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 */ diff --git a/src/core/window-private.h b/src/core/window-private.h index 0ed3535c6..755a25249 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -339,13 +339,17 @@ struct _MetaWindow /* if TRUE, we are freezing updates during a resize */ guint updates_frozen_for_resize : 1; + /* if TRUE, the we have the new form of sync request counter which + * also handles application frames */ + guint extended_sync_request_counter : 1; + /* Note: can be NULL */ GSList *struts; #ifdef HAVE_XSYNC /* XSync update counter */ XSyncCounter sync_request_counter; - guint sync_request_serial; + gint64 sync_request_serial; GTimeVal sync_request_time; /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ XSyncAlarm sync_request_alarm; @@ -592,7 +596,7 @@ void meta_window_set_gravity (MetaWindow *window, #ifdef HAVE_XSYNC void meta_window_update_sync_request_counter (MetaWindow *window, - guint64 new_counter_value); + gint64 new_counter_value); #endif /* HAVE_XSYNC */ void meta_window_handle_mouse_grab_op_event (MetaWindow *window, diff --git a/src/core/window-props.c b/src/core/window-props.c index e95ad4e33..eb8b379f9 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -883,13 +883,31 @@ reload_update_counter (MetaWindow *window, if (value->type != META_PROP_VALUE_INVALID) { meta_window_destroy_sync_request_alarm (window); + window->sync_request_counter = None; #ifdef HAVE_XSYNC - XSyncCounter counter = value->v.xcounter; + if (value->v.xcounter_list.n_counters == 0) + { + meta_warning ("_NET_WM_SYNC_REQUEST_COUNTER is empty\n"); + return; + } - window->sync_request_counter = counter; - meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx\n", - window->sync_request_counter); + if (value->v.xcounter_list.n_counters == 1) + { + window->sync_request_counter = value->v.xcounter_list.counters[0]; + window->extended_sync_request_counter = FALSE; + } + else + { + window->sync_request_counter = value->v.xcounter_list.counters[1]; + window->extended_sync_request_counter = TRUE; + } + meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx (extended=%s)\n", + window->sync_request_counter, + window->extended_sync_request_counter ? "true" : "false"); + + if (window->extended_sync_request_counter) + meta_window_create_sync_request_alarm (window); #endif } } @@ -1710,7 +1728,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display) { XA_WM_ICON_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE, FALSE }, { display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, TRUE, FALSE }, { display->atom__NET_STARTUP_ID, META_PROP_VALUE_UTF8, reload_net_startup_id, TRUE, FALSE }, - { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER, reload_update_counter, TRUE, FALSE }, + { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER_LIST, reload_update_counter, TRUE, TRUE }, { XA_WM_NORMAL_HINTS, META_PROP_VALUE_SIZE_HINTS, reload_normal_hints, TRUE, FALSE }, { display->atom_WM_PROTOCOLS, META_PROP_VALUE_ATOM_LIST, reload_wm_protocols, TRUE, FALSE }, { XA_WM_HINTS, META_PROP_VALUE_WM_HINTS, reload_wm_hints, TRUE, FALSE }, diff --git a/src/core/window.c b/src/core/window.c index cd04ae04e..52f426a65 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -4447,17 +4447,38 @@ meta_window_create_sync_request_alarm (MetaWindow *window) 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 + /* In the old style, we're responsible for setting the initial + * value of the counter. In the new (extended style), the counter + * value is initialized by the client before mapping the window */ - XSyncIntToValue (&init, 0); - XSyncSetCounter (window->display->xdisplay, - window->sync_request_counter, init); - window->sync_request_serial = 0; + if (window->extended_sync_request_counter) + { + if (!XSyncQueryCounter(window->display->xdisplay, + window->sync_request_counter, + &init)) + { + meta_error_trap_pop_with_return (window->display); + window->sync_request_counter = None; + return; + } + + window->sync_request_serial = + XSyncValueLow32 (init) + ((gint64)XSyncValueHigh32 (init) << 32); + + /* if the value is odd, the window starts off with updates frozen */ + meta_compositor_set_updates_frozen (window->display->compositor, window, + meta_window_updates_are_frozen (window)); + } + else + { + 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; + values.trigger.test_type = XSyncPositiveComparison; /* Initialize to one greater than the current value */ values.trigger.value_type = XSyncRelative; @@ -4508,12 +4529,17 @@ meta_window_destroy_sync_request_alarm (MetaWindow *window) static void send_sync_request (MetaWindow *window) { - XSyncValue value; XClientMessageEvent ev; + gint64 wait_serial; - window->sync_request_serial++; + /* For the old style of _NET_WM_SYNC_REQUEST_COUNTER, we just have to + * increase the value, but for the new "extended" style we need to + * pick an even (unfrozen) value sufficiently ahead of the last serial + * that we received from the client; the same code still works + * for the old style */ + wait_serial = window->sync_request_serial + 240; - XSyncIntToValue (&value, window->sync_request_serial); + window->display->grab_sync_counter_wait_serial = wait_serial; ev.type = ClientMessage; ev.window = window->xwindow; @@ -4526,8 +4552,9 @@ send_sync_request (MetaWindow *window) * want to use _roundtrip, though? */ ev.data.l[1] = meta_display_get_current_time (window->display); - ev.data.l[2] = XSyncValueLow32 (value); - ev.data.l[3] = XSyncValueHigh32 (value); + ev.data.l[2] = wait_serial & G_GUINT64_CONSTANT(0xffffffff); + ev.data.l[3] = wait_serial >> 32; + ev.data.l[4] = window->extended_sync_request_counter ? 1 : 0; /* We don't need to trap errors here as we are already * inside an error_trap_push()/pop() pair. @@ -4554,6 +4581,12 @@ send_sync_request (MetaWindow *window) gboolean meta_window_updates_are_frozen (MetaWindow *window) { +#ifdef HAVE_XSYNC + if (window->extended_sync_request_counter && + window->sync_request_serial % 2 == 1) + return TRUE; +#endif + return window->updates_frozen_for_resize; } @@ -9394,13 +9427,17 @@ update_tile_mode (MetaWindow *window) #ifdef HAVE_XSYNC void meta_window_update_sync_request_counter (MetaWindow *window, - guint64 new_counter_value) + gint64 new_counter_value) { + window->sync_request_serial = new_counter_value; + meta_compositor_set_updates_frozen (window->display->compositor, window, + meta_window_updates_are_frozen (window)); + if (window->display->grab_op != META_GRAB_OP_NONE && window == window->display->grab_window && - meta_grab_op_is_mouse (window->display->grab_op)) + meta_grab_op_is_mouse (window->display->grab_op) && + new_counter_value >= window->display->grab_sync_counter_wait_serial) { - meta_topic (META_DEBUG_RESIZING, "Alarm event received last motion x = %d y = %d\n", window->display->grab_latest_motion_x,