mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-17 06:10:15 +00:00
wayland: synchronize key repeat with server
key repeat is handled client side, which means stalls in the compositor dispatching key release events can lead to fictious repeat events. This commit ties key repeat to a server roundtrip to ensure the client and server are in sync. https://bugzilla.gnome.org/show_bug.cgi?id=757942
This commit is contained in:
parent
551f1742f5
commit
b5281837d6
@ -105,6 +105,8 @@ struct _GdkWaylandSeat
|
||||
gboolean have_server_repeat;
|
||||
uint32_t server_repeat_rate;
|
||||
uint32_t server_repeat_delay;
|
||||
|
||||
struct wl_callback *repeat_callback;
|
||||
guint32 repeat_timer;
|
||||
guint32 repeat_key;
|
||||
guint32 repeat_count;
|
||||
@ -175,6 +177,10 @@ struct _GdkWaylandDeviceManagerClass
|
||||
GdkDeviceManagerClass parent_class;
|
||||
};
|
||||
|
||||
static void deliver_key_event (GdkWaylandDeviceData *device,
|
||||
uint32_t time_,
|
||||
uint32_t key,
|
||||
uint32_t state);
|
||||
GType gdk_wayland_device_manager_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandDeviceManager,
|
||||
@ -1692,6 +1698,8 @@ stop_key_repeat (GdkWaylandDeviceData *device)
|
||||
g_source_remove (device->repeat_timer);
|
||||
device->repeat_timer = 0;
|
||||
}
|
||||
|
||||
g_clear_pointer (&device->repeat_callback, wl_callback_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1762,12 +1770,39 @@ deliver_key_event (GdkWaylandDeviceData *device,
|
||||
g_source_set_name_by_id (device->repeat_timer, "[gtk+] keyboard_repeat");
|
||||
}
|
||||
|
||||
static void
|
||||
sync_after_repeat_callback (void *data,
|
||||
struct wl_callback *callback,
|
||||
uint32_t time)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
|
||||
g_clear_pointer (&device->repeat_callback, wl_callback_destroy);
|
||||
|
||||
deliver_key_event (device, device->time, device->repeat_key, 1);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener sync_after_repeat_callback_listener = {
|
||||
sync_after_repeat_callback
|
||||
};
|
||||
|
||||
static gboolean
|
||||
keyboard_repeat (gpointer data)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
|
||||
deliver_key_event (device, device->time, device->repeat_key, 1);
|
||||
/* Ping the server and wait for the timeout. We won't process
|
||||
* key repeat until it responds, since a hung server could lead
|
||||
* to a delayed key release event. We don't want to generate
|
||||
* repeat events long after the user released the key, just because
|
||||
* the server is tardy in telling us the user released the key.
|
||||
*/
|
||||
device->repeat_callback = wl_display_sync (display->wl_display);
|
||||
|
||||
wl_callback_add_listener (device->repeat_callback,
|
||||
&sync_after_repeat_callback_listener,
|
||||
device);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user