mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 19:10:43 -05:00
Make handling of windows that don't respond to _NET_WM_SYNC_REQUEST reliable
Previously, we were handling failure to respond to _NET_WM_SYNC_REQUEST in the code path for throttling motion events. But this meant that if a window didn't respond to _NET_WM_SYNC_REQUEST and there were no motion events - for a keyboard resize, or after the end of the grab operation - it would end up in a stuck state. Use a separate per-window timeout to reliably catch the failure to respond to _NET_WM_SYNC_REQUEST. https://bugzilla.gnome.org/show_bug.cgi?id=694046
This commit is contained in:
parent
592374bc62
commit
97a4cc8c9b
@ -3962,8 +3962,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
|||||||
display->grab_window->sync_request_counter != None)
|
display->grab_window->sync_request_counter != None)
|
||||||
{
|
{
|
||||||
meta_window_create_sync_request_alarm (display->grab_window);
|
meta_window_create_sync_request_alarm (display->grab_window);
|
||||||
window->sync_request_time.tv_sec = 0;
|
|
||||||
window->sync_request_time.tv_usec = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ struct _MetaWindow
|
|||||||
XSyncCounter sync_request_counter;
|
XSyncCounter sync_request_counter;
|
||||||
gint64 sync_request_serial;
|
gint64 sync_request_serial;
|
||||||
gint64 sync_request_wait_serial;
|
gint64 sync_request_wait_serial;
|
||||||
GTimeVal sync_request_time;
|
guint sync_request_timeout_id;
|
||||||
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
|
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
|
||||||
XSyncAlarm sync_request_alarm;
|
XSyncAlarm sync_request_alarm;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1020,8 +1020,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
|||||||
#ifdef HAVE_XSYNC
|
#ifdef HAVE_XSYNC
|
||||||
window->sync_request_counter = None;
|
window->sync_request_counter = None;
|
||||||
window->sync_request_serial = 0;
|
window->sync_request_serial = 0;
|
||||||
window->sync_request_time.tv_sec = 0;
|
window->sync_request_timeout_id = 0;
|
||||||
window->sync_request_time.tv_usec = 0;
|
|
||||||
window->sync_request_alarm = None;
|
window->sync_request_alarm = None;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1774,6 +1773,12 @@ meta_window_unmanage (MetaWindow *window,
|
|||||||
invalidate_work_areas (window);
|
invalidate_work_areas (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->sync_request_timeout_id)
|
||||||
|
{
|
||||||
|
g_source_remove (window->sync_request_timeout_id);
|
||||||
|
window->sync_request_timeout_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (window->display->grab_window == window)
|
if (window->display->grab_window == window)
|
||||||
meta_display_end_grab_op (window->display, timestamp);
|
meta_display_end_grab_op (window->display, timestamp);
|
||||||
|
|
||||||
@ -4616,6 +4621,38 @@ meta_window_destroy_sync_request_alarm (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XSYNC
|
#ifdef HAVE_XSYNC
|
||||||
|
static gboolean
|
||||||
|
sync_request_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
MetaWindow *window = data;
|
||||||
|
|
||||||
|
window->sync_request_timeout_id = 0;
|
||||||
|
|
||||||
|
/* We have now waited for more than a second for the
|
||||||
|
* application to respond to the sync request
|
||||||
|
*/
|
||||||
|
window->disable_sync = TRUE;
|
||||||
|
|
||||||
|
/* Reset the wait serial, so we don't continue freezing
|
||||||
|
* window updates
|
||||||
|
*/
|
||||||
|
window->sync_request_wait_serial = 0;
|
||||||
|
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
||||||
|
meta_window_updates_are_frozen (window));
|
||||||
|
|
||||||
|
if (window == window->display->grab_window &&
|
||||||
|
meta_grab_op_is_resizing (window->display->grab_op))
|
||||||
|
{
|
||||||
|
update_resize (window,
|
||||||
|
window->display->grab_last_user_action_was_snap,
|
||||||
|
window->display->grab_latest_motion_x,
|
||||||
|
window->display->grab_latest_motion_y,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_sync_request (MetaWindow *window)
|
send_sync_request (MetaWindow *window)
|
||||||
{
|
{
|
||||||
@ -4654,7 +4691,13 @@ send_sync_request (MetaWindow *window)
|
|||||||
XSendEvent (window->display->xdisplay,
|
XSendEvent (window->display->xdisplay,
|
||||||
window->xwindow, False, 0, (XEvent*) &ev);
|
window->xwindow, False, 0, (XEvent*) &ev);
|
||||||
|
|
||||||
g_get_current_time (&window->sync_request_time);
|
/* We give the window 1 sec to respond to _NET_WM_SYNC_REQUEST;
|
||||||
|
* if this time expires, we consider the window unresponsive
|
||||||
|
* and resize it unsynchonized.
|
||||||
|
*/
|
||||||
|
window->sync_request_timeout_id = g_timeout_add (1000,
|
||||||
|
sync_request_timeout,
|
||||||
|
window);
|
||||||
|
|
||||||
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
||||||
meta_window_updates_are_frozen (window));
|
meta_window_updates_are_frozen (window));
|
||||||
@ -5206,8 +5249,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|||||||
!window->disable_sync &&
|
!window->disable_sync &&
|
||||||
window->sync_request_counter != None &&
|
window->sync_request_counter != None &&
|
||||||
window->sync_request_alarm != None &&
|
window->sync_request_alarm != None &&
|
||||||
window->sync_request_time.tv_usec == 0 &&
|
window->sync_request_timeout_id == 0)
|
||||||
window->sync_request_time.tv_sec == 0)
|
|
||||||
{
|
{
|
||||||
send_sync_request (window);
|
send_sync_request (window);
|
||||||
}
|
}
|
||||||
@ -8821,60 +8863,19 @@ check_moveresize_frequency (MetaWindow *window,
|
|||||||
gdouble *remaining)
|
gdouble *remaining)
|
||||||
{
|
{
|
||||||
GTimeVal current_time;
|
GTimeVal current_time;
|
||||||
|
const double max_resizes_per_second = 25.0;
|
||||||
|
const double ms_between_resizes = 1000.0 / max_resizes_per_second;
|
||||||
|
double elapsed;
|
||||||
|
|
||||||
g_get_current_time (¤t_time);
|
g_get_current_time (¤t_time);
|
||||||
|
|
||||||
#ifdef HAVE_XSYNC
|
#ifdef HAVE_XSYNC
|
||||||
|
/* If we are throttling via _NET_WM_SYNC_REQUEST, we don't need
|
||||||
|
* an artificial timeout-based throttled */
|
||||||
if (!window->disable_sync &&
|
if (!window->disable_sync &&
|
||||||
window->sync_request_alarm != None)
|
window->sync_request_alarm != None)
|
||||||
{
|
|
||||||
if (window->sync_request_time.tv_sec != 0 ||
|
|
||||||
window->sync_request_time.tv_usec != 0)
|
|
||||||
{
|
|
||||||
double elapsed =
|
|
||||||
time_diff (¤t_time, &window->sync_request_time);
|
|
||||||
|
|
||||||
if (elapsed < 1000.0)
|
|
||||||
{
|
|
||||||
/* We want to be sure that the timeout happens at
|
|
||||||
* a time where elapsed will definitely be
|
|
||||||
* greater than 1000, so we can disable sync
|
|
||||||
*/
|
|
||||||
if (remaining)
|
|
||||||
*remaining = 1000.0 - elapsed + 100;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We have now waited for more than a second for the
|
|
||||||
* application to respond to the sync request
|
|
||||||
*/
|
|
||||||
window->disable_sync = TRUE;
|
|
||||||
|
|
||||||
/* Reset the wait serial, so we don't continue freezing
|
|
||||||
* window updates
|
|
||||||
*/
|
|
||||||
window->sync_request_wait_serial = 0;
|
|
||||||
meta_compositor_set_updates_frozen (window->display->compositor, window,
|
|
||||||
meta_window_updates_are_frozen (window));
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No outstanding sync requests. Go ahead and resize
|
|
||||||
*/
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* HAVE_XSYNC */
|
#endif /* HAVE_XSYNC */
|
||||||
{
|
|
||||||
const double max_resizes_per_second = 25.0;
|
|
||||||
const double ms_between_resizes = 1000.0 / max_resizes_per_second;
|
|
||||||
double elapsed;
|
|
||||||
|
|
||||||
elapsed = time_diff (¤t_time, &window->display->grab_last_moveresize_time);
|
elapsed = time_diff (¤t_time, &window->display->grab_last_moveresize_time);
|
||||||
|
|
||||||
@ -8896,7 +8897,6 @@ check_moveresize_frequency (MetaWindow *window,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
update_move_timeout (gpointer data)
|
update_move_timeout (gpointer data)
|
||||||
@ -9625,8 +9625,9 @@ meta_window_update_sync_request_counter (MetaWindow *window,
|
|||||||
* busy with a pagefault or a long computation).
|
* busy with a pagefault or a long computation).
|
||||||
*/
|
*/
|
||||||
window->disable_sync = FALSE;
|
window->disable_sync = FALSE;
|
||||||
window->sync_request_time.tv_sec = 0;
|
|
||||||
window->sync_request_time.tv_usec = 0;
|
g_source_remove (window->sync_request_timeout_id);
|
||||||
|
window->sync_request_timeout_id = 0;
|
||||||
|
|
||||||
/* This means we are ready for another configure;
|
/* This means we are ready for another configure;
|
||||||
* no pointer round trip here, to keep in sync */
|
* no pointer round trip here, to keep in sync */
|
||||||
|
Loading…
Reference in New Issue
Block a user