The libwacom API does not provide any way for client applications to get the buttons order as this may differ from the actual button definition.

For example, the Bamboo Fun Pen&Touch tablet maps buttons from top to bottom (with pad on the left) as A, D, C, B instead of A, B, C, D as expected, thus breaking the logic used to number the buttons in client apps such as GNOME Wacom settings panel.

E.g. of such a panel definition:

    # Bamboo Fun Pen & Touch (CTH-470S)
    Name=Wacom Bamboo Fun Pen & Touch
    DeviceMatch=usb:056a:00de
    Class=Bamboo

    [Features]
    Stylus=true
    Reversible=true
    Touch=true
    Ring=false
    Ring2=false
    BuiltIn=false
    Buttons=5

    [Buttons]
    Left=A;E;D;C

The following patch allows application to query the order of buttons as listed in the definition file so that if a device has non-continuous button ranges or if buttons are not mapped in order applications can use the actual buttons order as listed in the [Buttons] definition.

Note: This patch takes a very conservative approach, as the original buttons array is kept so that apps that simply loop through all the buttons still work and do not access undefined memory.

It also keeps the num_button field (although we may think this is not required anymore) because some tablet definitions list more buttons that num buttons (e.g. dti-520.tablet which defined 10 buttons but lists 11 as 2 buttons send the same scancode) or vice-versa, the Bamboo Fun defines 5 buttons but list only 4 (as button 2 is not reported).

One noticeable change however is the libwacom_get_num_buttons() which will return the lesser value between the defined "Buttons" value and the length of the buttons listed in the "[Buttons]" section so applications would not get past neither the length of the button string nor the size of the buttons array.
>From e065f35ce419be8e07796bd2d6c1f4f56458c5fe Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofour...@redhat.com>
Date: Tue, 5 Jun 2012 14:34:42 +0200
Subject: [PATCH] lib: Add buttons order

Client applications need this to list the buttons in the same
order the buttons are laid out on the device.

Signed-off-by: Olivier Fourdan <ofour...@redhat.com>
---
 libwacom/libwacom-database.c |    2 ++
 libwacom/libwacom.c          |   27 ++++++++++++++++++++++++++-
 libwacom/libwacom.h          |   10 ++++++++++
 libwacom/libwacomint.h       |    1 +
 4 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c
index 5468975..f3cb3e7 100644
--- a/libwacom/libwacom-database.c
+++ b/libwacom/libwacom-database.c
@@ -268,6 +268,7 @@ libwacom_parse_buttons_key(WacomDevice      *device,
 			g_warning ("Ignoring value '%s' in key '%s'", vals[i], key);
 			continue;
 		}
+		device->buttons_order = g_string_append_c (device->buttons_order, val);
 		val -= 'A';
 		device->buttons[(int) val] |= flag;
 	}
@@ -409,6 +410,7 @@ libwacom_parse_tablet_keyfile(const char *path)
 		g_warning ("Tablet '%s' has no buttons defined, do something!", libwacom_get_match(device));
 		g_clear_error (&error);
 	}
+	device->buttons_order = g_string_new ("");
 	if (device->num_buttons > 0) {
 		device->buttons = g_new0 (WacomButtonFlags, device->num_buttons);
 		libwacom_parse_buttons(device, keyfile);
diff --git a/libwacom/libwacom.c b/libwacom/libwacom.c
index 482baa5..fbbeb35 100644
--- a/libwacom/libwacom.c
+++ b/libwacom/libwacom.c
@@ -306,6 +306,7 @@ libwacom_copy(const WacomDevice *device)
 	d->supported_styli = g_memdup (device->supported_styli, sizeof(int) * device->num_styli);
 	d->num_buttons = device->num_buttons;
 	d->buttons = g_memdup (device->buttons, sizeof(WacomButtonFlags) * device->num_buttons);
+	d->buttons_order = g_string_new (device->buttons_order->str);
 	return d;
 }
 
@@ -373,6 +374,9 @@ libwacom_compare(WacomDevice *a, WacomDevice *b, WacomCompareFlags flags)
 	if (memcmp(a->buttons, b->buttons, sizeof(WacomButtonFlags) * a->num_buttons) != 0)
 		return 1;
 
+	if (!g_string_equal (a->buttons_order, b->buttons_order))
+		return 1;
+
 	if ((flags & WCOMPARE_MATCHES) && compare_matches(a, b) != 0)
 		return 1;
 	else if (strcmp(a->matches[a->match]->match, b->matches[b->match]->match) != 0)
@@ -538,6 +542,20 @@ static void print_button_flag_if(int fd, WacomDevice *device, const char *label,
 	dprintf(fd, "\n");
 }
 
+static void print_buttons_order(int fd, WacomDevice *device)
+{
+	const char *order = libwacom_get_buttons_order(device);
+	const char *b;
+
+	if (libwacom_get_num_buttons(device) == 0)
+		return;
+
+	dprintf(fd, "Buttons order=");
+	for (b = order; *b; b++)
+			dprintf(fd, "%c;", *b);
+	dprintf(fd, "\n");
+}
+
 static void print_buttons_for_device (int fd, WacomDevice *device)
 {
 	int nbuttons = libwacom_get_num_buttons(device);
@@ -622,6 +640,7 @@ libwacom_print_device_description(int fd, WacomDevice *device)
 	dprintf(fd, "NumStrips=%d\n",	libwacom_get_num_strips(device));
 	dprintf(fd, "Buttons=%d\n",		libwacom_get_num_buttons(device));
 
+	print_buttons_order(fd, device);
 	print_buttons_for_device(fd, device);
 }
 
@@ -643,6 +662,7 @@ libwacom_destroy(WacomDevice *device)
 	g_free (device->matches);
 	g_free (device->supported_styli);
 	g_free (device->buttons);
+	g_string_free (device->buttons_order, TRUE);
 	g_free (device);
 }
 
@@ -738,7 +758,7 @@ int libwacom_has_touch(WacomDevice *device)
 
 int libwacom_get_num_buttons(WacomDevice *device)
 {
-	return device->num_buttons;
+	return MIN (device->num_buttons, device->buttons_order->len);
 }
 
 const int *libwacom_get_supported_styli(WacomDevice *device, int *num_styli)
@@ -809,6 +829,11 @@ libwacom_get_button_flag(WacomDevice *device,
 	return device->buttons[index];
 }
 
+const char *libwacom_get_buttons_order(WacomDevice *device)
+{
+	return device->buttons_order->str;
+}
+
 const WacomStylus *libwacom_stylus_get_for_id (WacomDeviceDatabase *db, int id)
 {
 	return g_hash_table_lookup (db->stylus_ht, GINT_TO_POINTER(id));
diff --git a/libwacom/libwacom.h b/libwacom/libwacom.h
index f7e6cf9..fa959a6 100644
--- a/libwacom/libwacom.h
+++ b/libwacom/libwacom.h
@@ -83,6 +83,8 @@ typedef struct _WacomDevice WacomDevice;
 
 typedef struct _WacomMatch WacomMatch;
 
+typedef struct _WacomButton WacomButton;
+
 typedef struct _WacomStylus WacomStylus;
 
 typedef struct _WacomError WacomError;
@@ -458,6 +460,14 @@ WacomBusType libwacom_get_bustype(WacomDevice *device);
 WacomButtonFlags libwacom_get_button_flag(WacomDevice *device,
 					  char         button);
 
+/*
+ * @param device The tablet to query
+ * @return the string of buttons ID between 'A' and 'Z' in the same order
+ * as in the tablet definition.
+ * The string is NULL terminated. Do not free.
+ */
+const char *libwacom_get_buttons_order(WacomDevice *device);
+
 /**
  * Get the WacomStylus for the given tool ID.
  *
diff --git a/libwacom/libwacomint.h b/libwacom/libwacomint.h
index 6d07e16..f041f92 100644
--- a/libwacom/libwacomint.h
+++ b/libwacom/libwacomint.h
@@ -89,6 +89,7 @@ struct _WacomDevice {
 
 	int num_buttons;
 	WacomButtonFlags *buttons;
+	GString *buttons_order;
 
 	gint refcnt; /* for the db hashtable */
 };
-- 
1.7.1

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to