Release Clutter 1.11.4 (snapshot)
[profile/ivi/clutter.git] / clutter / evdev / clutter-device-manager-evdev.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright (C) 2010  Intel Corp.
7  *
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.
12  *
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.
17  *
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/>.
20  *
21  * Author: Damien Lespiau <damien.lespiau@intel.com>
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <linux/input.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include <glib.h>
37 #include <gudev/gudev.h>
38
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"
51
52 #include "clutter-device-manager-evdev.h"
53
54 #define CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE(obj)               \
55   (G_TYPE_INSTANCE_GET_PRIVATE ((obj),                              \
56                                 CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,  \
57                                 ClutterDeviceManagerEvdevPrivate))
58
59 G_DEFINE_TYPE (ClutterDeviceManagerEvdev,
60                clutter_device_manager_evdev,
61                CLUTTER_TYPE_DEVICE_MANAGER);
62
63 struct _ClutterDeviceManagerEvdevPrivate
64 {
65   GUdevClient *udev_client;
66
67   ClutterStage *stage;
68   gboolean released;
69
70   GSList *devices;          /* list of ClutterInputDeviceEvdevs */
71   GSList *event_sources;    /* list of the event sources */
72
73   ClutterInputDevice *core_pointer;
74   ClutterInputDevice *core_keyboard;
75
76   ClutterStageManager *stage_manager;
77   guint stage_added_handler;
78   guint stage_removed_handler;
79 };
80
81 static const gchar *subsystems[] = { "input", NULL };
82
83 /*
84  * ClutterEventSource management
85  *
86  * The device manager is responsible for managing the GSource when devices
87  * appear and disappear from the system.
88  *
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.
93  */
94
95
96 static const char *option_xkb_layout = "us";
97 static const char *option_xkb_variant = "";
98 static const char *option_xkb_options = "";
99
100 /*
101  * ClutterEventSource for reading input devices
102  */
103
104 typedef struct _ClutterEventSource  ClutterEventSource;
105
106 struct _ClutterEventSource
107 {
108   GSource source;
109
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 */
115 };
116
117 static gboolean
118 clutter_event_prepare (GSource *source,
119                        gint    *timeout)
120 {
121   gboolean retval;
122
123   clutter_threads_enter ();
124
125   *timeout = -1;
126   retval = clutter_events_pending ();
127
128   clutter_threads_leave ();
129
130   return retval;
131 }
132
133 static gboolean
134 clutter_event_check (GSource *source)
135 {
136   ClutterEventSource *event_source = (ClutterEventSource *) source;
137   gboolean retval;
138
139   clutter_threads_enter ();
140
141   retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
142             clutter_events_pending ());
143
144   clutter_threads_leave ();
145
146   return retval;
147 }
148
149 static void
150 queue_event (ClutterEvent *event)
151 {
152   if (event == NULL)
153     return;
154
155   _clutter_event_push (event, FALSE);
156 }
157
158 static void
159 notify_key (ClutterEventSource *source,
160             guint32             time_,
161             guint32             key,
162             guint32             state)
163 {
164   ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
165   ClutterStage *stage;
166   ClutterEvent *event = NULL;
167
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);
171   if (!stage)
172     return;
173
174   /* if we have a mapping for that device, use it to generate the event */
175   if (source->xkb)
176     event =
177       _clutter_key_event_new_from_evdev (input_device,
178                                          stage,
179                                          source->xkb,
180                                          time_, key, state,
181                                          &source->modifier_state);
182
183   queue_event (event);
184 }
185
186
187 static void
188 notify_motion (ClutterEventSource *source,
189                guint32             time_,
190                gint                x,
191                gint                y)
192 {
193   ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
194   gfloat stage_width, stage_height, new_x, new_y;
195   ClutterEvent *event;
196   ClutterStage *stage;
197
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);
201   if (!stage)
202     return;
203
204   stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
205   stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
206
207   event = clutter_event_new (CLUTTER_MOTION);
208
209   if (x < 0)
210     new_x = 0.f;
211   else if (x >= stage_width)
212     new_x = stage_width - 1;
213   else
214     new_x = x;
215
216   if (y < 0)
217     new_y = 0.f;
218   else if (y >= stage_height)
219     new_y = stage_height - 1;
220   else
221     new_y = y;
222
223   source->x = new_x;
224   source->y = new_y;
225
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;
232
233   queue_event (event);
234 }
235
236 static void
237 notify_button (ClutterEventSource *source,
238                guint32             time_,
239                guint32             button,
240                guint32             state)
241 {
242   ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
243   ClutterEvent *event;
244   ClutterStage *stage;
245   gint button_nr;
246   static gint maskmap[8] =
247     {
248       CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON2_MASK, CLUTTER_BUTTON3_MASK,
249       CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
250     };
251
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);
255   if (!stage)
256     return;
257
258   button_nr = button - BTN_LEFT + 1;
259   if (G_UNLIKELY (button_nr < 1 || button_nr > 8))
260     {
261       g_warning ("Unhandled button event 0x%x", button);
262       return;
263     }
264
265   if (state)
266     event = clutter_event_new (CLUTTER_BUTTON_PRESS);
267   else
268     event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
269
270   /* Update the modfiers */
271   if (state)
272     source->modifier_state |= maskmap[button - BTN_LEFT];
273   else
274     source->modifier_state &= ~maskmap[button - BTN_LEFT];
275
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;
283
284   queue_event (event);
285 }
286
287 static gboolean
288 clutter_event_dispatch (GSource     *g_source,
289                         GSourceFunc  callback,
290                         gpointer     user_data)
291 {
292   ClutterEventSource *source = (ClutterEventSource *) g_source;
293   ClutterInputDevice *input_device = (ClutterInputDevice *) source->device;
294   struct input_event ev[8];
295   ClutterEvent *event;
296   gint len, i, dx = 0, dy = 0;
297   uint32_t _time;
298   ClutterStage *stage;
299
300   clutter_threads_enter ();
301
302   stage = _clutter_input_device_get_stage (input_device);
303
304   /* Don't queue more events if we haven't finished handling the previous batch
305    */
306   if (!clutter_events_pending ())
307     {
308        len = read (source->event_poll_fd.fd, &ev, sizeof (ev));
309        if (len < 0 || len % sizeof (ev[0]) != 0)
310        {
311          if (errno != EAGAIN)
312            {
313              ClutterDeviceManager *manager;
314              ClutterInputDevice *device;
315              const gchar *device_path;
316
317              device = CLUTTER_INPUT_DEVICE (source->device);
318
319              if (CLUTTER_HAS_DEBUG (EVENT))
320                {
321                  device_path =
322                    _clutter_input_device_evdev_get_device_path (source->device);
323
324                  CLUTTER_NOTE (EVENT, "Could not read device (%s), removing.",
325                                device_path);
326                }
327
328              /* remove the faulty device */
329              manager = clutter_device_manager_get_default ();
330              _clutter_device_manager_remove_device (manager, device);
331
332            }
333          goto out;
334        }
335
336        /* Drop events if we don't have any stage to forward them to */
337        if (!stage)
338          goto out;
339
340        for (i = 0; i < len / sizeof (ev[0]); i++)
341          {
342            struct input_event *e = &ev[i];
343
344            _time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
345            event = NULL;
346
347            switch (e->type)
348              {
349              case EV_KEY:
350
351                /* don't repeat mouse buttons */
352                if (e->code >= BTN_MOUSE && e->code < KEY_OK)
353                  if (e->value == 2)
354                    continue;
355
356                switch (e->code)
357                  {
358                  case BTN_TOUCH:
359                  case BTN_TOOL_PEN:
360                  case BTN_TOOL_RUBBER:
361                  case BTN_TOOL_BRUSH:
362                  case BTN_TOOL_PENCIL:
363                  case BTN_TOOL_AIRBRUSH:
364                  case BTN_TOOL_FINGER:
365                  case BTN_TOOL_MOUSE:
366                  case BTN_TOOL_LENS:
367                    break;
368
369                  case BTN_LEFT:
370                  case BTN_RIGHT:
371                  case BTN_MIDDLE:
372                  case BTN_SIDE:
373                  case BTN_EXTRA:
374                  case BTN_FORWARD:
375                  case BTN_BACK:
376                  case BTN_TASK:
377                    notify_button(source, _time, e->code, e->value);
378                    break;
379
380                  default:
381                    notify_key (source, _time, e->code, e->value);
382                  break;
383                  }
384                break;
385
386              case EV_SYN:
387                /* Nothing to do here? */
388                break;
389
390              case EV_MSC:
391                /* Nothing to do here? */
392                break;
393
394              case EV_REL:
395                /* compress the EV_REL events in dx/dy */
396                switch (e->code)
397                  {
398                  case REL_X:
399                    dx += e->value;
400                    break;
401                  case REL_Y:
402                    dy += e->value;
403                    break;
404                  }
405                break;
406
407              case EV_ABS:
408              default:
409                g_warning ("Unhandled event of type %d", e->type);
410                break;
411              }
412
413            queue_event (event);
414          }
415
416        if (dx != 0 || dy != 0)
417          notify_motion (source, _time, source->x + dx, source->y + dy);
418     }
419
420   /* Pop an event off the queue if any */
421   event = clutter_event_get ();
422
423   if (event)
424     {
425       /* forward the event into clutter for emission etc. */
426       clutter_do_event (event);
427       clutter_event_free (event);
428     }
429
430 out:
431   clutter_threads_leave ();
432
433   return TRUE;
434 }
435 static GSourceFuncs event_funcs = {
436   clutter_event_prepare,
437   clutter_event_check,
438   clutter_event_dispatch,
439   NULL
440 };
441
442 static GSource *
443 clutter_event_source_new (ClutterInputDeviceEvdev *input_device)
444 {
445   GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource));
446   ClutterEventSource *event_source = (ClutterEventSource *) source;
447   ClutterInputDeviceType type;
448   const gchar *node_path;
449   gint fd;
450
451   /* grab the udev input device node and open it */
452   node_path = _clutter_input_device_evdev_get_device_path (input_device);
453
454   CLUTTER_NOTE (EVENT, "Creating GSource for device %s", node_path);
455
456   fd = open (node_path, O_RDONLY | O_NONBLOCK);
457   if (fd < 0)
458     {
459       g_warning ("Could not open device %s: %s", node_path, strerror (errno));
460       return NULL;
461     }
462
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;
467
468   type =
469     clutter_input_device_get_device_type (CLUTTER_INPUT_DEVICE (input_device));
470
471   if (type == CLUTTER_KEYBOARD_DEVICE)
472     {
473       /* create the xkb description */
474       event_source->xkb = _clutter_xkb_desc_new (NULL,
475                                                  option_xkb_layout,
476                                                  option_xkb_variant,
477                                                  option_xkb_options);
478       if (G_UNLIKELY (event_source->xkb == NULL))
479         {
480           g_warning ("Could not compile keymap %s:%s:%s", option_xkb_layout,
481                      option_xkb_variant, option_xkb_options);
482           close (fd);
483           g_source_unref (source);
484           return NULL;
485         }
486     }
487   else if (type == CLUTTER_POINTER_DEVICE)
488     {
489       event_source->x = 0;
490       event_source->y = 0;
491     }
492
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);
498
499   return source;
500 }
501
502 static void
503 clutter_event_source_free (ClutterEventSource *source)
504 {
505   GSource *g_source = (GSource *) source;
506   const gchar *node_path;
507
508   node_path = _clutter_input_device_evdev_get_device_path (source->device);
509
510   CLUTTER_NOTE (EVENT, "Removing GSource for device %s", node_path);
511
512   /* ignore the return value of close, it's not like we can do something
513    * about it */
514   close (source->event_poll_fd.fd);
515
516   g_source_destroy (g_source);
517   g_source_unref (g_source);
518 }
519
520 static ClutterEventSource *
521 find_source_by_device (ClutterDeviceManagerEvdev *manager,
522                        ClutterInputDevice        *device)
523 {
524   ClutterDeviceManagerEvdevPrivate *priv = manager->priv;
525   GSList *l;
526
527   for (l = priv->event_sources; l; l = g_slist_next (l))
528     {
529       ClutterEventSource *source = l->data;
530
531       if (source->device == (ClutterInputDeviceEvdev *) device)
532         return source;
533     }
534
535   return NULL;
536 }
537
538 static gboolean
539 is_evdev (const gchar *sysfs_path)
540 {
541   GRegex *regex;
542   gboolean match;
543
544   regex = g_regex_new ("/input[0-9]+/event[0-9]+$", 0, 0, NULL);
545   match = g_regex_match (regex, sysfs_path, 0, NULL);
546
547   g_regex_unref (regex);
548   return match;
549 }
550
551 static void
552 evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
553                   GUdevDevice               *udev_device)
554 {
555   ClutterDeviceManager *manager = (ClutterDeviceManager *) manager_evdev;
556   ClutterInputDeviceType type = CLUTTER_EXTENSION_DEVICE;
557   ClutterInputDevice *device;
558   const gchar *device_file, *sysfs_path, *device_name;
559
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);
563
564   if (device_file == NULL || sysfs_path == NULL)
565     return;
566
567   if (g_udev_device_get_property (udev_device, "ID_INPUT") == NULL)
568     return;
569
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))
574     return;
575
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;
590
591   device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
592                          "id", 0,
593                          "name", device_name,
594                          "device-type", type,
595                          "sysfs-path", sysfs_path,
596                          "device-path", device_file,
597                          "enabled", TRUE,
598                          NULL);
599
600   _clutter_input_device_set_stage (device, manager_evdev->priv->stage);
601
602   _clutter_device_manager_add_device (manager, device);
603
604   CLUTTER_NOTE (EVENT, "Added device %s, type %d, sysfs %s",
605                 device_file, type, sysfs_path);
606 }
607
608 static ClutterInputDeviceEvdev *
609 find_device_by_udev_device (ClutterDeviceManagerEvdev *manager_evdev,
610                             GUdevDevice               *udev_device)
611 {
612   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
613   GSList *l;
614   const gchar *sysfs_path;
615
616   sysfs_path = g_udev_device_get_sysfs_path (udev_device);
617   if (sysfs_path == NULL)
618     {
619       g_message ("device file is NULL");
620       return NULL;
621     }
622
623   for (l = priv->devices; l; l = g_slist_next (l))
624     {
625       ClutterInputDeviceEvdev *device = l->data;
626
627       if (strcmp (sysfs_path,
628                   _clutter_input_device_evdev_get_sysfs_path (device)) == 0)
629         {
630           return device;
631         }
632     }
633
634   return NULL;
635 }
636
637 static void
638 evdev_remove_device (ClutterDeviceManagerEvdev *manager_evdev,
639                      GUdevDevice               *device)
640 {
641   ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev);
642   ClutterInputDeviceEvdev *device_evdev;
643   ClutterInputDevice *input_device;
644
645   device_evdev = find_device_by_udev_device (manager_evdev, device);
646   if (device_evdev == NULL)
647       return;
648
649   input_device = CLUTTER_INPUT_DEVICE (device_evdev);
650   _clutter_device_manager_remove_device (manager, input_device);
651 }
652
653 static void
654 on_uevent (GUdevClient *client,
655            gchar       *action,
656            GUdevDevice *device,
657            gpointer     data)
658 {
659   ClutterDeviceManagerEvdev *manager = CLUTTER_DEVICE_MANAGER_EVDEV (data);
660   ClutterDeviceManagerEvdevPrivate *priv = manager->priv;
661
662   if (priv->released)
663     return;
664
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);
669 }
670
671 /*
672  * ClutterDeviceManager implementation
673  */
674
675 static void
676 clutter_device_manager_evdev_add_device (ClutterDeviceManager *manager,
677                                          ClutterInputDevice   *device)
678 {
679   ClutterDeviceManagerEvdev *manager_evdev;
680   ClutterDeviceManagerEvdevPrivate *priv;
681   ClutterInputDeviceType device_type;
682   ClutterInputDeviceEvdev *device_evdev;
683   gboolean is_pointer, is_keyboard;
684   GSource *source;
685
686   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
687   priv = manager_evdev->priv;
688
689   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
690
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;
694
695   priv->devices = g_slist_prepend (priv->devices, device);
696
697   if (is_pointer && priv->core_pointer == NULL)
698     priv->core_pointer = device;
699
700   if (is_keyboard && priv->core_keyboard == NULL)
701     priv->core_keyboard = device;
702
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);
707 }
708
709 static void
710 clutter_device_manager_evdev_remove_device (ClutterDeviceManager *manager,
711                                             ClutterInputDevice   *device)
712 {
713   ClutterDeviceManagerEvdev *manager_evdev;
714   ClutterDeviceManagerEvdevPrivate *priv;
715   ClutterEventSource *source;
716
717   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
718   priv = manager_evdev->priv;
719
720   /* Remove the device */
721   priv->devices = g_slist_remove (priv->devices, device);
722
723   /* Remove the source */
724   source = find_source_by_device (manager_evdev, device);
725   if (G_UNLIKELY (source == NULL))
726     {
727       g_warning ("Trying to remove a device without a source installed ?!");
728       return;
729     }
730
731   clutter_event_source_free (source);
732   priv->event_sources = g_slist_remove (priv->event_sources, source);
733 }
734
735 static const GSList *
736 clutter_device_manager_evdev_get_devices (ClutterDeviceManager *manager)
737 {
738   return CLUTTER_DEVICE_MANAGER_EVDEV (manager)->priv->devices;
739 }
740
741 static ClutterInputDevice *
742 clutter_device_manager_evdev_get_core_device (ClutterDeviceManager   *manager,
743                                               ClutterInputDeviceType  type)
744 {
745   ClutterDeviceManagerEvdev *manager_evdev;
746   ClutterDeviceManagerEvdevPrivate *priv;
747
748   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
749   priv = manager_evdev->priv;
750
751   switch (type)
752     {
753     case CLUTTER_POINTER_DEVICE:
754       return priv->core_pointer;
755
756     case CLUTTER_KEYBOARD_DEVICE:
757       return priv->core_keyboard;
758
759     case CLUTTER_EXTENSION_DEVICE:
760     default:
761       return NULL;
762     }
763
764   return NULL;
765 }
766
767 static ClutterInputDevice *
768 clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
769                                          gint                  id)
770 {
771   ClutterDeviceManagerEvdev *manager_evdev;
772   ClutterDeviceManagerEvdevPrivate *priv;
773   GSList *l;
774
775   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
776   priv = manager_evdev->priv;
777
778   for (l = priv->devices; l; l = l->next)
779     {
780       ClutterInputDevice *device = l->data;
781
782       if (clutter_input_device_get_device_id (device) == id)
783         return device;
784     }
785
786   return NULL;
787 }
788
789 static void
790 clutter_device_manager_evdev_probe_devices (ClutterDeviceManagerEvdev *self)
791 {
792   ClutterDeviceManagerEvdevPrivate *priv = self->priv;
793   GList *devices, *l;
794
795   devices = g_udev_client_query_by_subsystem (priv->udev_client, subsystems[0]);
796   for (l = devices; l; l = g_list_next (l))
797     {
798       GUdevDevice *device = l->data;
799
800       evdev_add_device (self, device);
801       g_object_unref (device);
802     }
803   g_list_free (devices);
804 }
805
806 /*
807  * GObject implementation
808  */
809
810 static void
811 clutter_device_manager_evdev_constructed (GObject *gobject)
812 {
813   ClutterDeviceManagerEvdev *manager_evdev;
814   ClutterDeviceManagerEvdevPrivate *priv;
815
816   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
817   priv = manager_evdev->priv;
818
819   priv->udev_client = g_udev_client_new (subsystems);
820
821   clutter_device_manager_evdev_probe_devices (manager_evdev);
822
823   /* subcribe for events on input devices */
824   g_signal_connect (priv->udev_client, "uevent",
825                     G_CALLBACK (on_uevent), manager_evdev);
826 }
827
828 static void
829 clutter_device_manager_evdev_dispose (GObject *object)
830 {
831   ClutterDeviceManagerEvdev *manager_evdev;
832   ClutterDeviceManagerEvdevPrivate *priv;
833
834   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
835   priv = manager_evdev->priv;
836
837   if (priv->stage_added_handler)
838     {
839       g_signal_handler_disconnect (priv->stage_manager,
840                                    priv->stage_added_handler);
841       priv->stage_added_handler = 0;
842     }
843
844   if (priv->stage_removed_handler)
845     {
846       g_signal_handler_disconnect (priv->stage_manager,
847                                    priv->stage_removed_handler);
848       priv->stage_removed_handler = 0;
849     }
850
851   if (priv->stage_manager)
852     {
853       g_object_unref (priv->stage_manager);
854       priv->stage_manager = NULL;
855     }
856
857   G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->dispose (object);
858 }
859
860 static void
861 clutter_device_manager_evdev_finalize (GObject *object)
862 {
863   ClutterDeviceManagerEvdev *manager_evdev;
864   ClutterDeviceManagerEvdevPrivate *priv;
865   GSList *l;
866
867   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
868   priv = manager_evdev->priv;
869
870   g_object_unref (priv->udev_client);
871
872   for (l = priv->devices; l; l = g_slist_next (l))
873     {
874       ClutterInputDevice *device = l->data;
875
876       g_object_unref (device);
877     }
878   g_slist_free (priv->devices);
879
880   for (l = priv->event_sources; l; l = g_slist_next (l))
881     {
882       ClutterEventSource *source = l->data;
883
884       clutter_event_source_free (source);
885     }
886   g_slist_free (priv->event_sources);
887
888   G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object);
889 }
890
891 static void
892 clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
893 {
894   ClutterDeviceManagerClass *manager_class;
895   GObjectClass *gobject_class = (GObjectClass *) klass;
896
897   g_type_class_add_private (klass, sizeof (ClutterDeviceManagerEvdevPrivate));
898
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;
902
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;
909 }
910
911 static void
912 clutter_device_manager_evdev_stage_added_cb (ClutterStageManager *manager,
913                                              ClutterStage *stage,
914                                              ClutterDeviceManagerEvdev *self)
915 {
916   ClutterDeviceManagerEvdevPrivate *priv = self->priv;
917   GSList *l;
918
919   /* NB: Currently we can only associate a single stage with all evdev
920    * devices.
921    *
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.
925    */
926   priv->stage = stage;
927
928   /* Set the stage of any devices that don't already have a stage */
929   for (l = priv->devices; l; l = l->next)
930     {
931       ClutterInputDevice *device = l->data;
932
933       if (_clutter_input_device_get_stage (device) == NULL)
934         _clutter_input_device_set_stage (device, stage);
935     }
936
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;
943 }
944
945 static void
946 clutter_device_manager_evdev_stage_removed_cb (ClutterStageManager *manager,
947                                                ClutterStage *stage,
948                                                ClutterDeviceManagerEvdev *self)
949 {
950   ClutterDeviceManagerEvdevPrivate *priv = self->priv;
951   GSList *l;
952
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)
956     {
957       ClutterInputDevice *device = l->data;
958
959       if (_clutter_input_device_get_stage (device) == stage)
960         _clutter_input_device_set_stage (device, NULL);
961     }
962 }
963
964 static void
965 clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self)
966 {
967   ClutterDeviceManagerEvdevPrivate *priv;
968
969   priv = self->priv = CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE (self);
970
971   priv->stage_manager = clutter_stage_manager_get_default ();
972   g_object_ref (priv->stage_manager);
973
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,
983                       "stage-added",
984                       G_CALLBACK (clutter_device_manager_evdev_stage_added_cb),
985                       self);
986   priv->stage_removed_handler =
987     g_signal_connect (priv->stage_manager,
988                       "stage-removed",
989                       G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb),
990                       self);
991 }
992
993 void
994 _clutter_events_evdev_init (ClutterBackend *backend)
995 {
996   CLUTTER_NOTE (EVENT, "Initializing evdev backend");
997
998   backend->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,
999                                           "backend", backend,
1000                                           NULL);
1001 }
1002
1003 void
1004 _clutter_events_evdev_uninit (ClutterBackend *backend)
1005 {
1006   CLUTTER_NOTE (EVENT, "Uninitializing evdev backend");
1007 }
1008
1009 /**
1010  * clutter_evdev_release_devices:
1011  *
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().
1016  *
1017  * This function should only be called after clutter has been initialized.
1018  *
1019  * Since: 1.10
1020  * Stability: unstable
1021  */
1022 void
1023 clutter_evdev_release_devices (void)
1024 {
1025   ClutterDeviceManager *manager = clutter_device_manager_get_default ();
1026   ClutterDeviceManagerEvdev *evdev_manager;
1027   ClutterDeviceManagerEvdevPrivate *priv;
1028   GSList *l, *next;
1029
1030   if (!manager)
1031     {
1032       g_warning ("clutter_evdev_release_devices shouldn't be called "
1033                  "before clutter_init()");
1034       return;
1035     }
1036
1037   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager));
1038
1039   evdev_manager = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
1040   priv = evdev_manager->priv;
1041
1042   if (priv->released)
1043     {
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");
1047       return;
1048     }
1049
1050   for (l = priv->devices; l; l = next)
1051     {
1052       ClutterInputDevice *device = l->data;
1053
1054       /* Be careful about the list we're iterating being modified... */
1055       next = l->next;
1056
1057       _clutter_device_manager_remove_device (manager, device);
1058     }
1059
1060   priv->released = TRUE;
1061 }
1062
1063 /**
1064  * clutter_evdev_reclaim_devices:
1065  *
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
1070  * switching ttys.
1071  *
1072  * This function should only be called after clutter has been initialized.
1073  *
1074  * Since: 1.10
1075  * Stability: unstable
1076  */
1077 void
1078 clutter_evdev_reclaim_devices (void)
1079 {
1080   ClutterDeviceManager *manager = clutter_device_manager_get_default ();
1081   ClutterDeviceManagerEvdev *evdev_manager;
1082   ClutterDeviceManagerEvdevPrivate *priv;
1083
1084   if (!manager)
1085     {
1086       g_warning ("clutter_evdev_reclaim_devices shouldn't be called "
1087                  "before clutter_init()");
1088       return;
1089     }
1090
1091   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager));
1092
1093   evdev_manager = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
1094   priv = evdev_manager->priv;
1095
1096   if (!priv->released)
1097     {
1098       g_warning ("Spurious call to clutter_evdev_reclaim_devices() without "
1099                  "previous call to clutter_evdev_release_devices");
1100       return;
1101     }
1102
1103   priv->released = FALSE;
1104   clutter_device_manager_evdev_probe_devices (evdev_manager);
1105 }