Blob Blame History Raw
From aee0f01c59f407b25475ab83814a8a186bed175e Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Thu, 7 Apr 2016 18:45:19 +0200
Subject: [PATCH] wacom: rely on the SVG to get the actual position of the
 text, not libwacom

The problem rises up with the Wacom ExpressKey Remote (EKR). This device
is a separate "pad" but the Left/Right buttons do not apply for it in the
way the OSD relies on it.

When a pad is set to be on the left side, we align the labels from the
start as we are drawing them on the right. However, in the EKR case,
the labels from the left are drawn on the left, not the right. We can
not realistically infer where the text should be put from the db only,
so retrieve the actual style from the SVG and use that as the hint for
the position.

https://bugzilla.gnome.org/show_bug.cgi?id=764743
---
 configure.ac                         |  6 +++
 plugins/wacom/Makefile.am            |  3 ++
 plugins/wacom/gsd-wacom-device.c     | 84 ++++++++++++++++++++++++++++++++++--
 plugins/wacom/gsd-wacom-device.h     |  1 +
 plugins/wacom/gsd-wacom-osd-window.c |  2 +-
 5 files changed, 91 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 6d9408a..c86df22 100644
--- a/configure.ac
+++ b/configure.ac
@@ -229,6 +229,12 @@ dnl ---------------------------------------------------------------------------
 
 PKG_CHECK_MODULES(SOUND, [libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION])
 
+dnl ---------------------------------------------------------------------------
+dnl - wacom plugin stuff
+dnl ---------------------------------------------------------------------------
+
+PKG_CHECK_MODULES(LIBXML2, [libxml-2.0])
+
 # ---------------------------------------------------------------------------
 # Power
 # ---------------------------------------------------------------------------
diff --git a/plugins/wacom/Makefile.am b/plugins/wacom/Makefile.am
index 6274e43..324ac3a 100644
--- a/plugins/wacom/Makefile.am
+++ b/plugins/wacom/Makefile.am
@@ -2,6 +2,9 @@ plugin_name = wacom
 
 plugin_LTLIBRARIES = libgsdwacom.la
 
+WACOM_CFLAGS += $(LIBXML2_CFLAGS)
+WACOM_LIBS += $(LIBXML2_LIBS)
+
 libgsdwacom_la_SOURCES =	\
 	gsd-wacom-plugin.c	\
 	gsd-wacom-manager.h	\
diff --git a/plugins/wacom/gsd-wacom-device.c b/plugins/wacom/gsd-wacom-device.c
index 33d9cc5..813be57 100644
--- a/plugins/wacom/gsd-wacom-device.c
+++ b/plugins/wacom/gsd-wacom-device.c
@@ -29,6 +29,9 @@
 #define GNOME_DESKTOP_USE_UNSTABLE_API
 #include <libgnome-desktop/gnome-rr.h>
 
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
 #include <libwacom/libwacom.h>
 #include <X11/extensions/XInput.h>
 #include <X11/extensions/XInput2.h>
@@ -254,6 +257,64 @@ gsd_wacom_stylus_get_id (GsdWacomStylus *stylus)
 	return stylus->priv->id;
 }
 
+static gboolean
+gsd_wacom_xpath_has_style(const char         *id,
+			  xmlXPathContextPtr  xpath_context,
+			  const char         *style)
+{
+	xmlXPathObjectPtr xpath = NULL;
+	gboolean ret;
+	char *path;
+
+	path = g_strdup_printf ("//*[@id='%s'][contains(@style, '%s')]", id, style);
+	xpath = xmlXPathEvalExpression ((xmlChar *)path, xpath_context);
+	ret = xpath && xpath->nodesetval && xpath->nodesetval->nodeNr;
+
+	g_free (path);
+	xmlXPathFreeObject (xpath);
+
+	return ret;
+}
+
+static GsdWacomTabletButtonPos
+gsd_wacom_device_button_draw_pos (guint                    i,
+				  const char              *layout_file,
+				  GsdWacomTabletButtonPos  db_pos)
+{
+	GsdWacomTabletButtonPos ret = WACOM_TABLET_BUTTON_POS_UNDEF;
+	xmlXPathContextPtr xpath_context = NULL;
+	xmlDocPtr doc = NULL;
+	char *id;
+
+	id = g_strdup_printf ("Label%c", i);
+
+	doc = xmlParseFile (layout_file);
+	if (!doc)
+		g_error ("unable to parse '%s'", layout_file);
+
+	xpath_context = xmlXPathNewContext (doc);
+	if (!xpath_context)
+		g_error ("unable to create new XPath context");
+
+	if (gsd_wacom_xpath_has_style (id, xpath_context, "text-anchor:start"))
+		ret = WACOM_TABLET_BUTTON_POS_LEFT;
+	else if (gsd_wacom_xpath_has_style (id, xpath_context, "text-anchor:end"))
+		ret = WACOM_TABLET_BUTTON_POS_RIGHT;
+	else if (gsd_wacom_xpath_has_style (id, xpath_context, "text-anchor:middle"))
+		ret = db_pos == WACOM_TABLET_BUTTON_POS_BOTTOM ? \
+			WACOM_TABLET_BUTTON_POS_BOTTOM : \
+			WACOM_TABLET_BUTTON_POS_TOP;
+
+	if (ret == WACOM_TABLET_BUTTON_POS_UNDEF)
+		ret = db_pos;
+
+	g_free (id);
+	xmlXPathFreeContext (xpath_context);
+	xmlFreeDoc (doc);
+
+	return ret;
+}
+
 /* Tablet buttons */
 static GsdWacomTabletButton *
 gsd_wacom_tablet_button_new (const char               *name,
@@ -261,6 +322,7 @@ gsd_wacom_tablet_button_new (const char               *name,
 			     const char               *settings_path,
 			     GsdWacomTabletButtonType  type,
 			     GsdWacomTabletButtonPos   pos,
+			     GsdWacomTabletButtonPos   draw_pos,
 			     int                       group_id,
 			     int                       idx,
 			     int                       status_led,
@@ -282,6 +344,7 @@ gsd_wacom_tablet_button_new (const char               *name,
 	ret->idx = idx;
 	ret->type = type;
 	ret->pos = pos;
+	ret->draw_pos = draw_pos;
 	ret->status_led = status_led;
 	ret->has_oled = has_oled;
 
@@ -1033,6 +1096,7 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
 									   settings_path,
 									   WACOM_TABLET_BUTTON_TYPE_RING,
 									   WACOM_TABLET_BUTTON_POS_LEFT,
+									   WACOM_TABLET_BUTTON_POS_LEFT,
 									   group,
 									   0,
 									   GSD_WACOM_NO_LED,
@@ -1046,6 +1110,7 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
 				                                                   settings_path,
 				                                                   WACOM_TABLET_BUTTON_TYPE_RING,
 										   WACOM_TABLET_BUTTON_POS_LEFT,
+										   WACOM_TABLET_BUTTON_POS_LEFT,
 				                                                   group,
 				                                                   i - 1,
 										   GSD_WACOM_NO_LED,
@@ -1064,6 +1129,7 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
 									   settings_path,
 									   WACOM_TABLET_BUTTON_TYPE_RING,
 									   WACOM_TABLET_BUTTON_POS_RIGHT,
+									   WACOM_TABLET_BUTTON_POS_RIGHT,
 									   group,
 									   0,
 									   GSD_WACOM_NO_LED,
@@ -1077,6 +1143,7 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
 				                                                   settings_path,
 				                                                   WACOM_TABLET_BUTTON_TYPE_RING,
 										   WACOM_TABLET_BUTTON_POS_RIGHT,
+										   WACOM_TABLET_BUTTON_POS_RIGHT,
 				                                                   group,
 				                                                   i - 1,
 										   GSD_WACOM_NO_LED,
@@ -1117,6 +1184,7 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
 									   settings_path,
 									   WACOM_TABLET_BUTTON_TYPE_STRIP,
 									   WACOM_TABLET_BUTTON_POS_LEFT,
+									   WACOM_TABLET_BUTTON_POS_LEFT,
 									   group,
 									   0,
 									   GSD_WACOM_NO_LED,
@@ -1130,6 +1198,7 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
 				                                                   settings_path,
 				                                                   WACOM_TABLET_BUTTON_TYPE_STRIP,
 										   WACOM_TABLET_BUTTON_POS_LEFT,
+										   WACOM_TABLET_BUTTON_POS_LEFT,
 				                                                   group,
 				                                                   i - 1,
 										   GSD_WACOM_NO_LED,
@@ -1148,6 +1217,7 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
 									   settings_path,
 									   WACOM_TABLET_BUTTON_TYPE_STRIP,
 									   WACOM_TABLET_BUTTON_POS_RIGHT,
+									   WACOM_TABLET_BUTTON_POS_RIGHT,
 									   group,
 									   0,
 									   GSD_WACOM_NO_LED,
@@ -1161,6 +1231,7 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
 				                                                   settings_path,
 				                                                   WACOM_TABLET_BUTTON_TYPE_STRIP,
 										   WACOM_TABLET_BUTTON_POS_RIGHT,
+										   WACOM_TABLET_BUTTON_POS_RIGHT,
 				                                                   group,
 				                                                   i - 1,
 										   GSD_WACOM_NO_LED,
@@ -1215,6 +1286,7 @@ gsd_wacom_device_button_pos (WacomButtonFlags flags)
 static GList *
 gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
 				  const char       *settings_path,
+				  const char       *layout_path,
 				  WacomButtonFlags  direction,
 				  const char       *button_str_id)
 {
@@ -1260,6 +1332,7 @@ gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
 		                                                   settings_path,
 		                                                   WACOM_TABLET_BUTTON_TYPE_NORMAL,
 		                                                   gsd_wacom_device_button_pos (flags),
+		                                                   gsd_wacom_device_button_draw_pos (i, layout_path, gsd_wacom_device_button_pos (flags)),
 		                                                   flags_to_group (flags),
 		                                                   -1,
 								   GSD_WACOM_NO_LED,
@@ -1289,6 +1362,7 @@ gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
 		                                                   settings_path,
 		                                                   WACOM_TABLET_BUTTON_TYPE_HARDCODED,
 		                                                   gsd_wacom_device_button_pos (flags),
+		                                                   gsd_wacom_device_button_draw_pos (i, layout_path, gsd_wacom_device_button_pos (flags)),
 		                                                   flags_to_group (flags),
 		                                                   -1,
 		                                                   status_led,
@@ -1311,20 +1385,22 @@ gsd_wacom_device_add_buttons (GsdWacomDevice *device,
 			      WacomDevice    *wacom_device,
 			      const char     *settings_path)
 {
+	const char *layout_path;
 	GList *l, *ret;
 
 	ret = NULL;
+	layout_path = gsd_wacom_device_get_layout_path (device);
 
-	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_LEFT, "button");
+	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, layout_path, WACOM_BUTTON_POSITION_LEFT, "button");
 	if (l)
 		ret = l;
-	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_RIGHT, "button");
+	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, layout_path, WACOM_BUTTON_POSITION_RIGHT, "button");
 	if (l)
 		ret = g_list_concat (ret, l);
-	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_TOP, "button");
+	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, layout_path, WACOM_BUTTON_POSITION_TOP, "button");
 	if (l)
 		ret = g_list_concat (ret, l);
-	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_BOTTOM, "button");
+	l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, layout_path, WACOM_BUTTON_POSITION_BOTTOM, "button");
 	if (l)
 		ret = g_list_concat (ret, l);
 
diff --git a/plugins/wacom/gsd-wacom-device.h b/plugins/wacom/gsd-wacom-device.h
index 374eca9..ef3e0a0 100644
--- a/plugins/wacom/gsd-wacom-device.h
+++ b/plugins/wacom/gsd-wacom-device.h
@@ -118,6 +118,7 @@ typedef struct
 	GSettings                *settings;
 	GsdWacomTabletButtonType  type;
 	GsdWacomTabletButtonPos   pos;
+	GsdWacomTabletButtonPos   draw_pos;
 	int                       group_id, idx;
 	int                       status_led;
 	int                       has_oled;
diff --git a/plugins/wacom/gsd-wacom-osd-window.c b/plugins/wacom/gsd-wacom-osd-window.c
index d0814b0..42efb7a 100644
--- a/plugins/wacom/gsd-wacom-osd-window.c
+++ b/plugins/wacom/gsd-wacom-osd-window.c
@@ -1294,7 +1294,7 @@ gsd_wacom_osd_window_add_button_with_dir (GsdWacomOSDWindow    *osd_window,
 	g_free (str);
 
 	gsd_wacom_osd_button_set_button_type (osd_button, tablet_button->type);
-	gsd_wacom_osd_button_set_position (osd_button, tablet_button->pos);
+	gsd_wacom_osd_button_set_position (osd_button, tablet_button->draw_pos);
 	osd_window->priv->buttons = g_list_append (osd_window->priv->buttons, osd_button);
 
 	return osd_button;
-- 
2.9.3