diff --git a/src/core/events.c b/src/core/events.c index 8a046b398..d38377862 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -50,6 +50,12 @@ #define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \ (e)->type == CLUTTER_KEY_RELEASE) +typedef enum +{ + EVENTS_UNFREEZE_SYNC, + EVENTS_UNFREEZE_REPLAY, +} EventsUnfreezeMethod; + static gboolean stage_has_key_focus (void) { @@ -169,6 +175,43 @@ sequence_is_pointer_emulated (MetaDisplay *display, return FALSE; } +static void +maybe_unfreeze_pointer_events (MetaBackend *backend, + const ClutterEvent *event, + EventsUnfreezeMethod unfreeze_method) +{ + Display *xdisplay; + int event_mode; + int device_id; + + if (event->type != CLUTTER_BUTTON_PRESS) + return; + + if (!META_IS_BACKEND_X11 (backend)) + return; + + device_id = clutter_event_get_device_id (event); + switch (unfreeze_method) + { + case EVENTS_UNFREEZE_SYNC: + event_mode = XISyncDevice; + meta_verbose ("Syncing events time %u device %i\n", + (unsigned int) event->button.time, device_id); + break; + case EVENTS_UNFREEZE_REPLAY: + event_mode = XIReplayDevice; + meta_verbose ("Replaying events time %u device %i\n", + (unsigned int) event->button.time, device_id); + break; + default: + g_assert_not_reached (); + return; + } + + xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + XIAllowEvents (xdisplay, device_id, event_mode, event->button.time); +} + static gboolean meta_display_handle_event (MetaDisplay *display, const ClutterEvent *event) @@ -382,17 +425,7 @@ meta_display_handle_event (MetaDisplay *display, { /* Only replay button press events, since that's where we * have the synchronous grab. */ - if (event->type == CLUTTER_BUTTON_PRESS) - { - if (META_IS_BACKEND_X11 (backend)) - { - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - meta_verbose ("Allowing events time %u\n", - (unsigned int)event->button.time); - XIAllowEvents (xdisplay, clutter_event_get_device_id (event), - XIReplayDevice, event->button.time); - } - } + maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY); /* If the focus window has an active close dialog let clutter * events go through, so fancy clutter dialogs can get to handle @@ -408,6 +441,13 @@ meta_display_handle_event (MetaDisplay *display, goto out; } + else + { + /* We could not match the event with a window, make sure we sync + * the pointer to discard the sequence and don't keep events frozen. + */ + maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC); + } out: /* If the compositor has a grab, don't pass that through to Wayland */