4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2010 Intel Corp.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 * Author: Damien Lespiau <damien.lespiau@intel.com>
28 #include <linux/input.h>
30 #include <sys/types.h>
37 #include <gudev/gudev.h>
39 #include "clutter-backend.h"
40 #include "clutter-debug.h"
41 #include "clutter-device-manager.h"
42 #include "clutter-device-manager-private.h"
43 #include "clutter-event-private.h"
44 #include "clutter-input-device-evdev.h"
45 #include "clutter-main.h"
46 #include "clutter-private.h"
47 #include "clutter-stage-manager.h"
48 #include "clutter-xkb-utils.h"
49 #include "clutter-backend-private.h"
50 #include "clutter-evdev.h"
52 #include "clutter-device-manager-evdev.h"
54 #define CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE(obj) \
55 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
56 CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, \
57 ClutterDeviceManagerEvdevPrivate))
59 G_DEFINE_TYPE (ClutterDeviceManagerEvdev,
60 clutter_device_manager_evdev,
61 CLUTTER_TYPE_DEVICE_MANAGER);
63 struct _ClutterDeviceManagerEvdevPrivate
65 GUdevClient *udev_client;
70 GSList *devices; /* list of ClutterInputDeviceEvdevs */
71 GSList *event_sources; /* list of the event sources */
73 ClutterInputDevice *core_pointer;
74 ClutterInputDevice *core_keyboard;
76 ClutterStageManager *stage_manager;
77 guint stage_added_handler;
78 guint stage_removed_handler;
81 static const gchar *subsystems[] = { "input", NULL };
84 * ClutterEventSource management
86 * The device manager is responsible for managing the GSource when devices
87 * appear and disappear from the system.
89 * FIXME: For now, we associate a GSource with every single device. Starting
90 * from glib 2.28 we can use g_source_add_child_source() to have a single
91 * GSource for the device manager, each device becoming a child source. Revisit
92 * this once we depend on glib >= 2.28.
96 static const char *option_xkb_layout = "us";
97 static const char *option_xkb_variant = "";
98 static const char *option_xkb_options = "";
101 * ClutterEventSource for reading input devices
104 typedef struct _ClutterEventSource ClutterEventSource;
106 struct _ClutterEventSource
110 ClutterInputDeviceEvdev *device; /* back pointer to the evdev device */
111 GPollFD event_poll_fd; /* file descriptor of the /dev node */
112 struct xkb_desc *xkb; /* compiled xkb keymap */
113 uint32_t modifier_state; /* remember the modifier state */
114 gint x, y; /* last x, y position for pointers */
118 clutter_event_prepare (GSource *source,
123 clutter_threads_enter ();
126 retval = clutter_events_pending ();
128 clutter_threads_leave ();
134 clutter_event_check (GSource *source)
136 ClutterEventSource *event_source = (ClutterEventSource *) source;
139 clutter_threads_enter ();
141 retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
142 clutter_events_pending ());
144 clutter_threads_leave ();
150 queue_event (ClutterEvent *event)
155 _clutter_event_push (event, FALSE);
159 notify_key (ClutterEventSource *source,
164 ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
166 ClutterEvent *event = NULL;
168 /* We can drop the event on the floor if no stage has been
169 * associated with the device yet. */
170 stage = _clutter_input_device_get_stage (input_device);
174 /* if we have a mapping for that device, use it to generate the event */
177 _clutter_key_event_new_from_evdev (input_device,
181 &source->modifier_state);
188 notify_motion (ClutterEventSource *source,
193 ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
194 gfloat stage_width, stage_height, new_x, new_y;
198 /* We can drop the event on the floor if no stage has been
199 * associated with the device yet. */
200 stage = _clutter_input_device_get_stage (input_device);
204 stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
205 stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
207 event = clutter_event_new (CLUTTER_MOTION);
211 else if (x >= stage_width)
212 new_x = stage_width - 1;
218 else if (y >= stage_height)
219 new_y = stage_height - 1;
226 event->motion.time = time_;
227 event->motion.stage = stage;
228 event->motion.device = input_device;
229 event->motion.modifier_state = source->modifier_state;
230 event->motion.x = new_x;
231 event->motion.y = new_y;
237 notify_button (ClutterEventSource *source,
242 ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
246 static gint maskmap[8] =
248 CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON2_MASK, CLUTTER_BUTTON3_MASK,
249 CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
252 /* We can drop the event on the floor if no stage has been
253 * associated with the device yet. */
254 stage = _clutter_input_device_get_stage (input_device);
258 button_nr = button - BTN_LEFT + 1;
259 if (G_UNLIKELY (button_nr < 1 || button_nr > 8))
261 g_warning ("Unhandled button event 0x%x", button);
266 event = clutter_event_new (CLUTTER_BUTTON_PRESS);
268 event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
270 /* Update the modfiers */
272 source->modifier_state |= maskmap[button - BTN_LEFT];
274 source->modifier_state &= ~maskmap[button - BTN_LEFT];
276 event->button.time = time_;
277 event->button.stage = CLUTTER_STAGE (stage);
278 event->button.device = (ClutterInputDevice *) source->device;
279 event->button.modifier_state = source->modifier_state;
280 event->button.button = button_nr;
281 event->button.x = source->x;
282 event->button.y = source->y;
288 clutter_event_dispatch (GSource *g_source,
289 GSourceFunc callback,
292 ClutterEventSource *source = (ClutterEventSource *) g_source;
293 ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
294 struct input_event ev[8];
296 gint len, i, dx = 0, dy = 0;
300 clutter_threads_enter ();
302 stage = _clutter_input_device_get_stage (input_device);
304 /* Don't queue more events if we haven't finished handling the previous batch
306 if (!clutter_events_pending ())
308 len = read (source->event_poll_fd.fd, &ev, sizeof (ev));
309 if (len < 0 || len % sizeof (ev[0]) != 0)
313 ClutterDeviceManager *manager;
314 ClutterInputDevice *device;
315 const gchar *device_path;
317 device = CLUTTER_INPUT_DEVICE (source->device);
319 if (CLUTTER_HAS_DEBUG (EVENT))
322 _clutter_input_device_evdev_get_device_path (source->device);
324 CLUTTER_NOTE (EVENT, "Could not read device (%s), removing.",
328 /* remove the faulty device */
329 manager = clutter_device_manager_get_default ();
330 _clutter_device_manager_remove_device (manager, device);
336 /* Drop events if we don't have any stage to forward them to */
340 for (i = 0; i < len / sizeof (ev[0]); i++)
342 struct input_event *e = &ev[i];
344 _time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
351 /* don't repeat mouse buttons */
352 if (e->code >= BTN_MOUSE && e->code < KEY_OK)
360 case BTN_TOOL_RUBBER:
362 case BTN_TOOL_PENCIL:
363 case BTN_TOOL_AIRBRUSH:
364 case BTN_TOOL_FINGER:
377 notify_button(source, _time, e->code, e->value);
381 notify_key (source, _time, e->code, e->value);
387 /* Nothing to do here? */
391 /* Nothing to do here? */
395 /* compress the EV_REL events in dx/dy */
409 g_warning ("Unhandled event of type %d", e->type);
416 if (dx != 0 || dy != 0)
417 notify_motion (source, _time, source->x + dx, source->y + dy);
420 /* Pop an event off the queue if any */
421 event = clutter_event_get ();
425 /* forward the event into clutter for emission etc. */
426 clutter_do_event (event);
427 clutter_event_free (event);
431 clutter_threads_leave ();
435 static GSourceFuncs event_funcs = {
436 clutter_event_prepare,
438 clutter_event_dispatch,
443 clutter_event_source_new (ClutterInputDeviceEvdev *input_device)
445 GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource));
446 ClutterEventSource *event_source = (ClutterEventSource *) source;
447 ClutterInputDeviceType type;
448 const gchar *node_path;
451 /* grab the udev input device node and open it */
452 node_path = _clutter_input_device_evdev_get_device_path (input_device);
454 CLUTTER_NOTE (EVENT, "Creating GSource for device %s", node_path);
456 fd = open (node_path, O_RDONLY | O_NONBLOCK);
459 g_warning ("Could not open device %s: %s", node_path, strerror (errno));
463 /* setup the source */
464 event_source->device = input_device;
465 event_source->event_poll_fd.fd = fd;
466 event_source->event_poll_fd.events = G_IO_IN;
469 clutter_input_device_get_device_type (CLUTTER_INPUT_DEVICE (input_device));
471 if (type == CLUTTER_KEYBOARD_DEVICE)
473 /* create the xkb description */
474 event_source->xkb = _clutter_xkb_desc_new (NULL,
478 if (G_UNLIKELY (event_source->xkb == NULL))
480 g_warning ("Could not compile keymap %s:%s:%s", option_xkb_layout,
481 option_xkb_variant, option_xkb_options);
483 g_source_unref (source);
487 else if (type == CLUTTER_POINTER_DEVICE)
493 /* and finally configure and attach the GSource */
494 g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
495 g_source_add_poll (source, &event_source->event_poll_fd);
496 g_source_set_can_recurse (source, TRUE);
497 g_source_attach (source, NULL);
503 clutter_event_source_free (ClutterEventSource *source)
505 GSource *g_source = (GSource *) source;
506 const gchar *node_path;
508 node_path = _clutter_input_device_evdev_get_device_path (source->device);
510 CLUTTER_NOTE (EVENT, "Removing GSource for device %s", node_path);
512 /* ignore the return value of close, it's not like we can do something
514 close (source->event_poll_fd.fd);
516 g_source_destroy (g_source);
517 g_source_unref (g_source);
520 static ClutterEventSource *
521 find_source_by_device (ClutterDeviceManagerEvdev *manager,
522 ClutterInputDevice *device)
524 ClutterDeviceManagerEvdevPrivate *priv = manager->priv;
527 for (l = priv->event_sources; l; l = g_slist_next (l))
529 ClutterEventSource *source = l->data;
531 if (source->device == (ClutterInputDeviceEvdev *) device)
539 is_evdev (const gchar *sysfs_path)
544 regex = g_regex_new ("/input[0-9]+/event[0-9]+$", 0, 0, NULL);
545 match = g_regex_match (regex, sysfs_path, 0, NULL);
547 g_regex_unref (regex);
552 evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
553 GUdevDevice *udev_device)
555 ClutterDeviceManager *manager = (ClutterDeviceManager *) manager_evdev;
556 ClutterInputDeviceType type = CLUTTER_EXTENSION_DEVICE;
557 ClutterInputDevice *device;
558 const gchar *device_file, *sysfs_path, *device_name;
560 device_file = g_udev_device_get_device_file (udev_device);
561 sysfs_path = g_udev_device_get_sysfs_path (udev_device);
562 device_name = g_udev_device_get_name (udev_device);
564 if (device_file == NULL || sysfs_path == NULL)
567 if (g_udev_device_get_property (udev_device, "ID_INPUT") == NULL)
570 /* Make sure to only add evdev devices, ie the device with a sysfs path that
571 * finishes by input%d/event%d (We don't rely on the node name as this
572 * policy is enforced by udev rules Vs API/ABI guarantees of sysfs) */
573 if (!is_evdev (sysfs_path))
576 /* Clutter assumes that device types are exclusive in the
577 * ClutterInputDevice API */
578 if (g_udev_device_has_property (udev_device, "ID_INPUT_KEYBOARD"))
579 type = CLUTTER_KEYBOARD_DEVICE;
580 else if (g_udev_device_has_property (udev_device, "ID_INPUT_MOUSE"))
581 type = CLUTTER_POINTER_DEVICE;
582 else if (g_udev_device_has_property (udev_device, "ID_INPUT_JOYSTICK"))
583 type = CLUTTER_JOYSTICK_DEVICE;
584 else if (g_udev_device_has_property (udev_device, "ID_INPUT_TABLET"))
585 type = CLUTTER_TABLET_DEVICE;
586 else if (g_udev_device_has_property (udev_device, "ID_INPUT_TOUCHPAD"))
587 type = CLUTTER_TOUCHPAD_DEVICE;
588 else if (g_udev_device_has_property (udev_device, "ID_INPUT_TOUCHSCREEN"))
589 type = CLUTTER_TOUCHSCREEN_DEVICE;
591 device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
595 "sysfs-path", sysfs_path,
596 "device-path", device_file,
600 _clutter_input_device_set_stage (device, manager_evdev->priv->stage);
602 _clutter_device_manager_add_device (manager, device);
604 CLUTTER_NOTE (EVENT, "Added device %s, type %d, sysfs %s",
605 device_file, type, sysfs_path);
608 static ClutterInputDeviceEvdev *
609 find_device_by_udev_device (ClutterDeviceManagerEvdev *manager_evdev,
610 GUdevDevice *udev_device)
612 ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
614 const gchar *sysfs_path;
616 sysfs_path = g_udev_device_get_sysfs_path (udev_device);
617 if (sysfs_path == NULL)
619 g_message ("device file is NULL");
623 for (l = priv->devices; l; l = g_slist_next (l))
625 ClutterInputDeviceEvdev *device = l->data;
627 if (strcmp (sysfs_path,
628 _clutter_input_device_evdev_get_sysfs_path (device)) == 0)
638 evdev_remove_device (ClutterDeviceManagerEvdev *manager_evdev,
641 ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev);
642 ClutterInputDeviceEvdev *device_evdev;
643 ClutterInputDevice *input_device;
645 device_evdev = find_device_by_udev_device (manager_evdev, device);
646 if (device_evdev == NULL)
649 input_device = CLUTTER_INPUT_DEVICE (device_evdev);
650 _clutter_device_manager_remove_device (manager, input_device);
654 on_uevent (GUdevClient *client,
659 ClutterDeviceManagerEvdev *manager = CLUTTER_DEVICE_MANAGER_EVDEV (data);
660 ClutterDeviceManagerEvdevPrivate *priv = manager->priv;
665 if (g_strcmp0 (action, "add") == 0)
666 evdev_add_device (manager, device);
667 else if (g_strcmp0 (action, "remove") == 0)
668 evdev_remove_device (manager, device);
672 * ClutterDeviceManager implementation
676 clutter_device_manager_evdev_add_device (ClutterDeviceManager *manager,
677 ClutterInputDevice *device)
679 ClutterDeviceManagerEvdev *manager_evdev;
680 ClutterDeviceManagerEvdevPrivate *priv;
681 ClutterInputDeviceType device_type;
682 ClutterInputDeviceEvdev *device_evdev;
683 gboolean is_pointer, is_keyboard;
686 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
687 priv = manager_evdev->priv;
689 device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
691 device_type = clutter_input_device_get_device_type (device);
692 is_pointer = device_type == CLUTTER_POINTER_DEVICE;
693 is_keyboard = device_type == CLUTTER_KEYBOARD_DEVICE;
695 priv->devices = g_slist_prepend (priv->devices, device);
697 if (is_pointer && priv->core_pointer == NULL)
698 priv->core_pointer = device;
700 if (is_keyboard && priv->core_keyboard == NULL)
701 priv->core_keyboard = device;
703 /* Install the GSource for this device */
704 source = clutter_event_source_new (device_evdev);
705 if (G_LIKELY (source))
706 priv->event_sources = g_slist_prepend (priv->event_sources, source);
710 clutter_device_manager_evdev_remove_device (ClutterDeviceManager *manager,
711 ClutterInputDevice *device)
713 ClutterDeviceManagerEvdev *manager_evdev;
714 ClutterDeviceManagerEvdevPrivate *priv;
715 ClutterEventSource *source;
717 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
718 priv = manager_evdev->priv;
720 /* Remove the device */
721 priv->devices = g_slist_remove (priv->devices, device);
723 /* Remove the source */
724 source = find_source_by_device (manager_evdev, device);
725 if (G_UNLIKELY (source == NULL))
727 g_warning ("Trying to remove a device without a source installed ?!");
731 clutter_event_source_free (source);
732 priv->event_sources = g_slist_remove (priv->event_sources, source);
735 static const GSList *
736 clutter_device_manager_evdev_get_devices (ClutterDeviceManager *manager)
738 return CLUTTER_DEVICE_MANAGER_EVDEV (manager)->priv->devices;
741 static ClutterInputDevice *
742 clutter_device_manager_evdev_get_core_device (ClutterDeviceManager *manager,
743 ClutterInputDeviceType type)
745 ClutterDeviceManagerEvdev *manager_evdev;
746 ClutterDeviceManagerEvdevPrivate *priv;
748 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
749 priv = manager_evdev->priv;
753 case CLUTTER_POINTER_DEVICE:
754 return priv->core_pointer;
756 case CLUTTER_KEYBOARD_DEVICE:
757 return priv->core_keyboard;
759 case CLUTTER_EXTENSION_DEVICE:
767 static ClutterInputDevice *
768 clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
771 ClutterDeviceManagerEvdev *manager_evdev;
772 ClutterDeviceManagerEvdevPrivate *priv;
775 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
776 priv = manager_evdev->priv;
778 for (l = priv->devices; l; l = l->next)
780 ClutterInputDevice *device = l->data;
782 if (clutter_input_device_get_device_id (device) == id)
790 clutter_device_manager_evdev_probe_devices (ClutterDeviceManagerEvdev *self)
792 ClutterDeviceManagerEvdevPrivate *priv = self->priv;
795 devices = g_udev_client_query_by_subsystem (priv->udev_client, subsystems[0]);
796 for (l = devices; l; l = g_list_next (l))
798 GUdevDevice *device = l->data;
800 evdev_add_device (self, device);
801 g_object_unref (device);
803 g_list_free (devices);
807 * GObject implementation
811 clutter_device_manager_evdev_constructed (GObject *gobject)
813 ClutterDeviceManagerEvdev *manager_evdev;
814 ClutterDeviceManagerEvdevPrivate *priv;
816 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
817 priv = manager_evdev->priv;
819 priv->udev_client = g_udev_client_new (subsystems);
821 clutter_device_manager_evdev_probe_devices (manager_evdev);
823 /* subcribe for events on input devices */
824 g_signal_connect (priv->udev_client, "uevent",
825 G_CALLBACK (on_uevent), manager_evdev);
829 clutter_device_manager_evdev_dispose (GObject *object)
831 ClutterDeviceManagerEvdev *manager_evdev;
832 ClutterDeviceManagerEvdevPrivate *priv;
834 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
835 priv = manager_evdev->priv;
837 if (priv->stage_added_handler)
839 g_signal_handler_disconnect (priv->stage_manager,
840 priv->stage_added_handler);
841 priv->stage_added_handler = 0;
844 if (priv->stage_removed_handler)
846 g_signal_handler_disconnect (priv->stage_manager,
847 priv->stage_removed_handler);
848 priv->stage_removed_handler = 0;
851 if (priv->stage_manager)
853 g_object_unref (priv->stage_manager);
854 priv->stage_manager = NULL;
857 G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->dispose (object);
861 clutter_device_manager_evdev_finalize (GObject *object)
863 ClutterDeviceManagerEvdev *manager_evdev;
864 ClutterDeviceManagerEvdevPrivate *priv;
867 manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
868 priv = manager_evdev->priv;
870 g_object_unref (priv->udev_client);
872 for (l = priv->devices; l; l = g_slist_next (l))
874 ClutterInputDevice *device = l->data;
876 g_object_unref (device);
878 g_slist_free (priv->devices);
880 for (l = priv->event_sources; l; l = g_slist_next (l))
882 ClutterEventSource *source = l->data;
884 clutter_event_source_free (source);
886 g_slist_free (priv->event_sources);
888 G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object);
892 clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
894 ClutterDeviceManagerClass *manager_class;
895 GObjectClass *gobject_class = (GObjectClass *) klass;
897 g_type_class_add_private (klass, sizeof (ClutterDeviceManagerEvdevPrivate));
899 gobject_class->constructed = clutter_device_manager_evdev_constructed;
900 gobject_class->finalize = clutter_device_manager_evdev_finalize;
901 gobject_class->dispose = clutter_device_manager_evdev_dispose;
903 manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
904 manager_class->add_device = clutter_device_manager_evdev_add_device;
905 manager_class->remove_device = clutter_device_manager_evdev_remove_device;
906 manager_class->get_devices = clutter_device_manager_evdev_get_devices;
907 manager_class->get_core_device = clutter_device_manager_evdev_get_core_device;
908 manager_class->get_device = clutter_device_manager_evdev_get_device;
912 clutter_device_manager_evdev_stage_added_cb (ClutterStageManager *manager,
914 ClutterDeviceManagerEvdev *self)
916 ClutterDeviceManagerEvdevPrivate *priv = self->priv;
919 /* NB: Currently we can only associate a single stage with all evdev
922 * We save a pointer to the stage so if we release/reclaim input
923 * devices due to switching virtual terminals then we know what
924 * stage to re associate the devices with.
928 /* Set the stage of any devices that don't already have a stage */
929 for (l = priv->devices; l; l = l->next)
931 ClutterInputDevice *device = l->data;
933 if (_clutter_input_device_get_stage (device) == NULL)
934 _clutter_input_device_set_stage (device, stage);
937 /* We only want to do this once so we can catch the default
938 stage. If the application has multiple stages then it will need
939 to manage the stage of the input devices itself */
940 g_signal_handler_disconnect (priv->stage_manager,
941 priv->stage_added_handler);
942 priv->stage_added_handler = 0;
946 clutter_device_manager_evdev_stage_removed_cb (ClutterStageManager *manager,
948 ClutterDeviceManagerEvdev *self)
950 ClutterDeviceManagerEvdevPrivate *priv = self->priv;
953 /* Remove the stage of any input devices that were pointing to this
954 stage so we don't send events to invalid stages */
955 for (l = priv->devices; l; l = l->next)
957 ClutterInputDevice *device = l->data;
959 if (_clutter_input_device_get_stage (device) == stage)
960 _clutter_input_device_set_stage (device, NULL);
965 clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self)
967 ClutterDeviceManagerEvdevPrivate *priv;
969 priv = self->priv = CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE (self);
971 priv->stage_manager = clutter_stage_manager_get_default ();
972 g_object_ref (priv->stage_manager);
974 /* evdev doesn't have any way to link an event to a particular stage
975 so we'll have to leave it up to applications to set the
976 corresponding stage for an input device. However to make it
977 easier for applications that are only using one fullscreen stage
978 (which is probably the most frequent use-case for the evdev
979 backend) we'll associate any input devices that don't have a
980 stage with the first stage created. */
981 priv->stage_added_handler =
982 g_signal_connect (priv->stage_manager,
984 G_CALLBACK (clutter_device_manager_evdev_stage_added_cb),
986 priv->stage_removed_handler =
987 g_signal_connect (priv->stage_manager,
989 G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb),
994 _clutter_events_evdev_init (ClutterBackend *backend)
996 CLUTTER_NOTE (EVENT, "Initializing evdev backend");
998 backend->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,
1004 _clutter_events_evdev_uninit (ClutterBackend *backend)
1006 CLUTTER_NOTE (EVENT, "Uninitializing evdev backend");
1010 * clutter_evdev_release_devices:
1012 * Releases all the evdev devices that Clutter is currently managing. This api
1013 * is typically used when switching away from the Clutter application when
1014 * switching tty. The devices can be reclaimed later with a call to
1015 * clutter_evdev_reclaim_devices().
1017 * This function should only be called after clutter has been initialized.
1020 * Stability: unstable
1023 clutter_evdev_release_devices (void)
1025 ClutterDeviceManager *manager = clutter_device_manager_get_default ();
1026 ClutterDeviceManagerEvdev *evdev_manager;
1027 ClutterDeviceManagerEvdevPrivate *priv;
1032 g_warning ("clutter_evdev_release_devices shouldn't be called "
1033 "before clutter_init()");
1037 g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager));
1039 evdev_manager = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
1040 priv = evdev_manager->priv;
1044 g_warning ("clutter_evdev_release_devices() shouldn't be called "
1045 "multiple times without a corresponding call to "
1046 "clutter_evdev_reclaim_devices() first");
1050 for (l = priv->devices; l; l = next)
1052 ClutterInputDevice *device = l->data;
1054 /* Be careful about the list we're iterating being modified... */
1057 _clutter_device_manager_remove_device (manager, device);
1060 priv->released = TRUE;
1064 * clutter_evdev_reclaim_devices:
1066 * This causes Clutter to re-probe for evdev devices. This is must only be
1067 * called after a corresponding call to clutter_evdev_release_devices()
1068 * was previously used to release all evdev devices. This API is typically
1069 * used when a clutter application using evdev has regained focus due to
1072 * This function should only be called after clutter has been initialized.
1075 * Stability: unstable
1078 clutter_evdev_reclaim_devices (void)
1080 ClutterDeviceManager *manager = clutter_device_manager_get_default ();
1081 ClutterDeviceManagerEvdev *evdev_manager;
1082 ClutterDeviceManagerEvdevPrivate *priv;
1086 g_warning ("clutter_evdev_reclaim_devices shouldn't be called "
1087 "before clutter_init()");
1091 g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager));
1093 evdev_manager = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
1094 priv = evdev_manager->priv;
1096 if (!priv->released)
1098 g_warning ("Spurious call to clutter_evdev_reclaim_devices() without "
1099 "previous call to clutter_evdev_release_devices");
1103 priv->released = FALSE;
1104 clutter_device_manager_evdev_probe_devices (evdev_manager);