evdev: Associate devices with the first created stage
Because evdev isn't associated with the display system, it doesn't have any easy way to associate an input device with a stage. Previously Clutter would never set a stage for an input device and leave it up to the application to set it. To make it easier for applications which just have a single fullscreen stage (which is probably the most common use case for evdev) the device manager now associates all input devices with the first stage that is created unless something has already set a stage. Reviewed-by: Emmanuele Bassi <ebassi@linux.intel.com>
This commit is contained in:
parent
1bfd1d85eb
commit
a3bbcff946
@ -68,6 +68,10 @@ struct _ClutterDeviceManagerEvdevPrivate
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
|
||||
ClutterStageManager *stage_manager;
|
||||
guint stage_added_handler;
|
||||
guint stage_removed_handler;
|
||||
};
|
||||
|
||||
static const gchar *subsystems[] = { "input", NULL };
|
||||
@ -803,6 +807,38 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
|
||||
G_CALLBACK (on_uevent), manager_evdev);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_evdev_dispose (GObject *object)
|
||||
{
|
||||
ClutterDeviceManagerEvdev *manager_evdev;
|
||||
ClutterDeviceManagerEvdevPrivate *priv;
|
||||
|
||||
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
|
||||
priv = manager_evdev->priv;
|
||||
|
||||
if (priv->stage_added_handler)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->stage_manager,
|
||||
priv->stage_added_handler);
|
||||
priv->stage_added_handler = 0;
|
||||
}
|
||||
|
||||
if (priv->stage_removed_handler)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->stage_manager,
|
||||
priv->stage_removed_handler);
|
||||
priv->stage_removed_handler = 0;
|
||||
}
|
||||
|
||||
if (priv->stage_manager)
|
||||
{
|
||||
g_object_unref (priv->stage_manager);
|
||||
priv->stage_manager = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_evdev_finalize (GObject *object)
|
||||
{
|
||||
@ -844,6 +880,7 @@ clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
|
||||
|
||||
gobject_class->constructed = clutter_device_manager_evdev_constructed;
|
||||
gobject_class->finalize = clutter_device_manager_evdev_finalize;
|
||||
gobject_class->dispose = clutter_device_manager_evdev_dispose;
|
||||
|
||||
manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
|
||||
manager_class->add_device = clutter_device_manager_evdev_add_device;
|
||||
@ -853,10 +890,77 @@ clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
|
||||
manager_class->get_device = clutter_device_manager_evdev_get_device;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_evdev_stage_added_cb (ClutterStageManager *manager,
|
||||
ClutterStage *stage,
|
||||
ClutterDeviceManagerEvdev *self)
|
||||
{
|
||||
ClutterDeviceManagerEvdevPrivate *priv = self->priv;
|
||||
GSList *l;
|
||||
|
||||
/* Set the stage of any devices that don't already have a stage */
|
||||
for (l = priv->devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
|
||||
if (_clutter_input_device_get_stage (device) == NULL)
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
}
|
||||
|
||||
/* We only want to do this once so we can catch the default
|
||||
stage. If the application has multiple stages then it will need
|
||||
to manage the stage of the input devices itself */
|
||||
g_signal_handler_disconnect (priv->stage_manager,
|
||||
priv->stage_added_handler);
|
||||
priv->stage_added_handler = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_evdev_stage_removed_cb (ClutterStageManager *manager,
|
||||
ClutterStage *stage,
|
||||
ClutterDeviceManagerEvdev *self)
|
||||
{
|
||||
ClutterDeviceManagerEvdevPrivate *priv = self->priv;
|
||||
GSList *l;
|
||||
|
||||
/* Remove the stage of any input devices that were pointing to this
|
||||
stage so we don't send events to invalid stages */
|
||||
for (l = priv->devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
|
||||
if (_clutter_input_device_get_stage (device) == stage)
|
||||
_clutter_input_device_set_stage (device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self)
|
||||
{
|
||||
self->priv = CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE (self);
|
||||
ClutterDeviceManagerEvdevPrivate *priv;
|
||||
|
||||
priv = self->priv = CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE (self);
|
||||
|
||||
priv->stage_manager = clutter_stage_manager_get_default ();
|
||||
g_object_ref (priv->stage_manager);
|
||||
|
||||
/* evdev doesn't have any way to link an event to a particular stage
|
||||
so we'll have to leave it up to applications to set the
|
||||
corresponding stage for an input device. However to make it
|
||||
easier for applications that are only using one fullscreen stage
|
||||
(which is probably the most frequent use-case for the evdev
|
||||
backend) we'll associate any input devices that don't have a
|
||||
stage with the first stage created. */
|
||||
priv->stage_added_handler =
|
||||
g_signal_connect (priv->stage_manager,
|
||||
"stage-added",
|
||||
G_CALLBACK (clutter_device_manager_evdev_stage_added_cb),
|
||||
self);
|
||||
priv->stage_removed_handler =
|
||||
g_signal_connect (priv->stage_manager,
|
||||
"stage-removed",
|
||||
G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb),
|
||||
self);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user