[clutter/fosdem-2012] evdev: Adds api to release/reclaim the evdev devices



commit 422907dcd2428b36b94d4b0b3403394e70641bec
Author: Robert Bragg <robert linux intel com>
Date:   Sun Jan 22 15:36:17 2012 +0000

    evdev: Adds api to release/reclaim the evdev devices
    
    Clutter applications using evdev are typically fullscreen applications
    associated with a single virtual termainal. When switching away from
    the applications associated tty then Clutter should stop managing all
    evdev devices and re-probe for devices when the application regains
    focus by switching back to the tty. To facilitate this, this patch
    adds clutter_evdev_release_devices() and clutter_evdev_reclaim_devices()
    functions.

 clutter/Makefile.am                          |    5 +
 clutter/evdev/clutter-device-manager-evdev.c |  140 ++++++++++++++++++++++++--
 clutter/evdev/clutter-evdev.h                |   38 +++++++
 3 files changed, 173 insertions(+), 10 deletions(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index 4aaab1b..783ee0d 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -539,10 +539,15 @@ evdev_h_priv = \
 	$(srcdir)/evdev/clutter-device-manager-evdev.h	\
 	$(srcdir)/evdev/clutter-input-device-evdev.h	\
 	$(NULL)
+evdev_h = $(srcdir)/evdev/clutter-evdev.h
 
 if USE_EVDEV
 backend_source_c_priv += $(evdev_c_priv)
 backend_source_h_priv += $(evdev_h_priv)
+backend_source_h += $(evdev_h)
+
+clutterevdev_includedir = $(clutter_includedir)/evdev
+clutterevdev_include_HEADERS = $(evdev_h)
 endif # SUPPORT_EVDEV
 
 if NEED_XKB_UTILS
diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c
index 5074e54..62cb826 100644
--- a/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/evdev/clutter-device-manager-evdev.c
@@ -63,6 +63,9 @@ struct _ClutterDeviceManagerEvdevPrivate
 {
   GUdevClient *udev_client;
 
+  ClutterStage *stage;
+  gboolean released;
+
   GSList *devices;          /* list of ClutterInputDeviceEvdevs */
   GSList *event_sources;    /* list of the event sources */
 
@@ -593,6 +596,8 @@ evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
                          "enabled", TRUE,
                          NULL);
 
+  _clutter_input_device_set_stage (device, manager_evdev->priv->stage);
+
   _clutter_device_manager_add_device (manager, device);
 
   CLUTTER_NOTE (EVENT, "Added device %s, type %d, sysfs %s",
@@ -651,6 +656,10 @@ on_uevent (GUdevClient *client,
            gpointer     data)
 {
   ClutterDeviceManagerEvdev *manager = CLUTTER_DEVICE_MANAGER_EVDEV (data);
+  ClutterDeviceManagerEvdevPrivate *priv = manager->priv;
+
+  if (priv->released)
+    return;
 
   if (g_strcmp0 (action, "add") == 0)
     evdev_add_device (manager, device);
@@ -776,6 +785,23 @@ clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
   return NULL;
 }
 
+static void
+clutter_device_manager_evdev_probe_devices (ClutterDeviceManagerEvdev *self)
+{
+  ClutterDeviceManagerEvdevPrivate *priv = self->priv;
+  GList *devices, *l;
+
+  devices = g_udev_client_query_by_subsystem (priv->udev_client, subsystems[0]);
+  for (l = devices; l; l = g_list_next (l))
+    {
+      GUdevDevice *device = l->data;
+
+      evdev_add_device (self, device);
+      g_object_unref (device);
+    }
+  g_list_free (devices);
+}
+
 /*
  * GObject implementation
  */
@@ -785,22 +811,13 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
 {
   ClutterDeviceManagerEvdev *manager_evdev;
   ClutterDeviceManagerEvdevPrivate *priv;
-  GList *devices, *l;
 
   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
   priv = manager_evdev->priv;
 
   priv->udev_client = g_udev_client_new (subsystems);
 
-  devices = g_udev_client_query_by_subsystem (priv->udev_client, subsystems[0]);
-  for (l = devices; l; l = g_list_next (l))
-    {
-      GUdevDevice *device = l->data;
-
-      evdev_add_device (manager_evdev, device);
-      g_object_unref (device);
-    }
-  g_list_free (devices);
+  clutter_device_manager_evdev_probe_devices (manager_evdev);
 
   /* subcribe for events on input devices */
   g_signal_connect (priv->udev_client, "uevent",
@@ -898,6 +915,15 @@ clutter_device_manager_evdev_stage_added_cb (ClutterStageManager *manager,
   ClutterDeviceManagerEvdevPrivate *priv = self->priv;
   GSList *l;
 
+  /* NB: Currently we can only associate a single stage with all evdev
+   * devices.
+   *
+   * We save a pointer to the stage so if we release/reclaim input
+   * devices due to switching virtual terminals then we know what
+   * stage to re associate the devices with.
+   */
+  priv->stage = stage;
+
   /* Set the stage of any devices that don't already have a stage */
   for (l = priv->devices; l; l = l->next)
     {
@@ -977,3 +1003,97 @@ _clutter_events_evdev_uninit (ClutterBackend *backend)
 {
   CLUTTER_NOTE (EVENT, "Uninitializing evdev backend");
 }
+
+/**
+ * clutter_evdev_release_devices:
+ *
+ * Releases all the evdev devices that Clutter is currently managing. This api
+ * is typically used when switching away from the Clutter application when
+ * switching tty. The devices can be reclaimed later with a call to
+ * clutter_evdev_reclaim_devices().
+ *
+ * This function should only be called after clutter has been initialized.
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+void
+clutter_evdev_release_devices (void)
+{
+  ClutterDeviceManager *manager = clutter_device_manager_get_default ();
+  ClutterDeviceManagerEvdev *evdev_manager;
+  ClutterDeviceManagerEvdevPrivate *priv;
+  GSList *l, *next;
+
+  if (!manager)
+    {
+      g_warning ("clutter_evdev_release_devices shouldn't be called "
+                 "before clutter_init()");
+      return;
+    }
+
+  evdev_manager = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
+  priv = evdev_manager->priv;
+
+  if (priv->released)
+    {
+      g_warning ("clutter_evdev_release_devices() shouldn't be called "
+                 "multiple times without a corresponding call to "
+                 "clutter_evdev_reclaim_devices() first");
+      return;
+    }
+
+  for (l = priv->devices; l; l = next)
+    {
+      ClutterInputDevice *device = l->data;
+
+      /* Be careful about the list we're iterating being modified... */
+      next = l->next;
+
+      _clutter_device_manager_remove_device (manager, device);
+    }
+
+  priv->released = TRUE;
+}
+
+/**
+ * clutter_evdev_reclaim_devices:
+ *
+ * This causes Clutter to re-probe for evdev devices. This is must only be
+ * called after a corresponding call to clutter_evdev_release_devices()
+ * was previously used to release all evdev devices. This API is typically
+ * used when a clutter application using evdev has regained focus due to
+ * switching ttys.
+ *
+ * This function should only be called after clutter has been initialized.
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+void
+clutter_evdev_reclaim_devices (void)
+{
+  ClutterDeviceManager *manager = clutter_device_manager_get_default ();
+  ClutterDeviceManagerEvdev *evdev_manager;
+  ClutterDeviceManagerEvdevPrivate *priv;
+
+  if (!manager)
+    {
+      g_warning ("clutter_evdev_release_devices shouldn't be called "
+                 "before clutter_init()");
+      return;
+    }
+
+  evdev_manager = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
+  priv = evdev_manager->priv;
+
+  if (!priv->released)
+    {
+      g_warning ("Spurious call to clutter_evdev_reclaim_devices() without "
+                 "previous call to clutter_evdev_release_devices");
+      return;
+    }
+
+  priv->released = FALSE;
+  clutter_device_manager_evdev_probe_devices (evdev_manager);
+}
diff --git a/clutter/evdev/clutter-evdev.h b/clutter/evdev/clutter-evdev.h
new file mode 100644
index 0000000..cc5e18e
--- /dev/null
+++ b/clutter/evdev/clutter-evdev.h
@@ -0,0 +1,38 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2012  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __CLUTTER_EVDEV_H__
+#define __CLUTTER_EVDEV_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+void  clutter_evdev_release_devices (void);
+void  clutter_evdev_reclaim_devices (void);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_EVDEV_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]