From 741dd674f6b488a123e96bfc109acaa9f5ad1235 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 26 Feb 2016 00:45:50 +0100 Subject: [PATCH] backends: rate-filter the emission of MetaBackend::last-device-changed signal It indirectly triggers expensive operations in gnome-shell (js/ui/keyboard.js), which turns out too expensive if we happen to operate the shell simultaneously with 2 devices that will trigger the operations there. So just rate limit the signal emission, defer to an idle and just emit the last device gotten. Worst that will happen is that we may possibly emit the signal on the same device consecutively. https://bugzilla.gnome.org/show_bug.cgi?id=753527 --- src/backends/meta-backend.c | 60 +++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index e4ef6e3cc..93c8ad326 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -64,6 +64,8 @@ struct _MetaBackendPrivate MetaInputSettings *input_settings; ClutterActor *stage; + + guint device_update_idle_id; }; typedef struct _MetaBackendPrivate MetaBackendPrivate; @@ -78,6 +80,9 @@ meta_backend_finalize (GObject *object) g_clear_object (&priv->monitor_manager); g_clear_object (&priv->input_settings); + if (priv->device_update_idle_id) + g_source_remove (priv->device_update_idle_id); + g_hash_table_destroy (backend->device_monitors); G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); @@ -517,12 +522,44 @@ meta_backend_get_stage (MetaBackend *backend) return priv->stage; } +static gboolean +update_last_device (MetaBackend *backend) +{ + MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL); + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + ClutterInputDeviceType device_type; + ClutterDeviceManager *manager; + ClutterInputDevice *device; + + priv->device_update_idle_id = 0; + manager = clutter_device_manager_get_default (); + device = clutter_device_manager_get_device (manager, + backend->current_device_id); + device_type = clutter_input_device_get_device_type (device); + + g_signal_emit_by_name (backend, "last-device-changed", + backend->current_device_id); + + switch (device_type) + { + case CLUTTER_KEYBOARD_DEVICE: + break; + case CLUTTER_TOUCHSCREEN_DEVICE: + meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); + break; + default: + meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE); + break; + } + + return G_SOURCE_REMOVE; +} + void meta_backend_update_last_device (MetaBackend *backend, int device_id) { - ClutterInputDeviceType device_type; - MetaCursorTracker *cursor_tracker; + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); ClutterDeviceManager *manager; ClutterInputDevice *device; @@ -536,23 +573,14 @@ meta_backend_update_last_device (MetaBackend *backend, clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) return; - device_type = clutter_input_device_get_device_type (device); - - cursor_tracker = meta_cursor_tracker_get_for_screen (NULL); backend->current_device_id = device_id; - g_signal_emit_by_name (backend, "last-device-changed", device_id); - if (device_type == CLUTTER_KEYBOARD_DEVICE) - return; - - switch (device_type) + if (priv->device_update_idle_id == 0) { - case CLUTTER_TOUCHSCREEN_DEVICE: - meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); - break; - default: - meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE); - break; + priv->device_update_idle_id = + g_idle_add ((GSourceFunc) update_last_device, backend); + g_source_set_name_by_id (priv->device_update_idle_id, + "[mutter] update_last_device"); } }