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
This commit is contained in:
Carlos Garnacho 2016-02-26 00:45:50 +01:00
parent 821d737e2c
commit 741dd674f6

View File

@ -64,6 +64,8 @@ struct _MetaBackendPrivate
MetaInputSettings *input_settings; MetaInputSettings *input_settings;
ClutterActor *stage; ClutterActor *stage;
guint device_update_idle_id;
}; };
typedef struct _MetaBackendPrivate MetaBackendPrivate; typedef struct _MetaBackendPrivate MetaBackendPrivate;
@ -78,6 +80,9 @@ meta_backend_finalize (GObject *object)
g_clear_object (&priv->monitor_manager); g_clear_object (&priv->monitor_manager);
g_clear_object (&priv->input_settings); 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_hash_table_destroy (backend->device_monitors);
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
@ -517,12 +522,44 @@ meta_backend_get_stage (MetaBackend *backend)
return priv->stage; 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 void
meta_backend_update_last_device (MetaBackend *backend, meta_backend_update_last_device (MetaBackend *backend,
int device_id) int device_id)
{ {
ClutterInputDeviceType device_type; MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
MetaCursorTracker *cursor_tracker;
ClutterDeviceManager *manager; ClutterDeviceManager *manager;
ClutterInputDevice *device; ClutterInputDevice *device;
@ -536,23 +573,14 @@ meta_backend_update_last_device (MetaBackend *backend,
clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
return; 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; backend->current_device_id = device_id;
g_signal_emit_by_name (backend, "last-device-changed", device_id);
if (device_type == CLUTTER_KEYBOARD_DEVICE) if (priv->device_update_idle_id == 0)
return;
switch (device_type)
{ {
case CLUTTER_TOUCHSCREEN_DEVICE: priv->device_update_idle_id =
meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); g_idle_add ((GSourceFunc) update_last_device, backend);
break; g_source_set_name_by_id (priv->device_update_idle_id,
default: "[mutter] update_last_device");
meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE);
break;
} }
} }