[mutter] backends/x11: Implement tablet settings based on the Wacom driver



commit ff9753688fcba7eacc49ba2420bf42c0af22dc59
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Oct 31 18:01:25 2016 +0100

    backends/x11: Implement tablet settings based on the Wacom driver
    
    This is a stopgap solution until libinput is the fallback driver
    handling tablets and pads.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773779

 src/backends/x11/meta-input-settings-x11.c |  214 +++++++++++++++++++++++++++-
 1 files changed, 207 insertions(+), 7 deletions(-)
---
diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
index 332997b..d7d468d 100644
--- a/src/backends/x11/meta-input-settings-x11.c
+++ b/src/backends/x11/meta-input-settings-x11.c
@@ -188,10 +188,20 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings  *settings,
                                          ClutterInputDevice *device,
                                          gboolean            enabled)
 {
-  guchar value = (enabled) ? 1 : 0;
+  guchar value;
 
-  change_property (device, "libinput Left Handed Enabled",
-                   XA_INTEGER, 8, &value, 1);
+  if (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE)
+    {
+      value = enabled ? 3 : 0;
+      change_property (device, "Wacom Rotation",
+                       XA_INTEGER, 8, &value, 1);
+    }
+  else
+    {
+      value = enabled ? 1 : 0;
+      change_property (device, "libinput Left Handed Enabled",
+                       XA_INTEGER, 8, &value, 1);
+    }
 }
 
 static void
@@ -467,14 +477,76 @@ meta_input_settings_x11_set_tablet_mapping (MetaInputSettings     *settings,
                                             ClutterInputDevice    *device,
                                             GDesktopTabletMapping  mapping)
 {
+  MetaDisplay *display = meta_get_display ();
+  MetaBackend *backend = meta_get_backend ();
+  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+  int device_id = clutter_input_device_get_device_id (device);
+  XDevice *xdev;
+
+  if (!display)
+    return;
+
+  /* Grab the puke bucket! */
+  meta_error_trap_push (display);
+  xdev = XOpenDevice (xdisplay, device_id);
+  if (xdev)
+    {
+      XSetDeviceMode (xdisplay, xdev,
+                      mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE ?
+                      Absolute : Relative);
+      XCloseDevice (xdisplay, xdev);
+    }
+
+  if (meta_error_trap_pop_with_return (display))
+    {
+      g_warning ("Could not set tablet mapping for %s",
+                 clutter_input_device_get_device_name (device));
+    }
+}
+
+static gboolean
+device_query_area (ClutterInputDevice *device,
+                   gint               *width,
+                   gint               *height)
+{
+  MetaBackend *backend = meta_get_backend ();
+  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+  gint device_id, n_devices, i;
+  XIDeviceInfo *info;
+  Atom abs_x, abs_y;
+
+  *width = *height = 0;
+  device_id = clutter_input_device_get_device_id (device);
+  info = XIQueryDevice (xdisplay, device_id, &n_devices);
+  if (n_devices == 0)
+    return FALSE;
+
+  abs_x = XInternAtom (xdisplay, "Abs X", True);
+  abs_y = XInternAtom (xdisplay, "Abs Y", True);
+
+  for (i = 0; i < info->num_classes; i++)
+    {
+      XIValuatorClassInfo *valuator = (XIValuatorClassInfo *) info->classes[i];
+
+      if (valuator->type != XIValuatorClass)
+        continue;
+      if (valuator->label == abs_x)
+        *width = valuator->max - valuator->min;
+      else if (valuator->label == abs_y)
+        *height = valuator->max - valuator->min;
+    }
+
+  XIFreeDeviceInfo (info);
+  return TRUE;
 }
 
 static void
-meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings  *settings,
-                                                ClutterInputDevice *device,
-                                                MetaOutput         *output,
-                                                gboolean            keep_aspect)
+update_tablet_area (MetaInputSettings  *settings,
+                    ClutterInputDevice *device,
+                    gint32             *area)
 {
+  change_property (device, "Wacom Tablet Area",
+                   XA_INTEGER, 32, area, 4);
 }
 
 static void
@@ -485,6 +557,61 @@ meta_input_settings_x11_set_tablet_area (MetaInputSettings  *settings,
                                          gdouble             padding_top,
                                          gdouble             padding_bottom)
 {
+  gint32 width, height, area[4] = { 0 };
+
+  if (!device_query_area (device, &width, &height))
+    return;
+
+  area[0] = width * padding_left;
+  area[1] = height * padding_top;
+  area[2] = width - (width * padding_right);
+  area[2] = height - (height * padding_bottom);
+  update_tablet_area (settings, device, area);
+}
+
+static void
+meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings  *settings,
+                                                ClutterInputDevice *device,
+                                                MetaOutput         *output,
+                                                gboolean            keep_aspect)
+{
+  gint32 width, height, dev_width, dev_height, area[4] = { 0 };
+
+  if (!device_query_area (device, &dev_width, &dev_height))
+    return;
+
+  if (keep_aspect)
+    {
+      gdouble output_aspect, dev_aspect;
+
+      if (output && output->crtc)
+        {
+          width = output->crtc->rect.width;
+          height = output->crtc->rect.height;
+        }
+      else
+        {
+          MetaMonitorManager *monitor_manager;
+          MetaBackend *backend;
+
+          backend = meta_get_backend ();
+          monitor_manager = meta_backend_get_monitor_manager (backend);
+          meta_monitor_manager_get_screen_limits (monitor_manager,
+                                                  &width, &height);
+        }
+
+      output_aspect = (gdouble) width / height;
+      dev_aspect = (gdouble) dev_width / dev_height;
+
+      if (dev_aspect > output_aspect)
+        dev_width = dev_height * output_aspect;
+      else if (dev_aspect < output_aspect)
+        dev_height = dev_width / output_aspect;
+    }
+
+  area[2] = dev_width;
+  area[3] = dev_height;
+  update_tablet_area (settings, device, area);
 }
 
 static void
@@ -501,6 +628,76 @@ meta_input_settings_x11_dispose (GObject *object)
   G_OBJECT_CLASS (meta_input_settings_x11_parent_class)->dispose (object);
 }
 
+static guint
+action_to_button (GDesktopStylusButtonAction action,
+                  guint                      button)
+{
+  switch (action)
+    {
+    case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE:
+      return CLUTTER_BUTTON_MIDDLE;
+    case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT:
+      return CLUTTER_BUTTON_SECONDARY;
+    case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK:
+      return 8;
+    case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD:
+      return 9;
+    case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT:
+    default:
+      return button;
+    }
+}
+
+static void
+meta_input_settings_x11_set_stylus_button_map (MetaInputSettings          *settings,
+                                               ClutterInputDevice         *device,
+                                               ClutterInputDeviceTool     *tool,
+                                               GDesktopStylusButtonAction  primary,
+                                               GDesktopStylusButtonAction  secondary)
+{
+  MetaDisplay *display = meta_get_display ();
+  MetaBackend *backend = meta_get_backend ();
+  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
+  int device_id = clutter_input_device_get_device_id (device);
+  XDevice *xdev;
+
+  if (!display)
+    return;
+
+  /* Grab the puke bucket! */
+  meta_error_trap_push (display);
+  xdev = XOpenDevice (xdisplay, device_id);
+  if (xdev)
+    {
+      guchar map[3] = {
+        CLUTTER_BUTTON_PRIMARY,
+        action_to_button (primary, CLUTTER_BUTTON_MIDDLE),
+        action_to_button (secondary, CLUTTER_BUTTON_SECONDARY),
+      };
+
+      XSetDeviceButtonMapping (xdisplay, xdev, map, G_N_ELEMENTS (map));
+      XCloseDevice (xdisplay, xdev);
+    }
+
+  if (meta_error_trap_pop_with_return (display))
+    {
+      g_warning ("Could not set stylus button map for %s",
+                 clutter_input_device_get_device_name (device));
+    }
+}
+
+static void
+meta_input_settings_x11_set_stylus_pressure (MetaInputSettings      *settings,
+                                             ClutterInputDevice     *device,
+                                             ClutterInputDeviceTool *tool,
+                                             const gint32            pressure[4])
+{
+  guchar values[4] = { pressure[0], pressure[1], pressure[2], pressure[3] };
+
+  change_property (device, "Wacom Pressurecurve", XA_INTEGER, 8,
+                   &values, G_N_ELEMENTS (values));
+}
+
 static void
 meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
 {
@@ -527,6 +724,9 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
 
   input_settings_class->set_mouse_accel_profile = meta_input_settings_x11_set_mouse_accel_profile;
   input_settings_class->set_trackball_accel_profile = meta_input_settings_x11_set_trackball_accel_profile;
+
+  input_settings_class->set_stylus_pressure = meta_input_settings_x11_set_stylus_pressure;
+  input_settings_class->set_stylus_button_map = meta_input_settings_x11_set_stylus_button_map;
 }
 
 static void


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