summaryrefslogtreecommitdiffstats
path: root/panels/wacom/cc-wacom-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'panels/wacom/cc-wacom-device.c')
-rw-r--r--panels/wacom/cc-wacom-device.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/panels/wacom/cc-wacom-device.c b/panels/wacom/cc-wacom-device.c
new file mode 100644
index 0000000..695b85b
--- /dev/null
+++ b/panels/wacom/cc-wacom-device.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "cc-wacom-device.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ N_PROPS
+};
+
+GParamSpec *props[N_PROPS] = { 0 };
+
+typedef struct _CcWacomDevice CcWacomDevice;
+
+struct _CcWacomDevice {
+ GObject parent_instance;
+
+ GsdDevice *device;
+ WacomDevice *wdevice;
+};
+
+static void cc_wacom_device_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcWacomDevice, cc_wacom_device, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ cc_wacom_device_initable_iface_init))
+
+WacomDeviceDatabase *
+cc_wacom_device_database_get (void)
+{
+ static WacomDeviceDatabase *db = NULL;
+
+ if (g_once_init_enter (&db)) {
+ gpointer p = libwacom_database_new ();
+ g_once_init_leave (&db, p);
+ }
+
+ return db;
+}
+
+static void
+cc_wacom_device_init (CcWacomDevice *device)
+{
+}
+
+static void
+cc_wacom_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ device->device = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_object (value, device->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_wacom_device_finalize (GObject *object)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (object);
+
+ g_clear_pointer (&device->wdevice, libwacom_destroy);
+
+ G_OBJECT_CLASS (cc_wacom_device_parent_class)->finalize (object);
+}
+
+static void
+cc_wacom_device_class_init (CcWacomDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cc_wacom_device_set_property;
+ object_class->get_property = cc_wacom_device_get_property;
+ object_class->finalize = cc_wacom_device_finalize;
+
+ props[PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "device",
+ "device",
+ GSD_TYPE_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static gboolean
+cc_wacom_device_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CcWacomDevice *device = CC_WACOM_DEVICE (initable);
+ WacomDeviceDatabase *wacom_db;
+ WacomError *wacom_error;
+ const gchar *node_path;
+
+ wacom_db = cc_wacom_device_database_get ();
+ node_path = gsd_device_get_device_file (device->device);
+ wacom_error = libwacom_error_new ();
+ device->wdevice = libwacom_new_from_path (wacom_db, node_path, FALSE, wacom_error);
+
+ if (!device->wdevice) {
+ g_debug ("libwacom_new_from_path() failed: %s", libwacom_error_get_message (wacom_error));
+ libwacom_error_free (&wacom_error);
+ g_set_error (error, 0, 0, "Tablet description not found");
+ return FALSE;
+ }
+ libwacom_error_free (&wacom_error);
+
+ return TRUE;
+}
+
+static void
+cc_wacom_device_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = cc_wacom_device_initable_init;
+}
+
+CcWacomDevice *
+cc_wacom_device_new (GsdDevice *device)
+{
+ return g_initable_new (CC_TYPE_WACOM_DEVICE,
+ NULL, NULL,
+ "device", device,
+ NULL);
+}
+
+CcWacomDevice *
+cc_wacom_device_new_fake (const gchar *name)
+{
+ CcWacomDevice *device;
+ WacomDevice *wacom_device;
+ WacomError *wacom_error;
+
+ device = g_object_new (CC_TYPE_WACOM_DEVICE,
+ NULL);
+
+ wacom_error = libwacom_error_new ();
+ wacom_device = libwacom_new_from_name (cc_wacom_device_database_get(),
+ name, wacom_error);
+ if (wacom_device == NULL) {
+ g_debug ("libwacom_new_fake() failed: %s", libwacom_error_get_message (wacom_error));
+ libwacom_error_free (&wacom_error);
+ return NULL;
+ }
+ libwacom_error_free (&wacom_error);
+
+ device->wdevice = wacom_device;
+
+ return device;
+}
+
+const gchar *
+cc_wacom_device_get_name (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return libwacom_get_name (device->wdevice);
+}
+
+const gchar *
+cc_wacom_device_get_icon_name (CcWacomDevice *device)
+{
+ WacomIntegrationFlags integration_flags;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ integration_flags = libwacom_get_integration_flags (device->wdevice);
+
+ if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM) {
+ return "wacom-tablet-pc";
+ } else if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY) {
+ return "wacom-tablet-cintiq";
+ } else {
+ return "wacom-tablet";
+ }
+}
+
+gboolean
+cc_wacom_device_is_reversible (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), FALSE);
+
+ return libwacom_is_reversible (device->wdevice);
+}
+
+WacomIntegrationFlags
+cc_wacom_device_get_integration_flags (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), 0);
+
+ return libwacom_get_integration_flags (device->wdevice);
+}
+
+GsdDevice *
+cc_wacom_device_get_device (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return device->device;
+}
+
+GSettings *
+cc_wacom_device_get_settings (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return gsd_device_get_settings (device->device);
+}
+
+const gint *
+cc_wacom_device_get_supported_tools (CcWacomDevice *device,
+ gint *n_tools)
+{
+ *n_tools = 0;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ return libwacom_get_supported_styli (device->wdevice, n_tools);
+}
+
+static GnomeRROutput *
+find_output_by_edid (GnomeRRScreen *rr_screen,
+ const gchar *vendor,
+ const gchar *product,
+ const gchar *serial)
+{
+ GnomeRROutput **rr_outputs;
+ GnomeRROutput *retval = NULL;
+ guint i;
+
+ rr_outputs = gnome_rr_screen_list_outputs (rr_screen);
+
+ for (i = 0; rr_outputs[i] != NULL; i++) {
+ g_autofree gchar *o_vendor = NULL;
+ g_autofree gchar *o_product = NULL;
+ g_autofree gchar *o_serial = NULL;
+ gboolean match;
+
+ gnome_rr_output_get_ids_from_edid (rr_outputs[i],
+ &o_vendor,
+ &o_product,
+ &o_serial);
+
+ g_debug ("Checking for match between '%s','%s','%s' and '%s','%s','%s'", \
+ vendor, product, serial, o_vendor, o_product, o_serial);
+
+ match = (g_strcmp0 (vendor, o_vendor) == 0) && \
+ (g_strcmp0 (product, o_product) == 0) && \
+ (g_strcmp0 (serial, o_serial) == 0);
+
+ if (match) {
+ retval = rr_outputs[i];
+ break;
+ }
+ }
+
+ if (retval == NULL)
+ g_debug ("Did not find a matching output for EDID '%s,%s,%s'",
+ vendor, product, serial);
+
+ return retval;
+}
+
+static GnomeRROutput *
+find_output (GnomeRRScreen *rr_screen,
+ CcWacomDevice *device)
+{
+ g_autoptr(GSettings) settings = NULL;
+ g_autoptr(GVariant) variant = NULL;
+ g_autofree const gchar **edid = NULL;
+ gsize n;
+
+ settings = cc_wacom_device_get_settings (device);
+ variant = g_settings_get_value (settings, "output");
+ edid = g_variant_get_strv (variant, &n);
+
+ if (n != 3) {
+ g_critical ("Expected 'output' key to store %d values; got %"G_GSIZE_FORMAT".", 3, n);
+ return NULL;
+ }
+
+ if (strlen (edid[0]) == 0 || strlen (edid[1]) == 0 || strlen (edid[2]) == 0)
+ return NULL;
+
+ return find_output_by_edid (rr_screen, edid[0], edid[1], edid[2]);
+}
+
+GnomeRROutput *
+cc_wacom_device_get_output (CcWacomDevice *device,
+ GnomeRRScreen *rr_screen)
+{
+ GnomeRROutput *rr_output;
+ GnomeRRCrtc *crtc;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+ g_return_val_if_fail (GNOME_RR_IS_SCREEN (rr_screen), NULL);
+
+ rr_output = find_output (rr_screen, device);
+ if (rr_output == NULL) {
+ return NULL;
+ }
+
+ crtc = gnome_rr_output_get_crtc (rr_output);
+
+ if (!crtc || gnome_rr_crtc_get_current_mode (crtc) == NULL) {
+ g_debug ("Output is not active.");
+ return NULL;
+ }
+
+ return rr_output;
+}
+
+void
+cc_wacom_device_set_output (CcWacomDevice *device,
+ GnomeRROutput *output)
+{
+ g_autoptr(GSettings) settings = NULL;
+ g_autofree gchar *vendor = NULL;
+ g_autofree gchar *product = NULL;
+ g_autofree gchar *serial = NULL;
+ const gchar *values[] = { "", "", "", NULL };
+
+ g_return_if_fail (CC_IS_WACOM_DEVICE (device));
+
+ vendor = product = serial = NULL;
+ settings = cc_wacom_device_get_settings (device);
+
+ if (output != NULL) {
+ gnome_rr_output_get_ids_from_edid (output,
+ &vendor,
+ &product,
+ &serial);
+ values[0] = vendor;
+ values[1] = product;
+ values[2] = serial;
+ }
+
+ g_settings_set_strv (settings, "output", values);
+}
+
+guint
+cc_wacom_device_get_num_buttons (CcWacomDevice *device)
+{
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), 0);
+
+ return libwacom_get_num_buttons (device->wdevice);
+}
+
+GSettings *
+cc_wacom_device_get_button_settings (CcWacomDevice *device,
+ guint button)
+{
+ g_autoptr(GSettings) tablet_settings = NULL;
+ GSettings *settings;
+ g_autofree gchar *path = NULL;
+ g_autofree gchar *button_path = NULL;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ if (button > cc_wacom_device_get_num_buttons (device))
+ return NULL;
+
+ tablet_settings = cc_wacom_device_get_settings (device);
+ g_object_get (tablet_settings, "path", &path, NULL);
+
+ button_path = g_strdup_printf ("%sbutton%c/", path, 'A' + button);
+ settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
+ button_path);
+
+ return settings;
+}
+
+const gchar *
+cc_wacom_device_get_description (CcWacomDevice *device)
+{
+ WacomIntegrationFlags integration_flags;
+
+ g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
+
+ integration_flags = libwacom_get_integration_flags (device->wdevice);
+
+ if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM) {
+ return _("Tablet mounted on laptop panel");
+ } else if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY) {
+ return _("Tablet mounted on external display");
+ } else {
+ return _("External tablet device");
+ }
+}