[gnome-control-center] Update device configuration from gnome-settings-daemon



commit be8d68c591872dc034ef1f85de63dcfd4a523488
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jan 19 18:55:51 2015 +0100

    Update device configuration from gnome-settings-daemon
    
    GsdWacomDevice has been updated, dragging GsdDeviceManager as a dependency
    from g-s-d, which has been added to panels/common, and compiled as a
    separate static libary, which is used by the wacom and mouse modules.
    
    gsd-input-helper.[ch] is now in such library and has been removed from
    the panel directories.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=743196

 configure.ac                                |    7 +
 panels/common/Makefile.am                   |   61 +++-
 panels/common/gsd-device-manager-udev.c     |  232 ++++++++++++
 panels/common/gsd-device-manager-udev.h     |   43 +++
 panels/common/gsd-device-manager-x11.c      |  261 +++++++++++++
 panels/common/gsd-device-manager-x11.h      |   50 +++
 panels/common/gsd-device-manager.c          |  406 ++++++++++++++++++++
 panels/common/gsd-device-manager.h          |  108 ++++++
 panels/{wacom => common}/gsd-input-helper.c |  142 +++++++-
 panels/{wacom => common}/gsd-input-helper.h |    9 +
 panels/mouse/Makefile.am                    |   11 +-
 panels/mouse/gsd-input-helper.c             |  531 ---------------------------
 panels/mouse/gsd-input-helper.h             |   82 ----
 panels/wacom/Makefile.am                    |   14 +-
 panels/wacom/gsd-wacom-device.c             |  106 ++----
 panels/wacom/gsd-wacom-device.h             |    4 -
 shell/Makefile.am                           |    1 +
 17 files changed, 1349 insertions(+), 719 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 27db9ac..ad15b06 100644
--- a/configure.ac
+++ b/configure.ac
@@ -177,6 +177,13 @@ AM_CONDITIONAL(HAVE_INTROSPECTION, false)
 GDESKTOP_PREFIX=`$PKG_CONFIG --variable prefix gsettings-desktop-schemas`
 AC_SUBST(GDESKTOP_PREFIX)
 
+PKG_CHECK_MODULES(DEVICES, $COMMON_MODULES)
+PKG_CHECK_MODULES(UDEV, gudev-1.0, have_udev=yes, have_udev=no)
+if test "x$have_udev" = xyes ; then
+       AC_DEFINE(HAVE_UDEV, 1, [System has udev])
+       AM_CONDITIONAL(HAVE_UDEV, [test "x$have_udev" = "xyes"])
+fi
+
 PKG_CHECK_MODULES(NETWORK_MANAGER, NetworkManager >= $NETWORK_MANAGER_REQUIRED_VERSION
                   libnm-glib >= $NETWORK_MANAGER_REQUIRED_VERSION
                   libnm-glib-vpn >= $NETWORK_MANAGER_REQUIRED_VERSION
diff --git a/panels/common/Makefile.am b/panels/common/Makefile.am
index 6655972..1de96d9 100644
--- a/panels/common/Makefile.am
+++ b/panels/common/Makefile.am
@@ -1,9 +1,10 @@
 # This is used in PANEL_CFLAGS
 cappletname = common
 
-noinst_LTLIBRARIES = liblanguage.la
+noinst_LTLIBRARIES = liblanguage.la libdevice.la
 
 AM_CPPFLAGS =                                          \
+       $(DEVICES_CFLAGS)                               \
        $(PANEL_CFLAGS)                                 \
        $(LIBLANGUAGE_CFLAGS)
 
@@ -23,6 +24,47 @@ liblanguage_la_SOURCES =             \
 liblanguage_la_LIBADD =                \
        $(LIBLANGUAGE_LIBS)
 
+#libdevice
+GSD_COMMON_ENUM_FILES = gsd-common-enums.c gsd-common-enums.h
+
+gsd-common-enums.h: gsd-device-manager.h Makefile
+       $(AM_V_GEN)($(GLIB_MKENUMS) \
+                       --fhead "#ifndef GSD_COMMON_ENUMS_H\n#define GSD_COMMON_ENUMS_H\n\n#include 
<glib-object.h>\n\nG_BEGIN_DECLS\n" \
+                       --fprod "/* enumerations from \"@filename \" */\n" \
+                       --vhead "GType @enum_name _get_type (void) G_GNUC_CONST;\n#define GSD_TYPE_ 
ENUMSHORT@ (@enum_name _get_type())\n" \
+                       --ftail "G_END_DECLS\n\n#endif /* !GSD_COMMON_ENUMS_H */" \
+               $(srcdir)/gsd-device-manager.h > $@)
+
+gsd-common-enums.c: gsd-device-manager.h Makefile gsd-common-enums.h
+       $(AM_V_GEN)($(GLIB_MKENUMS) \
+                       --fhead "#include \"gsd-device-manager.h\"\n#include \"gsd-common-enums.h\"\n" \
+                       --fprod "\n/* enumerations from \"@filename \" */" \
+                       --vhead "GType\n enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if 
(etype == 0) {\n    static const G Type@Value values[] = {" \
+                       --vprod "      { @VALUENAME@, \"@VALUENAME \", \"@valuenick \" }," \
+                       --vtail "      { 0, NULL, NULL }\n    };\n    etype = g_ type@_register_static 
(\"@EnumName \", values);\n  }\n  return etype;\n}\n" \
+               $(srcdir)/gsd-device-manager.h > $@)
+
+libdevice_la_SOURCES =                 \
+       gsd-common-enums.c              \
+       gsd-common-enums.h              \
+       gsd-input-helper.c              \
+       gsd-input-helper.h              \
+       gsd-device-manager.c            \
+       gsd-device-manager.h            \
+       gsd-device-manager-x11.c        \
+       gsd-device-manager-x11.h
+
+libdevice_la_LIBADD =                  \
+       $(DEVICES_LIBS)
+
+if HAVE_UDEV
+AM_CPPFLAGS += $(UDEV_CFLAGS)
+libdevice_la_LIBADD += $(UDEV_LIBS)
+libdevice_la_SOURCES +=                        \
+       gsd-device-manager-udev.c       \
+       gsd-device-manager-udev.h
+endif
+
 resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies 
$(srcdir)/common.gresource.xml)
 cc-common-resources.c: common.gresource.xml $(resource_files)
        $(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name 
cc_common $<
@@ -33,6 +75,21 @@ rulesdir = $(datadir)/polkit-1/rules.d/
 rules_DATA = gnome-control-center.rules
 
 EXTRA_DIST = $(rules_DATA) $(resource_files) common.gresource.xml
-CLEANFILES = $(BUILT_SOURCES)
+CLEANFILES = $(BUILT_SOURCES) $(GSD_COMMON_ENUM_FILES)
+
+INPUTDIR=$(top_srcdir)/../gnome-settings-daemon/plugins/common/
+INPUTFILES=                            \
+       gsd-input-helper.c              \
+       gsd-input-helper.h              \
+       gsd-device-manager.c            \
+       gsd-device-manager.h            \
+       gsd-device-manager-x11.c        \
+       gsd-device-manager-x11.h        \
+       gsd-device-manager-udev.c       \
+       gsd-device-manager-udev.h
+
+update-from-gsd:
+       FILES="$(INPUTFILES)" DIR="$(INPUTDIR)" $(top_srcdir)/update-from-gsd.sh && changed=true ; \
+       git commit -m "mouse: Update from gnome-settings-daemon" $(INPUTFILES)
 
 -include $(top_srcdir)/git.mk
diff --git a/panels/common/gsd-device-manager-udev.c b/panels/common/gsd-device-manager-udev.c
new file mode 100644
index 0000000..6289f55
--- /dev/null
+++ b/panels/common/gsd-device-manager-udev.c
@@ -0,0 +1,232 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <gudev/gudev.h>
+
+#include "gsd-device-manager-udev.h"
+
+struct _GsdUdevDeviceManager
+{
+       GsdDeviceManager parent_instance;
+       GHashTable *devices;
+       GUdevClient *udev_client;
+};
+
+struct _GsdUdevDeviceManagerClass
+{
+       GsdDeviceManagerClass parent_class;
+};
+
+G_DEFINE_TYPE (GsdUdevDeviceManager, gsd_udev_device_manager, GSD_TYPE_DEVICE_MANAGER)
+
+/* Index matches GsdDeviceType */
+const gchar *udev_ids[] = {
+       "ID_INPUT_MOUSE",
+       "ID_INPUT_KEYBOARD",
+       "ID_INPUT_TOUCHPAD",
+       "ID_INPUT_TABLET",
+       "ID_INPUT_TOUCHSCREEN"
+};
+
+static GsdDeviceType
+udev_device_get_device_type (GUdevDevice *device)
+{
+       GsdDeviceType type = 0;
+       gint i;
+
+       for (i = 0; i < G_N_ELEMENTS (udev_ids); i++) {
+               if (g_udev_device_get_property_as_boolean (device, udev_ids[i]))
+                       type |= (1 << i);
+       }
+
+       return type;
+}
+
+static gboolean
+device_is_evdev (GUdevDevice *device)
+{
+       const gchar *device_file;
+
+       device_file = g_udev_device_get_device_file (device);
+
+       if (!device_file || strstr (device_file, "/event") == NULL)
+               return FALSE;
+
+       return g_udev_device_get_property_as_boolean (device, "ID_INPUT");
+}
+
+static GsdDevice *
+create_device (GUdevDevice *udev_device)
+{
+       const gchar *vendor, *product, *name;
+       guint width, height;
+       GUdevDevice *parent;
+       GsdDevice *device;
+
+       parent = g_udev_device_get_parent (udev_device);
+       g_assert (parent != NULL);
+
+       name = g_udev_device_get_sysfs_attr (parent, "name");
+       vendor = g_udev_device_get_property (udev_device, "ID_VENDOR_ID");
+       product = g_udev_device_get_property (udev_device, "ID_MODEL_ID");
+       width = g_udev_device_get_property_as_int (udev_device, "ID_INPUT_WIDTH_MM");
+       height = g_udev_device_get_property_as_int (udev_device, "ID_INPUT_WIDTH_MM");
+
+       device = g_object_new (GSD_TYPE_DEVICE,
+                              "name", name,
+                              "device-file", g_udev_device_get_device_file (udev_device),
+                              "type", udev_device_get_device_type (udev_device),
+                              "vendor-id", vendor,
+                              "product-id", product,
+                              "width", width,
+                              "height", height,
+                              NULL);
+
+       g_object_unref (parent);
+
+       return device;
+}
+
+static void
+add_device (GsdUdevDeviceManager *manager,
+           GUdevDevice          *udev_device)
+{
+       GUdevDevice *parent;
+       GsdDevice *device;
+
+       parent = g_udev_device_get_parent (udev_device);
+
+       if (!parent)
+               return;
+
+       device = create_device (udev_device);
+       g_hash_table_insert (manager->devices, g_object_ref (udev_device), device);
+       g_signal_emit_by_name (manager, "device-added", device);
+}
+
+static void
+remove_device (GsdUdevDeviceManager *manager,
+              GUdevDevice          *udev_device)
+{
+       GsdDevice *device;
+
+       device = g_hash_table_lookup (manager->devices, udev_device);
+
+       if (!device)
+               return;
+
+       g_hash_table_steal (manager->devices, udev_device);
+       g_signal_emit_by_name (manager, "device-removed", device);
+
+       g_object_unref (device);
+       g_object_unref (udev_device);
+}
+
+static void
+udev_event_cb (GUdevClient         *client,
+              gchar                *action,
+              GUdevDevice          *device,
+              GsdUdevDeviceManager *manager)
+{
+       if (!device_is_evdev (device))
+               return;
+
+       if (g_strcmp0 (action, "add") == 0) {
+               add_device (manager, device);
+       } else if (g_strcmp0 (action, "remove") == 0) {
+               remove_device (manager, device);
+       }
+}
+
+static void
+gsd_udev_device_manager_init (GsdUdevDeviceManager *manager)
+{
+       const gchar *subsystems[] = { "input", NULL };
+       GList *devices, *l;
+
+       manager->devices = g_hash_table_new_full (NULL, NULL,
+                                                 (GDestroyNotify) g_object_unref,
+                                                 (GDestroyNotify) g_object_unref);
+
+       manager->udev_client = g_udev_client_new (subsystems);
+       g_signal_connect (manager->udev_client, "uevent",
+                         G_CALLBACK (udev_event_cb), manager);
+
+       devices = g_udev_client_query_by_subsystem (manager->udev_client,
+                                                   subsystems[0]);
+
+       for (l = devices; l; l = l->next) {
+               GUdevDevice *device = l->data;
+
+               if (device_is_evdev (device))
+                       add_device (manager, device);
+
+               g_object_unref (device);
+       }
+
+       g_list_free (devices);
+}
+
+static void
+gsd_udev_device_manager_finalize (GObject *object)
+{
+       GsdUdevDeviceManager *manager = GSD_UDEV_DEVICE_MANAGER (object);
+
+       g_hash_table_destroy (manager->devices);
+       g_object_unref (manager->udev_client);
+
+       G_OBJECT_CLASS (gsd_udev_device_manager_parent_class)->finalize (object);
+}
+
+static GList *
+gsd_udev_device_manager_list_devices (GsdDeviceManager *manager,
+                                     GsdDeviceType     type)
+{
+       GsdUdevDeviceManager *manager_udev = GSD_UDEV_DEVICE_MANAGER (manager);
+       GsdDeviceType device_type;
+       GList *devices = NULL;
+       GHashTableIter iter;
+       GsdDevice *device;
+
+       g_hash_table_iter_init (&iter, manager_udev->devices);
+
+       while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) {
+               device_type = gsd_device_get_device_type (device);
+
+               if ((device_type & type) == type)
+                       devices = g_list_prepend (devices, device);
+       }
+
+       return devices;
+}
+
+static void
+gsd_udev_device_manager_class_init (GsdUdevDeviceManagerClass *klass)
+{
+       GsdDeviceManagerClass *manager_class = GSD_DEVICE_MANAGER_CLASS (klass);
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = gsd_udev_device_manager_finalize;
+       manager_class->list_devices = gsd_udev_device_manager_list_devices;
+}
diff --git a/panels/common/gsd-device-manager-udev.h b/panels/common/gsd-device-manager-udev.h
new file mode 100644
index 0000000..2004e97
--- /dev/null
+++ b/panels/common/gsd-device-manager-udev.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __GSD_UDEV_DEVICE_MANAGER_H__
+#define __GSD_UDEV_DEVICE_MANAGER_H__
+
+#include "gsd-device-manager.h"
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_UDEV_DEVICE_MANAGER         (gsd_udev_device_manager_get_type ())
+#define GSD_UDEV_DEVICE_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_UDEV_DEVICE_MANAGER, 
GsdUdevDeviceManager))
+#define GSD_UDEV_DEVICE_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_UDEV_DEVICE_MANAGER, 
GsdUdevDeviceManagerClass))
+#define GSD_IS_UDEV_DEVICE_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_UDEV_DEVICE_MANAGER))
+#define GSD_IS_UDEV_DEVICE_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_UDEV_DEVICE_MANAGER))
+#define GSD_UDEV_DEVICE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_UDEV_DEVICE_MANAGER, 
GsdUdevDeviceManagerClass))
+
+typedef struct _GsdUdevDeviceManager GsdUdevDeviceManager;
+typedef struct _GsdUdevDeviceManagerClass GsdUdevDeviceManagerClass;
+
+GType gsd_udev_device_manager_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GSD_UDEV_DEVICE_MANAGER_H__ */
diff --git a/panels/common/gsd-device-manager-x11.c b/panels/common/gsd-device-manager-x11.c
new file mode 100644
index 0000000..89397bd
--- /dev/null
+++ b/panels/common/gsd-device-manager-x11.c
@@ -0,0 +1,261 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include "gsd-input-helper.h"
+#include "gsd-device-manager-x11.h"
+
+struct _GsdX11DeviceManager
+{
+       GsdDeviceManager parent_instance;
+       GdkDeviceManager *device_manager;
+       GHashTable *devices;
+       GHashTable *gdk_devices;
+};
+
+struct _GsdX11DeviceManagerClass
+{
+       GsdDeviceManagerClass parent_class;
+};
+
+G_DEFINE_TYPE (GsdX11DeviceManager, gsd_x11_device_manager, GSD_TYPE_DEVICE_MANAGER)
+
+static GsdDeviceType
+device_get_device_type (GdkDevice *gdk_device)
+{
+       GdkInputSource source;
+
+       source = gdk_device_get_source (gdk_device);
+
+       switch (source) {
+       case GDK_SOURCE_MOUSE:
+               return GSD_DEVICE_TYPE_MOUSE;
+       case GDK_SOURCE_PEN:
+       case GDK_SOURCE_ERASER:
+       case GDK_SOURCE_CURSOR:
+               return GSD_DEVICE_TYPE_TABLET;
+       case GDK_SOURCE_KEYBOARD:
+               return GSD_DEVICE_TYPE_KEYBOARD;
+       case GDK_SOURCE_TOUCHSCREEN:
+               return GSD_DEVICE_TYPE_TOUCHSCREEN;
+       case GDK_SOURCE_TOUCHPAD:
+               return GSD_DEVICE_TYPE_TOUCHPAD;
+       default:
+               g_warning ("Unhandled input source %d\n", source);
+       }
+
+       return 0;
+}
+
+static GsdDevice *
+create_device (GdkDevice   *gdk_device,
+              const gchar *device_file)
+{
+       guint width, height;
+       GsdDevice *device;
+       gint id;
+
+       id = gdk_x11_device_get_id (gdk_device);
+       xdevice_get_dimensions (id, &width, &height);
+
+       device = g_object_new (GSD_TYPE_DEVICE,
+                              "name", gdk_device_get_name (gdk_device),
+                              "device-file", device_file,
+                              "type", device_get_device_type (gdk_device),
+                              "vendor-id", gdk_device_get_vendor_id (gdk_device),
+                              "product-id", gdk_device_get_product_id (gdk_device),
+                              "width", width,
+                              "height", height,
+                              NULL);
+       return device;
+}
+
+static void
+add_device (GsdX11DeviceManager *manager,
+           GdkDevice           *gdk_device)
+{
+       gchar *device_file;
+       GsdDevice *device;
+       gint id;
+
+       if (gdk_device_get_device_type (gdk_device) == GDK_DEVICE_TYPE_MASTER)
+               return;
+
+       id = gdk_x11_device_get_id (gdk_device);
+       device_file = xdevice_get_device_node (id);
+
+       if (!device_file)
+               return;
+
+       if (!g_hash_table_lookup (manager->devices, device_file)) {
+               device = create_device (gdk_device, device_file);
+               g_hash_table_insert (manager->devices, g_strdup (device_file), device);
+               g_signal_emit_by_name (manager, "device-added", device);
+       }
+
+       /* Takes ownership of device_file */
+       g_hash_table_insert (manager->gdk_devices, gdk_device, device_file);
+}
+
+static void
+remove_device (GsdX11DeviceManager *manager,
+              GdkDevice           *gdk_device)
+{
+       const gchar *device_file;
+       GsdDevice *device;
+
+       device_file = g_hash_table_lookup (manager->gdk_devices, gdk_device);
+
+       if (!device_file)
+               return;
+
+       device = g_hash_table_lookup (manager->devices, device_file);
+
+       if (device)
+               g_object_ref (device);
+
+       g_hash_table_remove (manager->devices, device_file);
+       g_hash_table_remove (manager->gdk_devices, gdk_device);
+
+       if (device) {
+               g_signal_emit_by_name (manager, "device-removed", device);
+               g_object_unref (device);
+       }
+}
+
+static void
+init_devices (GsdX11DeviceManager *manager,
+             GdkDeviceType        device_type)
+{
+       GList *devices, *l;
+
+       devices = gdk_device_manager_list_devices (manager->device_manager,
+                                                  device_type);
+
+       for (l = devices; l; l = l->next)
+               add_device (manager, l->data);
+
+       g_list_free (devices);
+}
+
+static void
+gsd_x11_device_manager_init (GsdX11DeviceManager *manager)
+{
+       GdkDisplay *display;
+
+       manager->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                 (GDestroyNotify) g_free,
+                                                 (GDestroyNotify) g_object_unref);
+       manager->gdk_devices = g_hash_table_new_full (NULL, NULL, NULL,
+                                                     (GDestroyNotify) g_free);
+
+       display = gdk_display_get_default ();
+       manager->device_manager = gdk_display_get_device_manager (display);
+
+       g_signal_connect_swapped (manager->device_manager, "device-added",
+                                 G_CALLBACK (add_device), manager);
+       g_signal_connect_swapped (manager->device_manager, "device-removed",
+                                 G_CALLBACK (remove_device), manager);
+
+       init_devices (manager, GDK_DEVICE_TYPE_SLAVE);
+       init_devices (manager, GDK_DEVICE_TYPE_FLOATING);
+}
+
+static GList *
+gsd_x11_device_manager_list_devices (GsdDeviceManager *manager,
+                                    GsdDeviceType     type)
+{
+       GsdX11DeviceManager *manager_x11 = GSD_X11_DEVICE_MANAGER (manager);
+       GsdDeviceType device_type;
+       GList *devices = NULL;
+       GHashTableIter iter;
+       GsdDevice *device;
+
+       g_hash_table_iter_init (&iter, manager_x11->devices);
+
+       while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) {
+               device_type = gsd_device_get_device_type (device);
+
+               if ((device_type & type) == type)
+                       devices = g_list_prepend (devices, device);
+       }
+
+       return devices;
+}
+
+static void
+gsd_x11_device_manager_class_init (GsdX11DeviceManagerClass *klass)
+{
+       GsdDeviceManagerClass *manager_class = GSD_DEVICE_MANAGER_CLASS (klass);
+
+       manager_class->list_devices = gsd_x11_device_manager_list_devices;
+}
+
+GdkDevice **
+gsd_x11_device_manager_get_gdk_devices (GsdX11DeviceManager *manager,
+                                       GsdDevice           *device,
+                                       guint               *n_gdk_devices)
+{
+       const gchar *device_node;
+       GPtrArray *gdk_devices;
+       GdkDevice *gdk_device;
+       GHashTableIter iter;
+
+       if (n_gdk_devices)
+               *n_gdk_devices = 0;
+
+       g_return_val_if_fail (GSD_IS_X11_DEVICE_MANAGER (manager), NULL);
+       g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+       gdk_devices = g_ptr_array_new ();
+       g_hash_table_iter_init (&iter, manager->gdk_devices);
+
+       while (g_hash_table_iter_next (&iter, (gpointer *) &gdk_device, (gpointer *) &device_node)) {
+               if (g_strcmp0 (gsd_device_get_device_file (device), device_node) == 0)
+                       g_ptr_array_add (gdk_devices, gdk_device);
+       }
+
+       if (n_gdk_devices)
+               *n_gdk_devices = gdk_devices->len;
+
+       return (GdkDevice **) g_ptr_array_free (gdk_devices, FALSE);
+}
+
+GsdDevice *
+gsd_x11_device_manager_lookup_gdk_device (GsdX11DeviceManager *manager,
+                                         GdkDevice           *gdk_device)
+{
+       const gchar *device_node;
+
+       g_return_val_if_fail (GSD_IS_X11_DEVICE_MANAGER (manager), NULL);
+       g_return_val_if_fail (GDK_IS_DEVICE (gdk_device), NULL);
+
+       device_node = g_hash_table_lookup (manager->gdk_devices, gdk_device);
+
+       if (!device_node)
+               return NULL;
+
+       return g_hash_table_lookup (manager->devices, device_node);
+}
diff --git a/panels/common/gsd-device-manager-x11.h b/panels/common/gsd-device-manager-x11.h
new file mode 100644
index 0000000..876bf50
--- /dev/null
+++ b/panels/common/gsd-device-manager-x11.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __GSD_X11_DEVICE_MANAGER_H__
+#define __GSD_X11_DEVICE_MANAGER_H__
+
+#include <gdk/gdk.h>
+#include "gsd-device-manager.h"
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_X11_DEVICE_MANAGER         (gsd_x11_device_manager_get_type ())
+#define GSD_X11_DEVICE_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_X11_DEVICE_MANAGER, 
GsdX11DeviceManager))
+#define GSD_X11_DEVICE_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_X11_DEVICE_MANAGER, 
GsdX11DeviceManagerClass))
+#define GSD_IS_X11_DEVICE_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_X11_DEVICE_MANAGER))
+#define GSD_IS_X11_DEVICE_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_X11_DEVICE_MANAGER))
+#define GSD_X11_DEVICE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_X11_DEVICE_MANAGER, 
GsdX11DeviceManagerClass))
+
+typedef struct _GsdX11DeviceManager GsdX11DeviceManager;
+typedef struct _GsdX11DeviceManagerClass GsdX11DeviceManagerClass;
+
+GType          gsd_x11_device_manager_get_type         (void) G_GNUC_CONST;
+
+GdkDevice   ** gsd_x11_device_manager_get_gdk_devices   (GsdX11DeviceManager *manager,
+                                                        GsdDevice           *device,
+                                                        guint               *n_gdk_devices);
+GsdDevice    * gsd_x11_device_manager_lookup_gdk_device (GsdX11DeviceManager *manager,
+                                                        GdkDevice           *gdk_device);
+
+G_END_DECLS
+
+#endif /* __GSD_X11_DEVICE_MANAGER_H__ */
diff --git a/panels/common/gsd-device-manager.c b/panels/common/gsd-device-manager.c
new file mode 100644
index 0000000..9272234
--- /dev/null
+++ b/panels/common/gsd-device-manager.c
@@ -0,0 +1,406 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "gsd-device-manager-x11.h"
+#include "gsd-device-manager-udev.h"
+#include "gsd-common-enums.h"
+
+typedef struct _GsdDevicePrivate GsdDevicePrivate;
+typedef struct _GsdDeviceManagerPrivate GsdDeviceManagerPrivate;
+
+struct _GsdDevicePrivate
+{
+       gchar *name;
+       gchar *device_file;
+       gchar *vendor_id;
+       gchar *product_id;
+       GsdDeviceType type;
+       guint width;
+       guint height;
+};
+
+enum {
+       PROP_NAME = 1,
+       PROP_DEVICE_FILE,
+       PROP_VENDOR_ID,
+       PROP_PRODUCT_ID,
+       PROP_TYPE,
+       PROP_WIDTH,
+       PROP_HEIGHT
+};
+
+enum {
+       DEVICE_ADDED,
+       DEVICE_REMOVED,
+       N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsdDevice, gsd_device, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GsdDeviceManager, gsd_device_manager, G_TYPE_OBJECT)
+
+static void
+gsd_device_init (GsdDevice *device)
+{
+}
+
+static void
+gsd_device_set_property (GObject      *object,
+                        guint         prop_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+       GsdDevicePrivate *priv;
+
+       priv = gsd_device_get_instance_private (GSD_DEVICE (object));
+
+       switch (prop_id) {
+       case PROP_NAME:
+               priv->name = g_value_dup_string (value);
+               break;
+       case PROP_DEVICE_FILE:
+               priv->device_file = g_value_dup_string (value);
+               break;
+       case PROP_VENDOR_ID:
+               priv->vendor_id = g_value_dup_string (value);
+               break;
+       case PROP_PRODUCT_ID:
+               priv->product_id = g_value_dup_string (value);
+               break;
+       case PROP_TYPE:
+               priv->type = g_value_get_flags (value);
+               break;
+       case PROP_WIDTH:
+               priv->width = g_value_get_uint (value);
+               break;
+       case PROP_HEIGHT:
+               priv->height = g_value_get_uint (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gsd_device_get_property (GObject    *object,
+                        guint       prop_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+       GsdDevicePrivate *priv;
+
+       priv = gsd_device_get_instance_private (GSD_DEVICE (object));
+
+       switch (prop_id) {
+       case PROP_NAME:
+               g_value_set_string (value, priv->name);
+               break;
+       case PROP_DEVICE_FILE:
+               g_value_set_string (value, priv->device_file);
+               break;
+       case PROP_VENDOR_ID:
+               g_value_set_string (value, priv->vendor_id);
+               break;
+       case PROP_PRODUCT_ID:
+               g_value_set_string (value, priv->product_id);
+               break;
+       case PROP_TYPE:
+               g_value_set_flags (value, priv->type);
+               break;
+       case PROP_WIDTH:
+               g_value_set_uint (value, priv->width);
+               break;
+       case PROP_HEIGHT:
+               g_value_set_uint (value, priv->height);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gsd_device_finalize (GObject *object)
+{
+       GsdDevicePrivate *priv;
+
+       priv = gsd_device_get_instance_private (GSD_DEVICE (object));
+
+       g_free (priv->name);
+       g_free (priv->vendor_id);
+       g_free (priv->product_id);
+       g_free (priv->device_file);
+
+       G_OBJECT_CLASS (gsd_device_parent_class)->finalize (object);
+}
+
+static void
+gsd_device_class_init (GsdDeviceClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->set_property = gsd_device_set_property;
+       object_class->get_property = gsd_device_get_property;
+       object_class->finalize = gsd_device_finalize;
+
+       g_object_class_install_property (object_class,
+                                        PROP_NAME,
+                                        g_param_spec_string ("name",
+                                                             "Name",
+                                                             "Name",
+                                                             NULL,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_DEVICE_FILE,
+                                        g_param_spec_string ("device-file",
+                                                             "Device file",
+                                                             "Device file",
+                                                             NULL,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_VENDOR_ID,
+                                        g_param_spec_string ("vendor-id",
+                                                             "Vendor ID",
+                                                             "Vendor ID",
+                                                             NULL,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_PRODUCT_ID,
+                                        g_param_spec_string ("product-id",
+                                                             "Product ID",
+                                                             "Product ID",
+                                                             NULL,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_TYPE,
+                                        g_param_spec_flags ("type",
+                                                            "Device type",
+                                                            "Device type",
+                                                            GSD_TYPE_DEVICE_TYPE, 0,
+                                                            G_PARAM_READWRITE |
+                                                            G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_WIDTH,
+                                        g_param_spec_uint ("width",
+                                                           "Width",
+                                                           "Width",
+                                                           0, G_MAXUINT, 0,
+                                                           G_PARAM_READWRITE |
+                                                           G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_HEIGHT,
+                                        g_param_spec_uint ("height",
+                                                           "Height",
+                                                           "Height",
+                                                           0, G_MAXUINT, 0,
+                                                           G_PARAM_READWRITE |
+                                                           G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gsd_device_manager_class_init (GsdDeviceManagerClass *klass)
+{
+       signals[DEVICE_ADDED] =
+               g_signal_new ("device-added",
+                             GSD_TYPE_DEVICE_MANAGER,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsdDeviceManagerClass, device_added),
+                             NULL, NULL, NULL,
+                             G_TYPE_NONE, 1,
+                             GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+       signals[DEVICE_REMOVED] =
+               g_signal_new ("device-removed",
+                             GSD_TYPE_DEVICE_MANAGER,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsdDeviceManagerClass, device_removed),
+                             NULL, NULL, NULL,
+                             G_TYPE_NONE, 1,
+                             GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
+}
+
+static void
+gsd_device_manager_init (GsdDeviceManager *manager)
+{
+}
+
+GsdDeviceManager *
+gsd_device_manager_get (void)
+{
+       GsdDeviceManager *manager;
+       GdkScreen *screen;
+
+       screen = gdk_screen_get_default ();
+       g_return_val_if_fail (screen != NULL, NULL);
+
+       manager = g_object_get_data (G_OBJECT (screen), "gsd-device-manager-data");
+
+       if (!manager) {
+#ifdef HAVE_WAYLAND
+               if (!GDK_IS_X11_SCREEN (screen))) {
+                       manager = g_object_new (GSD_TYPE_UDEV_DEVICE_MANAGER,
+                                               NULL);
+               } else
+#endif /* HAVE_WAYLAND */
+               {
+                       manager = g_object_new (GSD_TYPE_X11_DEVICE_MANAGER,
+                                               NULL);
+               }
+
+               g_object_set_data_full (G_OBJECT (screen), "gsd-device-manager-data",
+                                       manager, (GDestroyNotify) g_object_unref);
+       }
+
+       return manager;
+}
+
+GList *
+gsd_device_manager_list_devices (GsdDeviceManager *manager,
+                                GsdDeviceType     type)
+{
+       g_return_val_if_fail (GSD_IS_DEVICE_MANAGER (manager), NULL);
+
+       return GSD_DEVICE_MANAGER_GET_CLASS (manager)->list_devices (manager, type);
+}
+
+GsdDeviceType
+gsd_device_get_device_type (GsdDevice *device)
+{
+       GsdDevicePrivate *priv;
+
+       g_return_val_if_fail (GSD_IS_DEVICE (device), 0);
+
+       priv = gsd_device_get_instance_private (device);
+
+       return priv->type;
+}
+
+void
+gsd_device_get_device_ids (GsdDevice   *device,
+                          const gchar **vendor,
+                          const gchar **product)
+{
+       GsdDevicePrivate *priv;
+
+       g_return_if_fail (GSD_IS_DEVICE (device));
+
+       priv = gsd_device_get_instance_private (device);
+
+       if (vendor)
+               *vendor = priv->vendor_id;
+       if (product)
+               *product = priv->product_id;
+}
+
+GSettings *
+gsd_device_get_settings (GsdDevice *device)
+{
+       const gchar *schema = NULL, *vendor, *product;
+       GSettings *settings;
+       GsdDeviceType type;
+       gchar *path = NULL;
+
+       g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+       type = gsd_device_get_device_type (device);
+
+       if (type & (GSD_DEVICE_TYPE_TOUCHSCREEN | GSD_DEVICE_TYPE_TABLET)) {
+               gsd_device_get_device_ids (device, &vendor, &product);
+
+               if (type & GSD_DEVICE_TYPE_TOUCHSCREEN) {
+                       schema = "org.gnome.desktop.peripherals.touchscreen";
+                       path = g_strdup_printf ("/org/gnome/desktop/peripherals/touchscreens/%s:%s/",
+                                               vendor, product);
+               } else if (type & GSD_DEVICE_TYPE_TABLET) {
+                       schema = "org.gnome.desktop.peripherals.tablet";
+                       path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/",
+                                               vendor, product);
+               }
+       } else if (type & (GSD_DEVICE_TYPE_MOUSE | GSD_DEVICE_TYPE_TOUCHPAD)) {
+               schema = "org.gnome.desktop.peripherals.mouse";
+       } else if (type & GSD_DEVICE_TYPE_KEYBOARD) {
+               schema = "org.gnome.desktop.peripherals.keyboard";
+       } else {
+               return NULL;
+       }
+
+       if (path) {
+               settings = g_settings_new_with_path (schema, path);
+               g_free (path);
+       } else {
+               settings = g_settings_new (schema);
+       }
+
+       return settings;
+}
+
+const gchar *
+gsd_device_get_name (GsdDevice *device)
+{
+       GsdDevicePrivate *priv;
+
+       g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+       priv = gsd_device_get_instance_private (device);
+
+       return priv->name;
+}
+
+const gchar *
+gsd_device_get_device_file (GsdDevice *device)
+{
+       GsdDevicePrivate *priv;
+
+       g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
+
+       priv = gsd_device_get_instance_private (device);
+
+       return priv->device_file;
+}
+
+gboolean
+gsd_device_get_dimensions (GsdDevice *device,
+                          guint     *width,
+                          guint     *height)
+{
+       GsdDevicePrivate *priv;
+
+       g_return_val_if_fail (GSD_IS_DEVICE (device), FALSE);
+
+       priv = gsd_device_get_instance_private (device);
+
+       if (width)
+               *width = priv->width;
+       if (height)
+               *height = priv->height;
+
+       return priv->width > 0 && priv->height > 0;
+}
diff --git a/panels/common/gsd-device-manager.h b/panels/common/gsd-device-manager.h
new file mode 100644
index 0000000..61e5727
--- /dev/null
+++ b/panels/common/gsd-device-manager.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 Carlos Garnacho <carlosg gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSD_DEVICE_MANAGER_H__
+#define __GSD_DEVICE_MANAGER_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_DEVICE                (gsd_device_get_type ())
+#define GSD_DEVICE(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DEVICE, GsdDevice))
+#define GSD_DEVICE_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_DEVICE, GsdDeviceClass))
+#define GSD_IS_DEVICE(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DEVICE))
+#define GSD_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DEVICE))
+#define GSD_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DEVICE, GsdDeviceClass))
+
+#define GSD_TYPE_DEVICE_MANAGER                (gsd_device_manager_get_type ())
+#define GSD_DEVICE_MANAGER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DEVICE_MANAGER, 
GsdDeviceManager))
+#define GSD_DEVICE_MANAGER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_DEVICE_MANAGER, 
GsdDeviceManagerClass))
+#define GSD_IS_DEVICE_MANAGER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DEVICE_MANAGER))
+#define GSD_IS_DEVICE_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DEVICE_MANAGER))
+#define GSD_DEVICE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DEVICE_MANAGER, 
GsdDeviceManagerClass))
+
+typedef struct _GsdDevice GsdDevice;
+typedef struct _GsdDeviceClass GsdDeviceClass;
+typedef struct _GsdDeviceManager GsdDeviceManager;
+typedef struct _GsdDeviceManagerClass GsdDeviceManagerClass;
+
+typedef enum {
+       GSD_DEVICE_TYPE_MOUSE        = 1 << 0,
+       GSD_DEVICE_TYPE_KEYBOARD     = 1 << 1,
+       GSD_DEVICE_TYPE_TOUCHPAD     = 1 << 2,
+       GSD_DEVICE_TYPE_TABLET       = 1 << 3,
+       GSD_DEVICE_TYPE_TOUCHSCREEN  = 1 << 4
+} GsdDeviceType;
+
+struct _GsdDevice {
+       GObject parent_instance;
+};
+
+struct _GsdDeviceClass {
+       GObjectClass parent_class;
+};
+
+struct _GsdDeviceManager
+{
+       GObject parent_instance;
+};
+
+struct _GsdDeviceManagerClass
+{
+       GObjectClass parent_class;
+
+       GList * (* list_devices) (GsdDeviceManager *manager,
+                                 GsdDeviceType     type);
+
+       void (* device_added)   (GsdDeviceManager *manager,
+                                GsdDevice        *device);
+       void (* device_removed) (GsdDeviceManager *manager,
+                                GsdDevice        *device);
+};
+
+GType             gsd_device_get_type                (void) G_GNUC_CONST;
+GType             gsd_device_manager_get_type        (void) G_GNUC_CONST;
+GsdDeviceManager * gsd_device_manager_get            (void);
+GList *                   gsd_device_manager_list_devices    (GsdDeviceManager *manager,
+                                                      GsdDeviceType     type);
+
+const gchar *     gsd_device_get_name        (GsdDevice  *device);
+GsdDeviceType     gsd_device_get_device_type (GsdDevice  *device);
+void              gsd_device_get_device_ids  (GsdDevice    *device,
+                                              const gchar **vendor,
+                                              const gchar **product);
+GSettings *       gsd_device_get_settings    (GsdDevice  *device);
+
+const gchar *     gsd_device_get_device_file (GsdDevice  *device);
+gboolean          gsd_device_get_dimensions  (GsdDevice  *device,
+                                              guint      *width,
+                                              guint      *height);
+
+#ifdef GDK_WINDOWING_X11
+GdkDevice **      gsd_device_get_gdk_devices (GsdDevice *device,
+                                              guint     *n_gdk_devices);
+GsdDevice *       gsd_device_manager_lookup_gdk_device (GsdDeviceManager *manager,
+                                                        GdkDevice        *gdk_device);
+#endif
+
+G_END_DECLS
+
+#endif /* __GSD_DEVICE_MANAGER_H__ */
diff --git a/panels/wacom/gsd-input-helper.c b/panels/common/gsd-input-helper.c
similarity index 80%
rename from panels/wacom/gsd-input-helper.c
rename to panels/common/gsd-input-helper.c
index 6293c62..d3cf40c 100644
--- a/panels/wacom/gsd-input-helper.c
+++ b/panels/common/gsd-input-helper.c
@@ -33,6 +33,11 @@
 #define INPUT_DEVICES_SCHEMA "org.gnome.settings-daemon.peripherals.input-devices"
 #define KEY_HOTPLUG_COMMAND  "hotplug-command"
 
+#define ABS_MT_X "Abs MT Position X"
+#define ABS_MT_Y "Abs MT Position Y"
+#define ABS_X "Abs X"
+#define ABS_Y "Abs Y"
+
 typedef gboolean (* InfoIdentifyFunc) (XDeviceInfo *device_info);
 typedef gboolean (* DeviceIdentifyFunc) (XDevice *xdevice);
 
@@ -264,12 +269,9 @@ device_type_is_present (InfoIdentifyFunc info_func,
                         continue;
 
                 retval = (device_func) (device);
-                if (retval) {
-                        XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device);
+                xdevice_close (device);
+                if (retval)
                         break;
-                }
-
-                XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device);
         }
         XFreeDeviceList (device_info);
 
@@ -498,6 +500,7 @@ run_custom_command (GdkDevice              *device,
                     CustomCommand           command)
 {
         GSettings *settings;
+        GError *error = NULL;
         char *cmd;
         char *argv[7];
         int exit_status;
@@ -530,15 +533,25 @@ run_custom_command (GdkDevice              *device,
         g_free (out);
 
         rc = g_spawn_sync (g_get_home_dir (), argv, NULL, G_SPAWN_SEARCH_PATH,
-                           NULL, NULL, NULL, NULL, &exit_status, NULL);
+                           NULL, NULL, NULL, NULL, &exit_status, &error);
 
-        if (rc == FALSE)
-                g_warning ("Couldn't execute command '%s', verify that this is a valid command.", cmd);
+        if (rc == FALSE) {
+                g_warning ("Couldn't execute command '%s', verify that this is a valid command: %s", cmd, 
error->message);
+                g_clear_error (&error);
+        }
 
         g_free (argv[0]);
         g_free (argv[4]);
 
-        return (exit_status == 1);
+        if (!g_spawn_check_exit_status (exit_status, &error)) {
+                if (g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)) {
+                        g_clear_error (&error);
+                        return TRUE;
+                }
+                g_clear_error (&error);
+        }
+
+        return FALSE;
 }
 
 GList *
@@ -575,3 +588,114 @@ get_disabled_devices (GdkDeviceManager *manager)
 
         return ret;
 }
+
+const char *
+xdevice_get_wacom_tool_type (int deviceid)
+{
+        unsigned long nitems, bytes_after;
+        unsigned char *data = NULL;
+        Atom prop, realtype, tool;
+        GdkDisplay *display;
+        int realformat, rc;
+        const gchar *ret = NULL;
+
+        gdk_error_trap_push ();
+
+        display = gdk_display_get_default ();
+        prop = gdk_x11_get_xatom_by_name ("Wacom Tool Type");
+
+        rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
+                            deviceid, prop, 0, 1, False,
+                            XA_ATOM, &realtype, &realformat, &nitems,
+                            &bytes_after, &data);
+
+        gdk_error_trap_pop_ignored ();
+
+        if (rc != Success || nitems == 0)
+                return NULL;
+
+        if (realtype == XA_ATOM) {
+                tool = *((Atom*) data);
+                ret = gdk_x11_get_xatom_name (tool);
+        }
+
+        XFree (data);
+
+        return ret;
+}
+
+void
+xdevice_close (XDevice *xdevice)
+{
+    gdk_error_trap_push ();
+    XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
+    gdk_error_trap_pop_ignored();
+}
+
+gboolean
+xdevice_get_dimensions (int    deviceid,
+                        guint *width,
+                        guint *height)
+{
+        GdkDisplay *display = gdk_display_get_default ();
+        XIDeviceInfo *info;
+        guint *value, w, h;
+        int i, n_info;
+
+        info = XIQueryDevice (GDK_DISPLAY_XDISPLAY (display), deviceid, &n_info);
+        *width = *height = w = h = 0;
+
+        if (!info)
+                return FALSE;
+
+        for (i = 0; i < info->num_classes; i++) {
+                XIValuatorClassInfo *valuator_info;
+
+                if (info->classes[i]->type != XIValuatorClass)
+                        continue;
+
+                valuator_info = (XIValuatorClassInfo *) info->classes[i];
+
+                if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_X) ||
+                    valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_X))
+                        value = &w;
+                else if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_Y) ||
+                         valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_Y))
+                        value = &h;
+                else
+                        continue;
+
+                *value = (valuator_info->max -  valuator_info->min) * 1000 / valuator_info->resolution;
+        }
+
+        *width = w;
+        *height = h;
+
+        XIFreeDeviceInfo (info);
+
+        return (w != 0 && h != 0);
+}
+
+gboolean
+xdevice_is_libinput (gint deviceid)
+{
+        GdkDisplay *display = gdk_display_get_default ();
+        gulong nitems, bytes_after;
+        gint rc, format;
+        guchar *data;
+        Atom type;
+
+        gdk_error_trap_push ();
+
+        /* Lookup a libinput driver specific property */
+        rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display), deviceid,
+                            gdk_x11_get_xatom_by_name ("libinput Send Events Mode Enabled"),
+                            0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, &data);
+
+        if (rc == Success)
+                XFree (data);
+
+        gdk_error_trap_pop_ignored ();
+
+        return rc == Success && nitems > 0;
+}
diff --git a/panels/wacom/gsd-input-helper.h b/panels/common/gsd-input-helper.h
similarity index 89%
rename from panels/wacom/gsd-input-helper.h
rename to panels/common/gsd-input-helper.h
index 2b19155..f7f568e 100644
--- a/panels/wacom/gsd-input-helper.h
+++ b/panels/common/gsd-input-helper.h
@@ -80,6 +80,15 @@ gboolean  run_custom_command      (GdkDevice              *device,
 GList *   get_disabled_devices     (GdkDeviceManager       *manager);
 char *    xdevice_get_device_node  (int                     deviceid);
 int       xdevice_get_last_tool_id (int                     deviceid);
+gboolean  xdevice_get_dimensions   (int                     deviceid,
+                                    guint                  *width,
+                                    guint                  *height);
+void      xdevice_close      (XDevice                *xdevice);
+
+const char * xdevice_get_wacom_tool_type (int               deviceid);
+
+gboolean  xdevice_is_libinput (gint deviceid);
+
 
 G_END_DECLS
 
diff --git a/panels/mouse/Makefile.am b/panels/mouse/Makefile.am
index 8b705a7..84b5ce7 100644
--- a/panels/mouse/Makefile.am
+++ b/panels/mouse/Makefile.am
@@ -4,6 +4,7 @@ cappletname = mouse
 AM_CPPFLAGS =                                          \
        $(PANEL_CFLAGS)                                 \
        $(MOUSE_PANEL_CFLAGS)                           \
+       -I$(top_srcdir)/panels/common                   \
        -DGNOMELOCALEDIR="\"$(datadir)/locale\""        \
        $(NULL)
 
@@ -19,12 +20,10 @@ libmouse_properties_la_SOURCES =    \
        cc-mouse-panel.h                \
        gnome-mouse-properties.c        \
        gnome-mouse-properties.h        \
-       gsd-input-helper.c              \
-       gsd-input-helper.h              \
        gnome-mouse-test.c              \
        gnome-mouse-test.h
 
-libmouse_properties_la_LIBADD = $(PANEL_LIBS) $(MOUSE_PANEL_LIBS)
+libmouse_properties_la_LIBADD = $(PANEL_LIBS) $(MOUSE_PANEL_LIBS) $(top_builddir)/panels/common/libdevice.la
 
 test_gnome_mouse_test_SOURCES =                \
        $(BUILT_SOURCES)                \
@@ -49,12 +48,6 @@ desktopdir = $(datadir)/applications
 Desktop_in_files = gnome-mouse-panel.desktop.in
 desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
 
-INPUTDIR=$(top_srcdir)/../gnome-settings-daemon/plugins/common/
-INPUTFILES=gsd-input-helper.h gsd-input-helper.c
-update-from-gsd:
-       FILES="$(INPUTFILES)" DIR="$(INPUTDIR)" $(top_srcdir)/update-from-gsd.sh && changed=true ; \
-       git commit -m "mouse: Update from gnome-settings-daemon" $(INPUTFILES)
-
 CLEANFILES = $(Desktop_in_files) $(desktop_DATA)
 EXTRA_DIST = $(resource_files) mouse.gresource.xml
 
diff --git a/panels/wacom/Makefile.am b/panels/wacom/Makefile.am
index 41908b4..21b41d6 100644
--- a/panels/wacom/Makefile.am
+++ b/panels/wacom/Makefile.am
@@ -7,6 +7,7 @@ AM_CPPFLAGS =                                           \
        $(PANEL_CFLAGS)                                 \
        $(WACOM_PANEL_CFLAGS)                           \
        -I$(srcdir)/calibrator                          \
+       -I$(top_srcdir)/panels/common                   \
        -DGNOMELOCALEDIR="\"$(datadir)/locale\""        \
        $(NULL)
 
@@ -30,15 +31,13 @@ libwacom_properties_la_SOURCES =    \
        cc-wacom-stylus-page.h          \
        gsd-wacom-device.c              \
        gsd-wacom-device.h              \
-       gsd-input-helper.c              \
-       gsd-input-helper.h              \
        cc-wacom-nav-button.c           \
        cc-wacom-nav-button.h           \
        cc-wacom-mapping-panel.c        \
        cc-wacom-mapping-panel.h        \
        gsd-enums.h
 
-libwacom_properties_la_LIBADD = $(PANEL_LIBS) $(WACOM_PANEL_LIBS) 
$(builddir)/calibrator/libwacom-calibrator.la
+libwacom_properties_la_LIBADD = $(PANEL_LIBS) $(WACOM_PANEL_LIBS) 
$(builddir)/calibrator/libwacom-calibrator.la $(top_builddir)/panels/common/libdevice.la
 
 noinst_PROGRAMS = test-wacom
 
@@ -59,12 +58,10 @@ test_wacom_SOURCES =                        \
        cc-wacom-mapping-panel.h        \
        gsd-wacom-device.c              \
        gsd-wacom-device.h              \
-       gsd-input-helper.c              \
-       gsd-input-helper.h              \
        gsd-enums.h
 
 test_wacom_CPPFLAGS = $(AM_CPPFLAGS) -DFAKE_AREA
-test_wacom_LDADD = $(PANEL_LIBS) $(WACOM_PANEL_LIBS) $(builddir)/calibrator/libwacom-calibrator-test.la
+test_wacom_LDADD = $(PANEL_LIBS) $(WACOM_PANEL_LIBS) $(builddir)/calibrator/libwacom-calibrator-test.la 
$(top_builddir)/panels/common/libdevice.la
 
 resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies 
$(srcdir)/wacom.gresource.xml)
 cc-wacom-resources.c: wacom.gresource.xml $(resource_files)
@@ -80,12 +77,9 @@ desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
 WACOMDIR=$(top_srcdir)/../gnome-settings-daemon/plugins/wacom/
 WACOMFILES=gsd-wacom-device.c gsd-wacom-device.h gsd-wacom-key-shortcut-button.c 
gsd-wacom-key-shortcut-button.h
-COMMONDIR=$(top_srcdir)/../gnome-settings-daemon/plugins/common/
-COMMONFILES=gsd-input-helper.c gsd-input-helper.h
 update-from-gsd:
        FILES="$(WACOMFILES)" DIR="$(WACOMDIR)" $(top_srcdir)/update-from-gsd.sh && changed=true ; \
-       FILES="$(COMMONFILES)" DIR="$(COMMONDIR)" $(top_srcdir)/update-from-gsd.sh && changed=true ; \
-       git commit -m "wacom: Update from gnome-settings-daemon" $(WACOMFILES) $(COMMONFILES)
+       git commit -m "wacom: Update from gnome-settings-daemon" $(WACOMFILES)
 
 CLEANFILES = $(Desktop_in_files) $(desktop_DATA) $(BUILT_SOURCES)
 EXTRA_DIST = $(resource_files) wacom.gresource.xml
diff --git a/panels/wacom/gsd-wacom-device.c b/panels/wacom/gsd-wacom-device.c
index d656c2f..4c33052 100644
--- a/panels/wacom/gsd-wacom-device.c
+++ b/panels/wacom/gsd-wacom-device.c
@@ -37,6 +37,8 @@
 
 #include "gsd-enums.h"
 #include "gsd-wacom-device.h"
+#include "gsd-device-manager.h"
+#include "gsd-device-manager-x11.h"
 
 #define GSD_WACOM_STYLUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_STYLUS, 
GsdWacomStylusPrivate))
 
@@ -500,11 +502,12 @@ get_device_type (XDeviceInfo *dev)
                                  device, prop, 0, 1, False,
                                  XA_ATOM, &realtype, &realformat, &nitems,
                                  &bytes_after, &data);
-        XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device);
 
         if (gdk_error_trap_pop () || rc != Success || realtype == None)
                 ret = WACOM_TYPE_INVALID;
 
+        xdevice_close (device);
+
         XFree (data);
 
        return ret;
@@ -602,12 +605,19 @@ find_output_by_display (GnomeRRScreen *rr_screen, GsdWacomDevice *device)
        GVariant *display;
        const gchar **edid;
        GnomeRROutput *ret;
+       GsdDevice *gsd_device;
 
        if (device == NULL)
                return NULL;
 
+       gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get 
()),
+                                                              device->priv->gdk_device);
+
+       if (gsd_device == NULL)
+               return NULL;
+
        ret      = NULL;
-       tablet   = device->priv->wacom_settings;
+       tablet   = gsd_device_get_settings (gsd_device);
        display  = g_settings_get_value (tablet, "display");
        edid     = g_variant_get_strv (display, &n);
 
@@ -624,6 +634,7 @@ find_output_by_display (GnomeRRScreen *rr_screen, GsdWacomDevice *device)
 out:
        g_free (edid);
        g_variant_unref (display);
+       g_object_unref (tablet);
 
        return ret;
 }
@@ -690,12 +701,23 @@ set_display_by_output (GsdWacomDevice  *device,
        gsize        nvalues;
        gchar       *o_vendor, *o_product, *o_serial;
        const gchar *values[3];
+       GsdDevice *gsd_device;
+
+       if (device == NULL)
+               return;
+
+       gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get 
()),
+                                                              device->priv->gdk_device);
+
+       if (gsd_device == NULL)
+               return;
 
-       tablet  = gsd_wacom_device_get_settings (device);
+       tablet  = gsd_device_get_settings (gsd_device);
        c_array = g_settings_get_value (tablet, "display");
        g_variant_get_strv (c_array, &nvalues);
        if (nvalues != 3) {
                g_warning ("Unable set set display property. Got %"G_GSIZE_FORMAT" items; expected %d 
items.\n", nvalues, 4);
+               g_object_unref (tablet);
                return;
        }
 
@@ -719,6 +741,7 @@ set_display_by_output (GsdWacomDevice  *device,
        g_free (o_vendor);
        g_free (o_product);
        g_free (o_serial);
+       g_object_unref (tablet);
 }
 
 static GsdWacomRotation
@@ -777,34 +800,6 @@ find_output (GnomeRRScreen  *rr_screen,
        return rr_output;
 }
 
-static void
-calculate_transformation_matrix (const GdkRectangle mapped, const GdkRectangle desktop, float 
matrix[NUM_ELEMS_MATRIX])
-{
-       float x_scale = (float)mapped.x / desktop.width;
-       float y_scale = (float)mapped.y / desktop.height;
-       float width_scale  = (float)mapped.width / desktop.width;
-       float height_scale = (float)mapped.height / desktop.height;
-
-       matrix[0] = width_scale;
-       matrix[1] = 0.0f;
-       matrix[2] = x_scale;
-
-       matrix[3] = 0.0f;
-       matrix[4] = height_scale;
-       matrix[5] = y_scale;
-
-       matrix[6] = 0.0f;
-       matrix[7] = 0.0f;
-       matrix[8] = 1.0f;
-
-       g_debug ("Matrix is %f,%f,%f,%f,%f,%f,%f,%f,%f.",
-                matrix[0], matrix[1], matrix[2],
-                matrix[3], matrix[4], matrix[5],
-                matrix[6], matrix[7], matrix[8]);
-
-       return;
-}
-
 int
 gsd_wacom_device_get_display_monitor (GsdWacomDevice *device)
 {
@@ -854,59 +849,26 @@ gsd_wacom_device_get_display_monitor (GsdWacomDevice *device)
        return gdk_screen_get_monitor_at_point (gdk_screen_get_default (), area[0], area[1]);
 }
 
-gboolean
-gsd_wacom_device_get_display_matrix (GsdWacomDevice *device, float matrix[NUM_ELEMS_MATRIX])
-{
-       int monitor;
-       GdkRectangle display;
-       GdkRectangle desktop;
-       GdkScreen *screen = gdk_screen_get_default ();
-
-       matrix[0] = 1.0f;
-       matrix[1] = 0.0f;
-       matrix[2] = 0.0f;
-       matrix[3] = 0.0f;
-       matrix[4] = 1.0f;
-       matrix[5] = 0.0f;
-       matrix[6] = 0.0f;
-       matrix[7] = 0.0f;
-       matrix[8] = 1.0f;
-
-       monitor = gsd_wacom_device_get_display_monitor (device);
-       if (monitor < 0)
-               return FALSE;
-
-       desktop.x = 0;
-       desktop.y = 0;
-       desktop.width = gdk_screen_get_width (screen);
-       desktop.height = gdk_screen_get_height (screen);
-
-       gdk_screen_get_monitor_geometry (screen, monitor, &display);
-       calculate_transformation_matrix (display, desktop, matrix);
-       return TRUE;
-}
-
 GsdWacomRotation
 gsd_wacom_device_get_display_rotation (GsdWacomDevice *device)
 {
-       GError *error = NULL;
        GnomeRRScreen *rr_screen;
        GnomeRROutput *rr_output;
        GnomeRRRotation rotation = GNOME_RR_ROTATION_0;
 
-       rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
-       if (rr_screen == NULL) {
-               g_warning ("Failed to create GnomeRRScreen: %s", error->message);
-               g_error_free (error);
+       rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), NULL);
+
+       if (rr_screen == NULL)
                return GSD_WACOM_ROTATION_NONE;
-       }
 
-       rr_output = find_output (rr_screen, device);
+       rr_output = find_output_by_display (rr_screen, device);
+
        if (rr_output) {
                GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (rr_output);
                if (crtc)
                        rotation = gnome_rr_crtc_get_current_rotation (crtc);
        }
+
        g_object_unref (rr_screen);
 
        return get_rotation_wacom (rotation);
@@ -1901,7 +1863,7 @@ gsd_wacom_device_get_area (GsdWacomDevice *device)
                                 XA_INTEGER, &realtype, &realformat, &nitems,
                                 &bytes_after, &data);
        if (gdk_error_trap_pop () || rc != Success || realtype == None || bytes_after != 0 || nitems != 4) {
-               XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
+               xdevice_close (xdevice);
                return NULL;
        }
 
@@ -1910,7 +1872,7 @@ gsd_wacom_device_get_area (GsdWacomDevice *device)
                device_area[i] = ((long *)data)[i];
 
        XFree (data);
-       XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
+       xdevice_close (xdevice);
 
        return device_area;
 }
diff --git a/panels/wacom/gsd-wacom-device.h b/panels/wacom/gsd-wacom-device.h
index 5a04e84..dd3d439 100644
--- a/panels/wacom/gsd-wacom-device.h
+++ b/panels/wacom/gsd-wacom-device.h
@@ -26,8 +26,6 @@
 
 G_BEGIN_DECLS
 
-#define NUM_ELEMS_MATRIX 9
-
 #define GSD_TYPE_WACOM_DEVICE         (gsd_wacom_device_get_type ())
 #define GSD_WACOM_DEVICE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_WACOM_DEVICE, 
GsdWacomDevice))
 #define GSD_WACOM_DEVICE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_WACOM_DEVICE, 
GsdWacomDeviceClass))
@@ -147,8 +145,6 @@ GType gsd_wacom_device_get_type     (void);
 void     gsd_wacom_device_set_display         (GsdWacomDevice    *device,
                                                int                monitor);
 gint     gsd_wacom_device_get_display_monitor (GsdWacomDevice *device);
-gboolean gsd_wacom_device_get_display_matrix  (GsdWacomDevice *device,
-                                               float           matrix[NUM_ELEMS_MATRIX]);
 GsdWacomRotation gsd_wacom_device_get_display_rotation (GsdWacomDevice *device);
 
 GsdWacomDevice * gsd_wacom_device_new              (GdkDevice *device);
diff --git a/shell/Makefile.am b/shell/Makefile.am
index c0cb91a..b70393a 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -54,6 +54,7 @@ gnome_control_center_LDADD =                                          \
        $(CHEESE_LIBS)                                                  \
        $(top_builddir)/libgd/libgd.la                                  \
        $(top_builddir)/panels/common/liblanguage.la                    \
+       $(top_builddir)/panels/common/libdevice.la                      \
        $(top_builddir)/panels/background/libbackground.la              \
        $(top_builddir)/panels/color/libcolor.la                        \
        $(top_builddir)/panels/datetime/libdate_time.la                 \


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