[gnome-control-center/wip/garnacho/wayland-tablet: 15/31] wacom: Update to the new data model



commit 1005ea937b115aa351c0170c69c7892b5236705d
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jun 6 14:49:13 2016 +0200

    wacom: Update to the new data model
    
    There's much going on under the hood here:
    - Styli and tablets are now in split views, as per the mockups.
    - CcWacomDevice and CcWacomTool are now in use, with the subsequent
      API use changes. Moreover, using these objects means using the
      newer schemas in gsettings-desktop-schemas, so there had to be
      changes in the settings we store too.
    - We now use CcTabletToolMap, plus listen to tool proximity events,
      populating the "Stylus" sub-pane with those.

 panels/wacom/cc-wacom-mapping-panel.c |  100 +++++-----
 panels/wacom/cc-wacom-mapping-panel.h |    3 +-
 panels/wacom/cc-wacom-page.c          |  246 ++++++++---------------
 panels/wacom/cc-wacom-page.h          |   14 +-
 panels/wacom/cc-wacom-panel.c         |  366 +++++++++++++++++++++++++++------
 panels/wacom/cc-wacom-stylus-page.c   |  107 ++++------
 panels/wacom/cc-wacom-stylus-page.h   |    6 +-
 7 files changed, 488 insertions(+), 354 deletions(-)
---
diff --git a/panels/wacom/cc-wacom-mapping-panel.c b/panels/wacom/cc-wacom-mapping-panel.c
index 13c0d65..10758bd 100644
--- a/panels/wacom/cc-wacom-mapping-panel.c
+++ b/panels/wacom/cc-wacom-mapping-panel.c
@@ -28,7 +28,7 @@
 
 #include <string.h>
 
-#include "gsd-wacom-device.h"
+#include "cc-wacom-device.h"
 #include "cc-wacom-mapping-panel.h"
 
 G_DEFINE_TYPE (CcWacomMappingPanel, cc_wacom_mapping_panel, GTK_TYPE_BOX)
@@ -38,17 +38,19 @@ G_DEFINE_TYPE (CcWacomMappingPanel, cc_wacom_mapping_panel, GTK_TYPE_BOX)
 
 struct _CcWacomMappingPanelPrivate
 {
-       GsdWacomDevice *device;
+       CcWacomDevice  *device;
        GtkWidget      *label;
        GtkWidget      *combobox;
        GtkWidget      *checkbutton;
        GtkWidget      *aspectlabel;
        GtkWidget      *aspectswitch;
+
+       GnomeRRScreen  *rr_screen;
 };
 
 enum {
        MONITOR_NAME_COLUMN,
-       MONITOR_NUM_COLUMN,
+       MONITOR_PTR_COLUMN,
        MONITOR_NUM_COLUMNS
 };
 
@@ -56,19 +58,6 @@ static void combobox_changed_cb (GtkWidget *widget, CcWacomMappingPanel *self);
 static void checkbutton_toggled_cb (GtkWidget *widget, CcWacomMappingPanel *self);
 static void aspectswitch_toggled_cb (GtkWidget *widget, GParamSpec *pspec, CcWacomMappingPanel *self);
 
-static GnomeRROutputInfo**
-get_rr_outputs (void)
-{
-       GError *error = NULL;
-       GnomeRRScreen *rr_screen;
-       GnomeRRConfig *rr_config;
-
-       /* TODO: Check the value of 'error' */
-       rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
-       rr_config = gnome_rr_config_new_current (rr_screen, &error);
-       return gnome_rr_config_get_outputs (rr_config);
-}
-
 static void
 set_combobox_sensitive (CcWacomMappingPanel *self,
                        gboolean             sensitive)
@@ -90,14 +79,12 @@ static void
 update_monitor_chooser (CcWacomMappingPanel *self)
 {
        GtkListStore *store;
-       GnomeRROutputInfo **outputs;
-       GdkRectangle geom;
+       GnomeRROutput **outputs;
        GSettings *settings;
-       gint monitor;
-       gboolean single_mon;
+       GnomeRROutput *cur_output;
        guint i;
 
-       store = gtk_list_store_new (MONITOR_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
+       store = gtk_list_store_new (MONITOR_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
        gtk_combo_box_set_model (GTK_COMBO_BOX(self->priv->combobox), GTK_TREE_MODEL(store));
 
        if (self->priv->device == NULL) {
@@ -106,47 +93,43 @@ update_monitor_chooser (CcWacomMappingPanel *self)
                return;
        }
 
-       settings = gsd_wacom_device_get_settings (self->priv->device);
-       monitor = gsd_wacom_device_get_display_monitor (self->priv->device);
-       single_mon = (monitor != GSD_WACOM_SET_ALL_MONITORS);
+       settings = cc_wacom_device_get_settings (self->priv->device);
+       cur_output = cc_wacom_device_get_output (self->priv->device,
+                                                self->priv->rr_screen);
 
        g_signal_handlers_block_by_func (G_OBJECT (self->priv->checkbutton), checkbutton_toggled_cb, self);
-       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(self->priv->checkbutton), single_mon);
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(self->priv->checkbutton), cur_output != NULL);
        g_signal_handlers_unblock_by_func (G_OBJECT (self->priv->checkbutton), checkbutton_toggled_cb, self);
 
        g_signal_handlers_block_by_func (G_OBJECT (self->priv->aspectswitch), aspectswitch_toggled_cb, self);
        gtk_switch_set_active (GTK_SWITCH(self->priv->aspectswitch), g_settings_get_boolean (settings, 
"keep-aspect"));
        g_signal_handlers_unblock_by_func (G_OBJECT (self->priv->aspectswitch), aspectswitch_toggled_cb, 
self);
 
-       /* FIXME: does this break screen tablets? What's the default
-        * for unconfigured tablets? */
-       if (monitor < 0)
-               monitor = 0;
-       gdk_screen_get_monitor_geometry (gdk_screen_get_default (), monitor, &geom);
-
-       outputs = get_rr_outputs ();
-       if (outputs == NULL)
+       if (!self->priv->rr_screen) {
+               cur_output = NULL;
                goto bail;
+       }
+
+       outputs = gnome_rr_screen_list_outputs (self->priv->rr_screen);
 
        for (i = 0; outputs[i] != NULL; i++) {
-               GnomeRROutputInfo *output = outputs[i];
+               GnomeRROutput *output = outputs[i];
+               GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (output);
 
-               if (gnome_rr_output_info_is_active (output)) {
+               /* Output is turned on? */
+               if (crtc && gnome_rr_crtc_get_current_mode (crtc) != NULL) {
                        GtkTreeIter iter;
-                       gchar *name, *disp_name, *text;
-                       int x, y, w, h;
-                       int mon_at_point;
+                       const gchar *name, *disp_name;
+                       gchar *text;
 
-                       name = gnome_rr_output_info_get_name (output);
-                       disp_name = gnome_rr_output_info_get_display_name (output);
+                       name = gnome_rr_output_get_name (output);
+                       disp_name = gnome_rr_output_get_display_name (output);
                        text = g_strdup_printf ("%s (%s)", name, disp_name);
 
-                       gnome_rr_output_info_get_geometry (output, &x, &y, &w, &h);
-                       mon_at_point = gdk_screen_get_monitor_at_point (gdk_screen_get_default (), x, y);
                        gtk_list_store_append (store, &iter);
-                       gtk_list_store_set (store, &iter, MONITOR_NAME_COLUMN, text, MONITOR_NUM_COLUMN, 
mon_at_point, -1);
+                       gtk_list_store_set (store, &iter, MONITOR_NAME_COLUMN, text, MONITOR_PTR_COLUMN, 
output, -1);
 
-                       if (x == geom.x && y == geom.y && w == geom.width && h == geom.height) {
+                       if (i == 0 || output == cur_output) {
                                g_signal_handlers_block_by_func (G_OBJECT (self->priv->combobox), 
combobox_changed_cb, self);
                                gtk_combo_box_set_active_iter (GTK_COMBO_BOX(self->priv->combobox), &iter);
                                g_signal_handlers_unblock_by_func (G_OBJECT (self->priv->combobox), 
combobox_changed_cb, self);
@@ -157,7 +140,7 @@ update_monitor_chooser (CcWacomMappingPanel *self)
        }
 
 bail:
-       set_combobox_sensitive (self, single_mon);
+       set_combobox_sensitive (self, cur_output != NULL);
        g_object_unref (store);
 }
 
@@ -170,7 +153,10 @@ update_ui (CcWacomMappingPanel *self)
        } else {
                gboolean is_screen_tablet;
 
-               is_screen_tablet = gsd_wacom_device_is_screen_tablet (self->priv->device);
+               is_screen_tablet =
+                       cc_wacom_device_get_integration_flags (self->priv->device) &
+                       WACOM_DEVICE_INTEGRATED_DISPLAY;
+
                gtk_widget_set_sensitive (GTK_WIDGET(self->priv->checkbutton), !is_screen_tablet);
                gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON(self->priv->checkbutton), FALSE);
        }
@@ -181,7 +167,7 @@ update_ui (CcWacomMappingPanel *self)
 static void
 update_mapping (CcWacomMappingPanel *self)
 {
-       int monitor = GSD_WACOM_SET_ALL_MONITORS;
+       GnomeRROutput *output = NULL;
 
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->checkbutton))) {
                GtkTreeIter iter;
@@ -194,15 +180,15 @@ update_mapping (CcWacomMappingPanel *self)
                        return;
                }
 
-               gtk_tree_model_get (model, &iter, MONITOR_NAME_COLUMN, &name, MONITOR_NUM_COLUMN, &monitor, 
-1);
+               gtk_tree_model_get (model, &iter, MONITOR_NAME_COLUMN, &name, MONITOR_PTR_COLUMN, &output, 
-1);
        }
 
-       gsd_wacom_device_set_display (self->priv->device, monitor);
+       cc_wacom_device_set_output (self->priv->device, output);
 }
 
 void
 cc_wacom_mapping_panel_set_device (CcWacomMappingPanel *self,
-                                   GsdWacomDevice *device)
+                                   CcWacomDevice       *device)
 {
        self->priv->device = device;
        update_ui (self);
@@ -228,7 +214,7 @@ aspectswitch_toggled_cb (GtkWidget           *widget,
 {
        GSettings *settings;
 
-       settings = gsd_wacom_device_get_settings (self->priv->device);
+       settings = cc_wacom_device_get_settings (self->priv->device);
        g_settings_set_boolean (settings,
                                "keep-aspect",
                                gtk_switch_get_active (GTK_SWITCH (widget)));
@@ -247,9 +233,17 @@ cc_wacom_mapping_panel_init (CcWacomMappingPanel *self)
        CcWacomMappingPanelPrivate *priv;
        GtkWidget *vbox, *grid;
        GtkCellRenderer *renderer;
+       GError *error = NULL;
 
        priv = self->priv = WACOM_MAPPING_PANEL_PRIVATE (self);
 
+       priv->rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
+
+       if (error) {
+               g_warning ("Could not get RR screen: %s", error->message);
+               g_error_free (error);
+       }
+
        vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
        gtk_container_add (GTK_CONTAINER (self), vbox);
        gtk_container_set_border_width (GTK_CONTAINER (self), 12);
@@ -338,6 +332,10 @@ cc_wacom_mapping_panel_set_property (GObject      *object,
 static void
 cc_wacom_mapping_panel_dispose (GObject *object)
 {
+       CcWacomMappingPanel *self = CC_WACOM_MAPPING_PANEL (object);
+
+       g_clear_object (&self->priv->rr_screen);
+
        G_OBJECT_CLASS (cc_wacom_mapping_panel_parent_class)->dispose (object);
 }
 
diff --git a/panels/wacom/cc-wacom-mapping-panel.h b/panels/wacom/cc-wacom-mapping-panel.h
index 8bf891d..ae9dabb 100644
--- a/panels/wacom/cc-wacom-mapping-panel.h
+++ b/panels/wacom/cc-wacom-mapping-panel.h
@@ -22,6 +22,7 @@
 #define CC_WACOM_MAPPING_PANEL_H_
 
 #include <gtk/gtk.h>
+#include "cc-wacom-device.h"
 
 G_BEGIN_DECLS
 
@@ -69,7 +70,7 @@ GtkWidget * cc_wacom_mapping_panel_new (void);
 
 
 void cc_wacom_mapping_panel_set_device (CcWacomMappingPanel *self,
-                                        GsdWacomDevice *device);
+                                        CcWacomDevice       *device);
 
 G_END_DECLS
 
diff --git a/panels/wacom/cc-wacom-page.c b/panels/wacom/cc-wacom-page.c
index fc31328..f1d0d2c 100644
--- a/panels/wacom/cc-wacom-page.c
+++ b/panels/wacom/cc-wacom-page.c
@@ -27,7 +27,9 @@
 
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
+#include <gdesktop-enums.h>
 
+#include "cc-wacom-device.h"
 #include "cc-wacom-button-row.h"
 #include "cc-wacom-page.h"
 #include "cc-wacom-nav-button.h"
@@ -61,13 +63,16 @@ enum {
 struct _CcWacomPagePrivate
 {
        CcWacomPanel   *panel;
-       GsdWacomDevice *stylus, *pad;
+       CcWacomDevice  *stylus;
+       CcWacomDevice  *pad;
        GtkBuilder     *builder;
        GtkWidget      *nav;
        GtkWidget      *notebook;
        CalibArea      *area;
        GSettings      *wacom_settings;
 
+       GtkSizeGroup   *header_group;
+
        /* Button mapping */
        GtkBuilder     *mapping_builder;
        GtkWidget      *button_map;
@@ -112,13 +117,14 @@ update_tablet_ui (CcWacomPage *page,
                  int          layout);
 
 static int
-get_layout_type (GsdWacomDevice *device)
+get_layout_type (CcWacomDevice *device)
 {
        int layout;
 
-       if (gsd_wacom_device_is_screen_tablet (device))
+       if (cc_wacom_device_get_integration_flags (device) &
+           (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM))
                layout = LAYOUT_SCREEN;
-       else if (gsd_wacom_device_reversible (device))
+       else if (cc_wacom_device_is_reversible (device))
                layout = LAYOUT_REVERSIBLE;
        else
                layout = LAYOUT_NORMAL;
@@ -161,6 +167,8 @@ set_calibration (GsdWacomDevice *device,
                 display_width, display_height);
 }
 
+#if 0
+
 static void
 finish_calibration (CalibArea *area,
                    gpointer   user_data)
@@ -299,11 +307,15 @@ calibrate (CcWacomPage *page)
        gtk_widget_set_sensitive (WID ("button-calibrate"), FALSE);
 }
 
+#endif
+
 static void
 calibrate_button_clicked_cb (GtkButton   *button,
                             CcWacomPage *page)
 {
+#if 0
        calibrate (page);
+#endif
 }
 
 /* This avoids us crashing when a newer version of
@@ -332,6 +344,7 @@ create_row_from_button (GtkWidget            *list_box,
 static void
 setup_button_mapping (CcWacomPage *page)
 {
+#if 0
        CcWacomPagePrivate *priv;
        GList              *list, *l;
        GtkWidget          *list_box = NULL;
@@ -361,6 +374,7 @@ setup_button_mapping (CcWacomPage *page)
                create_row_from_button (list_box, button, 0);
        }
        g_list_free (list);
+#endif
 }
 
 static void
@@ -441,14 +455,18 @@ set_osd_visibility_cb (GObject      *source_object,
 }
 
 static void
-set_osd_visibility (CcWacomPage *page,
-                   guint32      device_id)
+set_osd_visibility (CcWacomPage *page)
 {
        CcWacomPagePrivate *priv;
        GDBusProxy         *proxy;
+       GsdDevice          *gsd_device;
+       const gchar        *device_path;
 
        priv = page->priv;
        proxy = cc_wacom_panel_get_gsd_wacom_bus_proxy (priv->panel);
+       gsd_device = cc_wacom_device_get_device (priv->pad);
+
+       device_path = gsd_device_get_device_file (gsd_device);
 
        if (proxy == NULL) {
                show_button_mapping_dialog (page);
@@ -457,7 +475,7 @@ set_osd_visibility (CcWacomPage *page,
 
        g_dbus_proxy_call (proxy,
                           "SetOSDVisibility",
-                          g_variant_new ("(ubb)", device_id, TRUE, TRUE),
+                          g_variant_new ("(obb)", device_path, TRUE, TRUE),
                           G_DBUS_CALL_FLAGS_NONE,
                           -1,
                           priv->cancellable,
@@ -469,28 +487,7 @@ static void
 map_buttons_button_clicked_cb (GtkButton   *button,
                               CcWacomPage *page)
 {
-       CcWacomPagePrivate *priv;
-       GdkDevice *gdk_device = NULL;
-       guint32 device_id;
-        const gchar *layout_path;
-
-       priv = page->priv;
-
-       gdk_device = gsd_wacom_device_get_gdk_device (priv->pad);
-
-       g_return_if_fail (gdk_device != NULL);
-
-       g_object_get (gdk_device, "device-id", &device_id, NULL);
-
-       /* Check if the OSD should be shown instead of the button mapping dialod */
-        layout_path = gsd_wacom_device_get_layout_path (page->priv->pad);
-        if (layout_path && g_file_test (layout_path, G_FILE_TEST_EXISTS)) {
-               set_osd_visibility (page, device_id);
-               return;
-       }
-
-       g_message ("Couldn't find a layout for '%s'. Launching the button mapping dialog.", 
gsd_wacom_device_get_name (priv->pad));
-       show_button_mapping_dialog (page);
+       set_osd_visibility (page);
 }
 
 static void
@@ -540,11 +537,10 @@ display_mapping_button_clicked_cb (GtkButton   *button,
 static void
 tabletmode_changed_cb (GtkComboBox *combo, gpointer user_data)
 {
-       CcWacomPagePrivate      *priv   = CC_WACOM_PAGE(user_data)->priv;
-       GtkListStore            *liststore;
-       GtkTreeIter             iter;
-       gint                    mode;
-       gboolean                is_absolute;
+       CcWacomPagePrivate *priv = CC_WACOM_PAGE (user_data)->priv;
+       GtkListStore *liststore;
+       GtkTreeIter iter;
+       gint mode;
 
        if (!gtk_combo_box_get_active_iter (combo, &iter))
                return;
@@ -554,66 +550,40 @@ tabletmode_changed_cb (GtkComboBox *combo, gpointer user_data)
                            MODENUMBER_COLUMN, &mode,
                            -1);
 
-       is_absolute = (mode == MODE_ABSOLUTE);
-       g_settings_set_boolean (priv->wacom_settings, "is-absolute", is_absolute);
-}
-
-static const gchar*
-opposite_rotation (const gchar *rotation)
-{
-       /* Order matters here, if not found we return "none"  */
-       static const gchar *rotations[] = { "half", "cw", "none", "ccw" };
-       guint i, n;
-
-       n = G_N_ELEMENTS (rotations);
-       for (i = 0; i < n; i++) {
-               if (strcmp (rotation, rotations[i]) == 0)
-                       break;
-       }
-
-       return rotations[(i + n / 2) % n];
+       g_settings_set_enum (priv->wacom_settings, "mapping", mode);
 }
 
 static void
 left_handed_toggled_cb (GtkSwitch *sw, GParamSpec *pspec, gpointer *user_data)
 {
-       CcWacomPagePrivate      *priv = CC_WACOM_PAGE(user_data)->priv;
-       GsdWacomDevice          *device = priv->stylus;
-       GsdWacomRotation        display_rotation;
-       const gchar*            rotation;
-
-       display_rotation = gsd_wacom_device_get_display_rotation (device);
-       rotation = gsd_wacom_device_rotation_type_to_name (display_rotation);
-       if (gtk_switch_get_active (sw))
-               rotation = opposite_rotation (rotation);
+       CcWacomPagePrivate *priv = CC_WACOM_PAGE (user_data)->priv;
+       gboolean left_handed;
 
-       g_settings_set_string (priv->wacom_settings, "rotation", rotation);
+       left_handed = gtk_switch_get_active (sw);
+       g_settings_set_boolean (priv->wacom_settings, "left-handed", left_handed);
 }
 
 static void
 set_left_handed_from_gsettings (CcWacomPage *page)
 {
-       CcWacomPagePrivate      *priv = CC_WACOM_PAGE(page)->priv;
-       GsdWacomDevice          *device = priv->stylus;
-       GsdWacomRotation        display_rotation;
-       const gchar*            rotation;
-
-       display_rotation = gsd_wacom_device_get_display_rotation (device);
-       rotation = g_settings_get_string (priv->wacom_settings, "rotation");
-       if (strcmp (rotation, gsd_wacom_device_rotation_type_to_name (display_rotation)) != 0)
-               gtk_switch_set_active (GTK_SWITCH (WID ("switch-left-handed")), TRUE);
+       CcWacomPagePrivate *priv = CC_WACOM_PAGE (page)->priv;
+       gboolean left_handed;
+
+       left_handed = g_settings_get_boolean (priv->wacom_settings, "left-handed");
+       gtk_switch_set_active (GTK_SWITCH (WID ("switch-left-handed")), left_handed);
 }
 
 static void
-set_mode_from_gsettings (GtkComboBox *combo, CcWacomPage *page)
+set_mode_from_gsettings (GtkComboBox *combo,
+                        CcWacomPage *page)
 {
-       CcWacomPagePrivate      *priv = page->priv;
-       gboolean                is_absolute;
+       CcWacomPagePrivate *priv = page->priv;
+       GDesktopTabletMapping mapping;
 
-       is_absolute = g_settings_get_boolean (priv->wacom_settings, "is-absolute");
+       mapping = g_settings_get_enum (priv->wacom_settings, "mapping");
 
        /* this must be kept in sync with the .ui file */
-       gtk_combo_box_set_active (combo, is_absolute ? MODE_ABSOLUTE : MODE_RELATIVE);
+       gtk_combo_box_set_active (combo, mapping);
 }
 
 static void
@@ -701,6 +671,12 @@ cc_wacom_page_dispose (GObject *object)
                priv->builder = NULL;
        }
 
+       if (priv->header_group) {
+               g_object_unref (priv->header_group);
+               priv->header_group = NULL;
+       }
+
+
        priv->panel = NULL;
 
        G_OBJECT_CLASS (cc_wacom_page_parent_class)->dispose (object);
@@ -754,8 +730,6 @@ cc_wacom_page_init (CcWacomPage *self)
        gtk_container_add (GTK_CONTAINER (self), box);
        gtk_widget_set_vexpand (GTK_WIDGET (box), TRUE);
 
-       self->priv->notebook = WID ("stylus-notebook");
-
        g_signal_connect (WID ("button-calibrate"), "clicked",
                          G_CALLBACK (calibrate_button_clicked_cb), self);
        g_signal_connect (WID ("map-buttons-button"), "clicked",
@@ -808,65 +782,6 @@ typedef struct {
 } StylusPair;
 
 static void
-add_styli (CcWacomPage *page)
-{
-       GList *styli, *l;
-       CcWacomPagePrivate *priv;
-
-       priv = page->priv;
-
-       styli = gsd_wacom_device_list_styli (priv->stylus);
-
-       for (l = styli; l; l = l->next) {
-               GsdWacomStylus *stylus;
-               GtkWidget *page;
-
-               stylus = l->data;
-
-               if (gsd_wacom_stylus_get_stylus_type (stylus) == WACOM_STYLUS_TYPE_PUCK)
-                       continue;
-
-               page = cc_wacom_stylus_page_new (stylus);
-               cc_wacom_stylus_page_set_navigation (CC_WACOM_STYLUS_PAGE (page), GTK_NOTEBOOK 
(priv->notebook));
-               gtk_widget_show (page);
-               gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), page, NULL);
-       }
-       g_list_free (styli);
-}
-
-static void
-stylus_changed (GsdWacomDevice *device,
-               GParamSpec     *pspec,
-               CcWacomPage    *page)
-{
-       GsdWacomStylus *stylus;
-       CcWacomPagePrivate *priv;
-       int num_pages;
-       guint i;
-
-       priv = page->priv;
-       g_object_get (G_OBJECT (device), "last-stylus", &stylus, NULL);
-       if (stylus == NULL)
-               return;
-
-       num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
-       for (i = 0; i < num_pages; i++) {
-               GsdWacomStylus *s;
-               CcWacomStylusPage *spage;
-
-               spage = CC_WACOM_STYLUS_PAGE (gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), i));
-               s = cc_wacom_stylus_page_get_stylus (spage);
-               if (s == stylus) {
-                       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), i);
-                       return;
-               }
-       }
-
-       g_warning ("Failed to find the page for stylus '%s'",
-                  gsd_wacom_stylus_get_name (stylus));
-}
-
-static void
 remove_left_handed (CcWacomPagePrivate *priv)
 {
        gtk_widget_destroy (WID ("label-left-handed"));
@@ -896,20 +811,32 @@ remove_mouse_link (CcWacomPagePrivate *priv)
 static gboolean
 has_monitor (CcWacomPage *page)
 {
-       return gsd_wacom_device_get_display_monitor (page->priv->stylus) >= 0;
+       WacomIntegrationFlags integration_flags;
+       CcWacomPagePrivate *priv;
+
+       priv = page->priv;
+       integration_flags = cc_wacom_device_get_integration_flags (priv->stylus);
+
+       return ((integration_flags &
+                (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM)) != 0);
 }
 
 static void
 update_tablet_ui (CcWacomPage *page,
                  int          layout)
 {
+       WacomIntegrationFlags integration_flags;
        CcWacomPagePrivate *priv;
-       GsdWacomStylus *puck;
 
        priv = page->priv;
-       puck = gsd_wacom_device_get_stylus_for_type (priv->stylus, WACOM_STYLUS_TYPE_PUCK);
-       if (puck == NULL)
+
+       integration_flags = cc_wacom_device_get_integration_flags (priv->stylus);
+
+       if ((integration_flags &
+            (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM)) != 0) {
+               /* FIXME: Check we've got a puck, or a corresponding touchpad device */
                remove_mouse_link (priv);
+       }
 
        /* Hide the pad buttons if no pad is present */
        gtk_widget_set_visible (WID ("map-buttons-button"), priv->pad != NULL);
@@ -946,9 +873,9 @@ update_tablet_ui (CcWacomPage *page,
 }
 
 gboolean
-cc_wacom_page_update_tools (CcWacomPage    *page,
-                           GsdWacomDevice *stylus,
-                           GsdWacomDevice *pad)
+cc_wacom_page_update_tools (CcWacomPage   *page,
+                           CcWacomDevice *stylus,
+                           CcWacomDevice *pad)
 {
        CcWacomPagePrivate *priv;
        int layout;
@@ -971,18 +898,15 @@ cc_wacom_page_update_tools (CcWacomPage    *page,
 }
 
 GtkWidget *
-cc_wacom_page_new (CcWacomPanel   *panel,
-                  GsdWacomDevice *stylus,
-                  GsdWacomDevice *pad)
+cc_wacom_page_new (CcWacomPanel  *panel,
+                  CcWacomDevice *stylus,
+                  CcWacomDevice *pad)
 {
        CcWacomPage *page;
        CcWacomPagePrivate *priv;
 
-       g_return_val_if_fail (GSD_IS_WACOM_DEVICE (stylus), NULL);
-       g_return_val_if_fail (gsd_wacom_device_get_device_type (stylus) == WACOM_TYPE_STYLUS, NULL);
-
-       if (pad != NULL)
-               g_return_val_if_fail (gsd_wacom_device_get_device_type (pad) == WACOM_TYPE_PAD, NULL);
+       g_return_val_if_fail (CC_IS_WACOM_DEVICE (stylus), NULL);
+       g_return_val_if_fail (!pad || CC_IS_WACOM_DEVICE (pad), NULL);
 
        page = g_object_new (CC_TYPE_WACOM_PAGE, NULL);
 
@@ -992,26 +916,18 @@ cc_wacom_page_new (CcWacomPanel   *panel,
        cc_wacom_page_update_tools (page, stylus, pad);
 
        /* FIXME move this to construct */
-       priv->wacom_settings  = gsd_wacom_device_get_settings (stylus);
+       priv->wacom_settings  = cc_wacom_device_get_settings (stylus);
        set_mode_from_gsettings (GTK_COMBO_BOX (WID ("combo-tabletmode")), page);
 
        /* Tablet name */
-       gtk_label_set_text (GTK_LABEL (WID ("label-tabletmodel")), gsd_wacom_device_get_name (stylus));
+       gtk_label_set_text (GTK_LABEL (WID ("label-tabletmodel")), cc_wacom_device_get_name (stylus));
 
        /* Left-handedness */
-       if (gsd_wacom_device_reversible (stylus))
+       if (cc_wacom_device_is_reversible (stylus))
                set_left_handed_from_gsettings (page);
 
        /* Tablet icon */
-       set_icon_name (page, "image-tablet", gsd_wacom_device_get_icon_name (stylus));
-
-       /* Add styli */
-       add_styli (page);
-
-       /* Get the current stylus and switch to its page */
-       stylus_changed (priv->stylus, NULL, page);
-       g_signal_connect (G_OBJECT (priv->stylus), "notify::last-stylus",
-                         G_CALLBACK (stylus_changed), page);
+       set_icon_name (page, "image-tablet", cc_wacom_device_get_icon_name (stylus));
 
        return GTK_WIDGET (page);
 }
@@ -1038,7 +954,9 @@ cc_wacom_page_calibrate (CcWacomPage *page)
 {
        g_return_if_fail (CC_IS_WACOM_PAGE (page));
 
+#if 0
        calibrate (page);
+#endif
 }
 
 gboolean
diff --git a/panels/wacom/cc-wacom-page.h b/panels/wacom/cc-wacom-page.h
index 9cb24f3..65cd12b 100644
--- a/panels/wacom/cc-wacom-page.h
+++ b/panels/wacom/cc-wacom-page.h
@@ -24,7 +24,7 @@
 
 #include <gtk/gtk.h>
 #include "cc-wacom-panel.h"
-#include "gsd-wacom-device.h"
+#include "cc-wacom-device.h"
 
 G_BEGIN_DECLS
 
@@ -68,13 +68,13 @@ struct _CcWacomPageClass
 
 GType cc_wacom_page_get_type (void) G_GNUC_CONST;
 
-GtkWidget * cc_wacom_page_new (CcWacomPanel   *panel,
-                              GsdWacomDevice *stylus,
-                              GsdWacomDevice *pad);
+GtkWidget * cc_wacom_page_new (CcWacomPanel  *panel,
+                              CcWacomDevice *stylus,
+                              CcWacomDevice *pad);
 
-gboolean cc_wacom_page_update_tools (CcWacomPage    *page,
-                                    GsdWacomDevice *stylus,
-                                    GsdWacomDevice *pad);
+gboolean cc_wacom_page_update_tools (CcWacomPage   *page,
+                                    CcWacomDevice *stylus,
+                                    CcWacomDevice *pad);
 
 void cc_wacom_page_set_navigation (CcWacomPage *page,
                                   GtkNotebook *notebook,
diff --git a/panels/wacom/cc-wacom-panel.c b/panels/wacom/cc-wacom-panel.c
index c92c7bc..5df76b0 100644
--- a/panels/wacom/cc-wacom-panel.c
+++ b/panels/wacom/cc-wacom-panel.c
@@ -23,13 +23,21 @@
 
 #include <string.h>
 #include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
 
 #include "cc-wacom-panel.h"
 #include "cc-wacom-page.h"
+#include "cc-wacom-stylus-page.h"
 #include "cc-wacom-resources.h"
 #include "cc-drawing-area.h"
+#include "cc-tablet-tool-map.h"
+#include "gsd-device-manager.h"
 #include "gsd-wacom-device.h"
 
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/gdkwayland.h>
+#endif
+
 #define WID(x) (GtkWidget *) gtk_builder_get_object (priv->builder, x)
 
 CC_PANEL_REGISTER (CcWacomPanel, cc_wacom_panel)
@@ -40,15 +48,21 @@ CC_PANEL_REGISTER (CcWacomPanel, cc_wacom_panel)
 struct _CcWacomPanelPrivate
 {
        GtkBuilder       *builder;
-       GtkWidget        *notebook;
+       GtkWidget        *stack;
+       GtkWidget        *switcher;
+       GtkWidget        *tablet_notebook;
+       GtkWidget        *stylus_notebook;
        GtkWidget        *test_popover;
        GtkWidget        *test_draw_area;
-       GHashTable       *devices; /* key=GdkDevice, value=GsdWacomDevice */
+       GHashTable       *devices; /* key=GsdDevice, value=CcWacomDevice */
        GHashTable       *pages; /* key=device name, value=GtkWidget */
-       GdkDeviceManager *manager;
+       GHashTable       *stylus_pages; /* key=CcWacomTool, value=GtkWidget */
+       GsdDeviceManager *manager;
        guint             device_added_id;
        guint             device_removed_id;
 
+       CcTabletToolMap  *tablet_tool_map;
+
        /* DBus */
        GCancellable  *cancellable;
        GDBusProxy    *proxy;
@@ -56,8 +70,8 @@ struct _CcWacomPanelPrivate
 
 typedef struct {
        const char *name;
-       GsdWacomDevice *stylus;
-       GsdWacomDevice *pad;
+       CcWacomDevice *stylus;
+       CcWacomDevice *pad;
 } Tablet;
 
 enum {
@@ -90,8 +104,8 @@ set_device_page (CcWacomPanel *self, const gchar *device_name)
                return page;
        }
 
-       current = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), GTK_WIDGET (page));
-       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), current);
+       current = gtk_notebook_page_num (GTK_NOTEBOOK (priv->tablet_notebook), GTK_WIDGET (page));
+       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->tablet_notebook), current);
 
        return page;
 }
@@ -229,10 +243,148 @@ cc_wacom_panel_dispose (GObject *object)
                priv->pages = NULL;
        }
 
+       if (priv->stylus_pages)
+       {
+               g_hash_table_destroy (priv->stylus_pages);
+               priv->stylus_pages = NULL;
+       }
+
        G_OBJECT_CLASS (cc_wacom_panel_parent_class)->dispose (object);
 }
 
 static void
+check_remove_stylus_pages (CcWacomPanel *self)
+{
+       CcWacomPanelPrivate *priv;
+       GHashTableIter iter;
+       CcWacomDevice *device;
+       CcWacomTool *tool;
+       GtkWidget *page;
+       GList *tools, *total = NULL;
+
+       priv = self->priv;
+
+       /* First. Iterate known devices and get the tools */
+       g_hash_table_iter_init (&iter, priv->devices);
+       while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &device)) {
+               tools = cc_tablet_tool_map_list_tools (priv->tablet_tool_map, device);
+               total = g_list_concat (total, tools);
+       }
+
+       /* Second. Iterate through stylus pages and remove the ones whose
+        * tool is no longer in the list.
+        */
+       g_hash_table_iter_init (&iter, priv->stylus_pages);
+       while (g_hash_table_iter_next (&iter, (gpointer*) &tool, (gpointer*) &page)) {
+               if (g_list_find (total, tool))
+                       continue;
+               gtk_widget_destroy (page);
+               g_hash_table_iter_remove (&iter);
+       }
+
+       g_list_free (total);
+}
+
+static gboolean
+add_stylus (CcWacomPanel *self,
+           CcWacomTool  *tool)
+{
+       CcWacomPanelPrivate *priv;
+       GtkWidget *page;
+
+       priv = self->priv;
+
+       if (g_hash_table_lookup (priv->stylus_pages, tool))
+               return FALSE;
+
+       page = cc_wacom_stylus_page_new (tool);
+       cc_wacom_stylus_page_set_navigation (CC_WACOM_STYLUS_PAGE (page),
+                                            GTK_NOTEBOOK (priv->stylus_notebook));
+       gtk_widget_show (page);
+       gtk_notebook_append_page (GTK_NOTEBOOK (priv->stylus_notebook), page, NULL);
+       g_hash_table_insert (priv->stylus_pages, tool, page);
+       return TRUE;
+}
+
+static void
+update_current_tool (CcWacomPanel  *panel,
+                    GdkDevice     *device,
+                    GdkDeviceTool *tool)
+{
+       CcWacomPanelPrivate *priv = panel->priv;;
+       GsdDeviceManager *device_manager;
+       CcWacomDevice *wacom_device;
+       CcWacomTool *stylus;
+       GsdDevice *gsd_device;
+       guint64 serial, id;
+
+       if (!tool)
+               return;
+
+       /* Work our way to the CcWacomDevice */
+       device_manager = gsd_device_manager_get ();
+       gsd_device = gsd_device_manager_lookup_gdk_device (device_manager,
+                                                          device);
+       if (!gsd_device)
+               return;
+
+       wacom_device = g_hash_table_lookup (priv->devices, gsd_device);
+       if (!wacom_device)
+               return;
+
+       /* Check whether we already know this tool, nothing to do then */
+       serial = gdk_device_tool_get_serial (tool);
+       stylus = cc_tablet_tool_map_lookup_tool (priv->tablet_tool_map,
+                                                wacom_device, serial);
+
+       if (!stylus) {
+               gboolean added;
+
+               /* FIXME: wayland only? */
+               id = gdk_wayland_device_tool_get_hardware_id (tool);
+               stylus = cc_wacom_tool_new (serial, id, wacom_device);
+               if (!stylus)
+                       return;
+
+               added = add_stylus (panel, stylus);
+
+               if (added) {
+                       if (priv->stylus_notebook ==
+                           gtk_stack_get_visible_child (GTK_STACK (priv->stack))) {
+                               GtkWidget *widget;
+                               gint page;
+
+                               widget = g_hash_table_lookup (priv->stylus_pages, stylus);
+                               page = gtk_notebook_page_num (GTK_NOTEBOOK (priv->stylus_notebook), widget);
+                               gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->stylus_notebook), page);
+                       } else {
+                               gtk_container_child_set (GTK_CONTAINER (priv->stack),
+                                                        priv->stylus_notebook,
+                                                        "needs-attention", TRUE,
+                                                        NULL);
+                       }
+               }
+       }
+
+       cc_tablet_tool_map_add_relation (priv->tablet_tool_map,
+                                        wacom_device, stylus);
+}
+
+static gboolean
+on_shell_event_cb (GtkWidget    *wigdet,
+                  GdkEvent     *event,
+                  CcWacomPanel *panel)
+{
+       if (event->type == GDK_PROXIMITY_IN) {
+               update_current_tool (panel,
+                                    gdk_event_get_source_device (event),
+                                    gdk_event_get_device_tool (event));
+       }
+
+       return GDK_EVENT_PROPAGATE;
+}
+
+static void
 cc_wacom_panel_constructed (GObject *object)
 {
        CcWacomPanel *self = CC_WACOM_PANEL (object);
@@ -265,6 +417,9 @@ cc_wacom_panel_constructed (GObject *object)
        g_object_bind_property (button, "active",
                                priv->test_popover, "visible",
                                G_BINDING_BIDIRECTIONAL);
+
+       g_signal_connect_object (shell, "event",
+                                G_CALLBACK (on_shell_event_cb), self, 0);
 }
 
 static const char *
@@ -273,6 +428,14 @@ cc_wacom_panel_get_help_uri (CcPanel *panel)
   return "help:gnome-help/wacom";
 }
 
+static GtkWidget *
+cc_wacom_panel_get_title_widget (CcPanel *panel)
+{
+       CcWacomPanelPrivate *priv = CC_WACOM_PANEL (panel)->priv;
+
+       return priv->switcher;
+}
+
 static void
 cc_wacom_panel_class_init (CcWacomPanelClass *klass)
 {
@@ -287,6 +450,7 @@ cc_wacom_panel_class_init (CcWacomPanelClass *klass)
        object_class->constructed = cc_wacom_panel_constructed;
 
        panel_class->get_help_uri = cc_wacom_panel_get_help_uri;
+       panel_class->get_title_widget = cc_wacom_panel_get_title_widget;
 
        g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
 }
@@ -308,44 +472,49 @@ remove_page (GtkNotebook *notebook,
 }
 
 static void
-update_current_page (CcWacomPanel *self)
+update_current_page (CcWacomPanel  *self,
+                    CcWacomDevice *removed_device)
 {
        GHashTable *ht;
-       GList *devices, *tablets, *l;
+       GList *tablets, *l;
        gboolean changed;
        CcWacomPanelPrivate *priv;
+       GHashTableIter iter;
+       GsdDevice *gsd_device;
+       CcWacomDevice *device;
 
        priv = self->priv;
        changed = FALSE;
 
        ht = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
-       devices = g_hash_table_get_values (priv->devices);
-       for (l = devices; l; l = l->next) {
+
+       if (removed_device) {
+               Tablet *tablet = g_new0 (Tablet, 1);
+               tablet->name = cc_wacom_device_get_name (removed_device);
+               g_hash_table_insert (ht, (gpointer) tablet->name, tablet);
+       }
+
+       g_hash_table_iter_init (&iter, priv->devices);
+
+       while (g_hash_table_iter_next (&iter, (gpointer*) &gsd_device,
+                                      (gpointer*) &device)) {
                Tablet *tablet;
-               GsdWacomDevice *device;
+               GsdDeviceType device_type;
 
-               device = l->data;
-               tablet = g_hash_table_lookup (ht, gsd_wacom_device_get_name (device));
+               device_type = gsd_device_get_device_type (gsd_device);
+               tablet = g_hash_table_lookup (ht, cc_wacom_device_get_name (device));
                if (tablet == NULL) {
                        tablet = g_new0 (Tablet, 1);
-                       tablet->name = gsd_wacom_device_get_name (device);
+                       tablet->name = cc_wacom_device_get_name (device);
                        g_hash_table_insert (ht, (gpointer) tablet->name, tablet);
                }
 
-               switch (gsd_wacom_device_get_device_type (device)) {
-               case WACOM_TYPE_STYLUS:
-                       tablet->stylus = device;
-                       break;
-               case WACOM_TYPE_PAD:
+               if (device_type & GSD_DEVICE_TYPE_PAD) {
                        tablet->pad = device;
-                       break;
-               case WACOM_TYPE_ERASER:
-               default:
-                       /* Nothing */
-                       ;
+               } else if (device_type & GSD_DEVICE_TYPE_TABLET) {
+                       tablet->stylus = device;
                }
        }
-       g_list_free (devices);
 
        /* We now have a list of Tablet structs,
         * see which ones are full tablets */
@@ -358,7 +527,7 @@ update_current_page (CcWacomPanel *self)
                if (tablet->stylus == NULL) {
                        page = g_hash_table_lookup (priv->pages, tablet->name);
                        if (page != NULL) {
-                               remove_page (GTK_NOTEBOOK (priv->notebook), page);
+                               remove_page (GTK_NOTEBOOK (priv->tablet_notebook), page);
                                g_hash_table_remove (priv->pages, tablet->name);
 
                                changed = TRUE;
@@ -369,9 +538,9 @@ update_current_page (CcWacomPanel *self)
                page = g_hash_table_lookup (priv->pages, tablet->name);
                if (page == NULL) {
                        page = cc_wacom_page_new (self, tablet->stylus, tablet->pad);
-                       cc_wacom_page_set_navigation (CC_WACOM_PAGE (page), GTK_NOTEBOOK (priv->notebook), 
TRUE);
+                       cc_wacom_page_set_navigation (CC_WACOM_PAGE (page), GTK_NOTEBOOK 
(priv->tablet_notebook), TRUE);
                        gtk_widget_show (page);
-                       gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), page, NULL);
+                       gtk_notebook_append_page (GTK_NOTEBOOK (priv->tablet_notebook), page, NULL);
                        g_hash_table_insert (priv->pages, g_strdup (tablet->name), page);
 
                        changed = TRUE;
@@ -386,48 +555,74 @@ update_current_page (CcWacomPanel *self)
        if (changed == TRUE) {
                int num_pages;
 
-               num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
+               num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->tablet_notebook));
                if (num_pages > 1)
-                       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), WACOM_PAGE);
+                       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->tablet_notebook), 1);
        }
 }
 
 static void
 add_known_device (CcWacomPanel *self,
-                 GdkDevice    *gdk_device)
+                 GsdDevice    *gsd_device)
 {
        CcWacomPanelPrivate *priv;
-       GsdWacomDevice *device;
+       CcWacomDevice *device;
+       GsdDeviceType device_type;
+       GList *tools, *l;
 
        priv = self->priv;
+       device_type = gsd_device_get_device_type (gsd_device);
+
+       if ((device_type & GSD_DEVICE_TYPE_TABLET) == 0)
+               return;
+
+       if ((device_type &
+            (GSD_DEVICE_TYPE_TOUCHSCREEN | GSD_DEVICE_TYPE_TOUCHPAD)) != 0) {
+               return;
+       }
 
-       device = gsd_wacom_device_new (gdk_device);
-       if (gsd_wacom_device_get_device_type (device) == WACOM_TYPE_INVALID) {
-               g_object_unref (device);
+       device = cc_wacom_device_new (gsd_device);
+       if (!device)
                return;
+
+       g_hash_table_insert (priv->devices, gsd_device, device);
+
+       /* Only trigger tool lookup on pen devices */
+       if ((device_type & GSD_DEVICE_TYPE_PAD) != 0) {
+               tools = cc_tablet_tool_map_list_tools (priv->tablet_tool_map, device);
+
+               for (l = tools; l != NULL; l = l->next) {
+                       add_stylus (self, l->data);
+               }
+
+               g_list_free (tools);
        }
-       g_debug ("Adding device '%s' (type: '%s') to known devices list",
-                gsd_wacom_device_get_tool_name (device),
-                gsd_wacom_device_type_to_string (gsd_wacom_device_get_device_type (device)));
-       g_hash_table_insert (priv->devices, (gpointer) gdk_device, device);
 }
 
 static void
-device_removed_cb (GdkDeviceManager *manager,
-                  GdkDevice        *gdk_device,
+device_removed_cb (GsdDeviceManager *manager,
+                  GsdDevice        *gsd_device,
                   CcWacomPanel     *self)
 {
-       g_hash_table_remove (self->priv->devices, gdk_device);
-       update_current_page (self);
+       CcWacomDevice *device;
+
+       device = g_hash_table_lookup (self->priv->devices, gsd_device);
+       if (!device)
+               return;
+
+       g_hash_table_steal (self->priv->devices, gsd_device);
+       update_current_page (self, device);
+       check_remove_stylus_pages (self);
+       g_object_unref (device);
 }
 
 static void
-device_added_cb (GdkDeviceManager *manager,
-                GdkDevice        *device,
+device_added_cb (GsdDeviceManager *manager,
+                GsdDevice        *device,
                 CcWacomPanel     *self)
 {
        add_known_device (self, device);
-       update_current_page (self);
+       update_current_page (self, NULL);
 }
 
 static gboolean
@@ -490,10 +685,27 @@ enbiggen_label (GtkLabel *label)
 }
 
 static void
+on_stack_visible_child_notify_cb (GObject      *object,
+                                 GParamSpec   *pspec,
+                                 CcWacomPanel *panel)
+{
+       CcWacomPanelPrivate *priv = panel->priv;
+       GtkWidget *child;
+
+       child = gtk_stack_get_visible_child (GTK_STACK (object));
+
+       if (child == priv->stylus_notebook) {
+               gtk_container_child_set (GTK_CONTAINER (priv->stack),
+                                        priv->stylus_notebook,
+                                        "needs-attention", FALSE,
+                                        NULL);
+       }
+}
+
+static void
 cc_wacom_panel_init (CcWacomPanel *self)
 {
        CcWacomPanelPrivate *priv;
-       GtkNotebook *notebook;
        GtkWidget *widget;
        GList *devices, *l;
        GError *error = NULL;
@@ -519,6 +731,8 @@ cc_wacom_panel_init (CcWacomPanel *self)
                return;
        }
 
+       priv->tablet_tool_map = cc_tablet_tool_map_new ();
+
        priv->cancellable = g_cancellable_new ();
 
        g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
@@ -531,47 +745,71 @@ cc_wacom_panel_init (CcWacomPanel *self)
                                  got_wacom_proxy_cb,
                                  self);
 
-       /* Notebook */
-       notebook = GTK_NOTEBOOK (gtk_notebook_new ());
-       priv->notebook = GTK_WIDGET (notebook);
-
-       gtk_notebook_set_show_tabs (notebook, FALSE);
-       gtk_notebook_set_show_border (notebook, FALSE);
-       gtk_widget_set_vexpand (GTK_WIDGET (notebook), TRUE);
-       gtk_container_set_border_width (GTK_CONTAINER (notebook), 0);
-       g_object_set (G_OBJECT (notebook),
-                     "margin-top", 6,
+       /* Stack + Switcher */
+       priv->stack = gtk_stack_new ();
+       g_object_set (G_OBJECT (priv->stack),
+                     "margin-top", 30,
                      "margin-end", 30,
                      "margin-start", 30,
                      "margin-bottom", 30,
                      NULL);
 
-       gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (notebook));
-       gtk_widget_show (priv->notebook);
+       g_signal_connect (priv->stack, "notify::visible-child",
+                         G_CALLBACK (on_stack_visible_child_notify_cb), self);
+
+       priv->switcher = gtk_stack_switcher_new ();
+       gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (priv->switcher),
+                                     GTK_STACK (priv->stack));
+       gtk_widget_show (priv->switcher);
+
+       gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (priv->stack));
+       gtk_widget_show (priv->stack);
+
+       priv->tablet_notebook = gtk_notebook_new ();
+       gtk_widget_show (priv->tablet_notebook);
+       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->tablet_notebook), FALSE);
+       gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->tablet_notebook), FALSE);
+       gtk_widget_set_vexpand (priv->tablet_notebook, TRUE);
+
+       priv->stylus_notebook = gtk_notebook_new ();
+       gtk_widget_show (priv->stylus_notebook);
+       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->stylus_notebook), FALSE);
+       gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->stylus_notebook), FALSE);
+       gtk_container_set_border_width (GTK_CONTAINER (priv->stylus_notebook), 0);
+       gtk_widget_set_vexpand (priv->stylus_notebook, TRUE);
+
+       gtk_stack_add_titled (GTK_STACK (priv->stack),
+                             priv->stylus_notebook, "stylus",
+                             _("Stylus"));
+       gtk_stack_add_titled (GTK_STACK (priv->stack),
+                             priv->tablet_notebook, "tablet",
+                             _("Tablet"));
 
        /* No tablets page */
        widget = WID ("main-box");
        enbiggen_label (GTK_LABEL (WID ("advice-label1")));
-       gtk_notebook_append_page (notebook, widget, NULL);
+       gtk_notebook_append_page (GTK_NOTEBOOK (priv->tablet_notebook), widget, NULL);
 
        g_signal_connect (G_OBJECT (WID ("linkbutton")), "activate-link",
                          G_CALLBACK (link_activated), self);
 
        priv->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
        priv->pages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+       priv->stylus_pages = g_hash_table_new (NULL, NULL);
 
-       priv->manager = gdk_display_get_device_manager (gdk_display_get_default ());
+       priv->manager = gsd_device_manager_get ();
        priv->device_added_id = g_signal_connect (G_OBJECT (priv->manager), "device-added",
                                                  G_CALLBACK (device_added_cb), self);
        priv->device_removed_id = g_signal_connect (G_OBJECT (priv->manager), "device-removed",
                                                    G_CALLBACK (device_removed_cb), self);
 
-       devices = gdk_device_manager_list_devices (priv->manager, GDK_DEVICE_TYPE_SLAVE);
+       devices = gsd_device_manager_list_devices (priv->manager,
+                                                  GSD_DEVICE_TYPE_TABLET);
        for (l = devices; l ; l = l->next)
                add_known_device (self, l->data);
        g_list_free (devices);
 
-       update_current_page (self);
+       update_current_page (self, NULL);
 }
 
 GDBusProxy *
diff --git a/panels/wacom/cc-wacom-stylus-page.c b/panels/wacom/cc-wacom-stylus-page.c
index 5b8f5b7..e876b90 100644
--- a/panels/wacom/cc-wacom-stylus-page.c
+++ b/panels/wacom/cc-wacom-stylus-page.c
@@ -25,6 +25,7 @@
 #include "cc-wacom-stylus-page.h"
 #include "cc-wacom-nav-button.h"
 #include <gtk/gtk.h>
+#include <gdesktop-enums.h>
 
 #include <string.h>
 
@@ -38,10 +39,10 @@ G_DEFINE_TYPE (CcWacomStylusPage, cc_wacom_stylus_page, GTK_TYPE_BOX)
 
 struct _CcWacomStylusPagePrivate
 {
-       GsdWacomStylus *stylus;
+       CcWacomTool    *stylus;
        GtkBuilder     *builder;
        GtkWidget      *nav;
-       GSettings      *stylus_settings, *eraser_settings;
+       GSettings      *stylus_settings;
 };
 
 /* Button combo box storage columns */
@@ -67,7 +68,7 @@ static const gint32 PRESSURE_CURVES[N_PRESSURE_CURVES][4] = {
 };
 
 static void
-set_pressurecurve (GtkRange *range, GSettings *settings)
+set_pressurecurve (GtkRange *range, GSettings *settings, const gchar *key)
 {
        gint            slider_val = gtk_range_get_value (range);
        GVariant        *values[4],
@@ -79,30 +80,30 @@ set_pressurecurve (GtkRange *range, GSettings *settings)
 
        array = g_variant_new_array (G_VARIANT_TYPE_INT32, values, G_N_ELEMENTS (values));
 
-       g_settings_set_value (settings, "pressurecurve", array);
+       g_settings_set_value (settings, key, array);
 }
 
 static void
 tip_feel_value_changed_cb (GtkRange *range, gpointer user_data)
 {
-    set_pressurecurve (range, CC_WACOM_STYLUS_PAGE(user_data)->priv->stylus_settings);
+       set_pressurecurve (range, CC_WACOM_STYLUS_PAGE(user_data)->priv->stylus_settings, "pressure-curve");
 }
 
 static void
 eraser_feel_value_changed_cb (GtkRange *range, gpointer user_data)
 {
-    set_pressurecurve (range, CC_WACOM_STYLUS_PAGE(user_data)->priv->eraser_settings);
+       set_pressurecurve (range, CC_WACOM_STYLUS_PAGE(user_data)->priv->stylus_settings, 
"eraser-pressure-curve");
 }
 
 static void
-set_feel_from_gsettings (GtkAdjustment *adjustment, GSettings *settings)
+set_feel_from_gsettings (GtkAdjustment *adjustment, GSettings *settings, const gchar *key)
 {
        GVariant        *variant;
        const gint32    *values;
        gsize           nvalues;
        int             i;
 
-       variant = g_settings_get_value (settings, "pressurecurve");
+       variant = g_settings_get_value (settings, key);
        values = g_variant_get_fixed_array (variant, &nvalues, sizeof (gint32));
 
        if (nvalues != 4) {
@@ -119,17 +120,14 @@ set_feel_from_gsettings (GtkAdjustment *adjustment, GSettings *settings)
 }
 
 static void
-set_button_mapping_from_gsettings (GtkComboBox *combo, GSettings* settings, gint current_button)
+set_button_mapping_from_gsettings (GtkComboBox *combo, GSettings* settings, const gchar *key)
 {
-       GVariant        *current;
-       gsize            nvalues;
-       const gint      *values;
+       GDesktopStylusButtonAction action;
        GtkTreeModel    *model;
        GtkTreeIter      iter;
        gboolean         valid;
 
-       current = g_settings_get_value (settings, "buttonmapping");
-       values = g_variant_get_fixed_array (current, &nvalues, sizeof (gint32));
+       action = g_settings_get_enum (settings, key);
        model = gtk_combo_box_get_model (combo);
        valid = gtk_tree_model_get_iter_first (model, &iter);
 
@@ -147,7 +145,7 @@ set_button_mapping_from_gsettings (GtkComboBox *combo, GSettings* settings, gint
                 */
 
                /* 0 vs 1-indexed array/button numbers */
-               if (button == values[current_button - 1]) {
+               if (button == action) {
                        gtk_combo_box_set_active_iter (combo, &iter);
                        break;
                }
@@ -157,35 +155,6 @@ set_button_mapping_from_gsettings (GtkComboBox *combo, GSettings* settings, gint
 }
 
 static void
-map_button (GSettings *settings, int button2, int button3)
-{
-       GVariant        *current; /* current mapping */
-       GVariant        *array;   /* new mapping */
-       GVariant        **tmp;
-       gsize            nvalues;
-       const gint      *values;
-       gint             i;
-
-       current = g_settings_get_value (settings, "buttonmapping");
-       values = g_variant_get_fixed_array (current, &nvalues, sizeof (gint32));
-
-       tmp = g_malloc (nvalues * sizeof (GVariant*));
-       for (i = 0; i < nvalues; i++) {
-               if (i == 1) /* zero indexed array vs one-indexed buttons */
-                       tmp[i] = g_variant_new_int32 (button2);
-               else if (i == 2)
-                       tmp[i] = g_variant_new_int32 (button3);
-               else
-                       tmp[i] = g_variant_new_int32 (values[i]);
-       }
-
-       array = g_variant_new_array (G_VARIANT_TYPE_INT32, tmp, nvalues);
-       g_settings_set_value (settings, "buttonmapping", array);
-
-       g_free (tmp);
-}
-
-static void
 button_changed_cb (GtkComboBox *combo, gpointer user_data)
 {
        CcWacomStylusPagePrivate        *priv = CC_WACOM_STYLUS_PAGE(user_data)->priv;
@@ -202,7 +171,7 @@ button_changed_cb (GtkComboBox *combo, gpointer user_data)
                            BUTTONNUMBER_COLUMN, &mapping_b2,
                            -1);
 
-       if (gsd_wacom_stylus_get_num_buttons (priv->stylus) > 1) {
+       if (cc_wacom_tool_get_num_buttons (priv->stylus) > 1) {
                if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (WID ("combo-topbutton")), &iter))
                        return;
 
@@ -213,7 +182,8 @@ button_changed_cb (GtkComboBox *combo, gpointer user_data)
                mapping_b3 = 0;
        }
 
-       map_button (priv->stylus_settings, mapping_b2, mapping_b3);
+       g_settings_set_enum (priv->stylus_settings, "button-action", mapping_b2);
+       g_settings_set_enum (priv->stylus_settings, "secondary-button-action", mapping_b3);
 }
 
 static void
@@ -429,15 +399,15 @@ update_stylus_ui (CcWacomStylusPage *page,
 }
 
 GtkWidget *
-cc_wacom_stylus_page_new (GsdWacomStylus *stylus)
+cc_wacom_stylus_page_new (CcWacomTool *stylus)
 {
        CcWacomStylusPage *page;
        CcWacomStylusPagePrivate *priv;
-       int num_buttons;
+       guint num_buttons;
        int layout;
-       int has_eraser;
+       gboolean has_eraser;
 
-       g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL);
+       g_return_val_if_fail (CC_IS_WACOM_TOOL (stylus), NULL);
 
        page = g_object_new (CC_TYPE_WACOM_STYLUS_PAGE, NULL);
 
@@ -445,18 +415,16 @@ cc_wacom_stylus_page_new (GsdWacomStylus *stylus)
        priv->stylus = stylus;
 
        /* Icon */
-       set_icon_name (page, "image-stylus", gsd_wacom_stylus_get_icon_name (stylus));
+       set_icon_name (page, "image-stylus", cc_wacom_tool_get_icon_name (stylus));
 
        /* Settings */
-       priv->stylus_settings = gsd_wacom_stylus_get_settings (stylus);
-       has_eraser = gsd_wacom_stylus_get_has_eraser (stylus);
-       if (has_eraser)
-               priv->eraser_settings = gsd_wacom_stylus_get_settings (stylus);
+       priv->stylus_settings = cc_wacom_tool_get_settings (stylus);
+       has_eraser = cc_wacom_tool_get_has_eraser (stylus);
 
        /* Stylus name */
-       gtk_label_set_text (GTK_LABEL (WID ("label-stylus")), gsd_wacom_stylus_get_name (stylus));
+       gtk_label_set_text (GTK_LABEL (WID ("label-stylus")), cc_wacom_tool_get_name (stylus));
 
-       num_buttons = gsd_wacom_stylus_get_num_buttons (stylus);
+       num_buttons = cc_wacom_tool_get_num_buttons (stylus);
        if (num_buttons == 0 && !has_eraser)
                layout = LAYOUT_INKING;
        else if (num_buttons == 2 && has_eraser)
@@ -483,21 +451,32 @@ cc_wacom_stylus_page_new (GsdWacomStylus *stylus)
        update_stylus_ui (page, layout);
 
        if (num_buttons == 2)
-               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-topbutton")), 
priv->stylus_settings, 3);
+               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-topbutton")),
+                                                  priv->stylus_settings, "secondary-button-action");
        if (num_buttons >= 1)
-               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-bottombutton")), 
priv->stylus_settings, 2);
-       set_feel_from_gsettings (GTK_ADJUSTMENT (WID ("adjustment-tip-feel")), priv->stylus_settings);
+               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-bottombutton")),
+                                                  priv->stylus_settings, "button-action");
+       set_feel_from_gsettings (GTK_ADJUSTMENT (WID ("adjustment-tip-feel")),
+                                priv->stylus_settings, "pressure-curve");
 
        if (has_eraser)
-               set_feel_from_gsettings (GTK_ADJUSTMENT (WID ("adjustment-eraser-feel")), 
priv->eraser_settings);
+               set_feel_from_gsettings (GTK_ADJUSTMENT (WID ("adjustment-eraser-feel")),
+                                        priv->stylus_settings, "eraser-pressure-curve");
 
-       g_object_set (G_OBJECT (page), "margin-top", 16, NULL);
+       {
+               GtkAllocation allocation;
+               GtkWidget *w;
+
+               w = WID ("image-stylus");
+               gtk_widget_get_allocation (w, &allocation);
+               gtk_widget_set_size_request (WID ("image-stylus"), -1, 210);
+       }
 
        return GTK_WIDGET (page);
 }
 
-GsdWacomStylus *
-cc_wacom_stylus_page_get_stylus (CcWacomStylusPage *page)
+CcWacomTool *
+cc_wacom_stylus_page_get_tool (CcWacomStylusPage *page)
 {
        return page->priv->stylus;
 }
diff --git a/panels/wacom/cc-wacom-stylus-page.h b/panels/wacom/cc-wacom-stylus-page.h
index 7941351..19d3a07 100644
--- a/panels/wacom/cc-wacom-stylus-page.h
+++ b/panels/wacom/cc-wacom-stylus-page.h
@@ -23,7 +23,7 @@
 #define _CC_WACOM_STYLUS_PAGE_H
 
 #include <gtk/gtk.h>
-#include "gsd-wacom-device.h"
+#include "cc-wacom-tool.h"
 
 G_BEGIN_DECLS
 
@@ -67,9 +67,9 @@ struct _CcWacomStylusPageClass
 
 GType cc_wacom_stylus_page_get_type (void) G_GNUC_CONST;
 
-GtkWidget * cc_wacom_stylus_page_new (GsdWacomStylus *stylus);
+GtkWidget * cc_wacom_stylus_page_new (CcWacomTool *stylus);
 
-GsdWacomStylus * cc_wacom_stylus_page_get_stylus (CcWacomStylusPage *page);
+CcWacomTool * cc_wacom_stylus_page_get_tool (CcWacomStylusPage *page);
 
 void cc_wacom_stylus_page_set_navigation (CcWacomStylusPage *page,
                                          GtkNotebook *notebook);


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