Skip to content

Commit

Permalink
Add support for relative dials
Browse files Browse the repository at this point in the history
We already have a number of tablets with a relative dial that sends
mouse wheel events (UCLOGIC/Huion/XP Pen devices, primarily) so let's
add support for these in our description files.

This is copy/paste from the touch strip support.
  • Loading branch information
whot committed Apr 22, 2024
1 parent e14f94f commit 1e81d5e
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 3 deletions.
12 changes: 11 additions & 1 deletion data/wacom.example
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,16 @@ TouchSwitch=false

# This tablet has a touch ring (Intuos4 and Cintiq 24HD)
# A touch ring is a circular button that responds to touch
# (rather than clicks):
# (rather than clicks) and sends absolute events:
# http://intuos.wacom.com/americas/touch-ring.php
Ring=true
# This tablet has a second touch ring (Cintiq 24HD)
Ring2=false

# This tablet's number of dials/rotary toggles that send relative events
# similar to a mouse wheel.
NumDials=1

# This tablet's number of touch strips (e.g. Cintiq 22HD), default is zero
NumStrips=1

Expand Down Expand Up @@ -222,6 +226,12 @@ Touchstrip2=J
# if there is more than one
StripsNumModes=4

# If the dial have mode toggling through a button
Dial=A
# We assume the same number of modes for each of the dials
# if there is more than one
DialsNumModes=4


# Metadata about the keys on the tablet
[Keys]
Expand Down
6 changes: 5 additions & 1 deletion libwacom/libwacom-database.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,8 @@ static const struct {
{ "Ring2", WACOM_BUTTON_RING2_MODESWITCH },
{ "Touchstrip", WACOM_BUTTON_TOUCHSTRIP_MODESWITCH },
{ "Touchstrip2", WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH },
{ "OLEDs", WACOM_BUTTON_OLED }
{ "OLEDs", WACOM_BUTTON_OLED },
{ "Dial", WACOM_BUTTON_DIAL_MODESWITCH },
};

static const struct {
Expand Down Expand Up @@ -671,6 +672,7 @@ libwacom_parse_buttons(WacomDevice *device,
device->ring_num_modes = libwacom_parse_num_modes(device, keyfile, "RingNumModes", WACOM_BUTTON_RING_MODESWITCH);
device->ring2_num_modes = libwacom_parse_num_modes(device, keyfile, "Ring2NumModes", WACOM_BUTTON_RING2_MODESWITCH);
device->strips_num_modes = libwacom_parse_num_modes(device, keyfile, "StripsNumModes", WACOM_BUTTON_TOUCHSTRIP_MODESWITCH);
device->dials_num_modes = libwacom_parse_num_modes(device, keyfile, "DialsNumModes", WACOM_BUTTON_DIAL_MODESWITCH);
}

static void
Expand Down Expand Up @@ -780,6 +782,7 @@ libwacom_parse_features(WacomDevice *device, GKeyFile *keyfile)
g_warning ("Tablet '%s' has touch switch but no touch tool. This is impossible", libwacom_get_match(device));

device->num_strips = g_key_file_get_integer(keyfile, FEATURES_GROUP, "NumStrips", NULL);
device->num_dials = g_key_file_get_integer(keyfile, FEATURES_GROUP, "NumDials", NULL);

string_list = g_key_file_get_string_list(keyfile, FEATURES_GROUP, "StatusLEDs", NULL, NULL);
if (string_list) {
Expand Down Expand Up @@ -916,6 +919,7 @@ libwacom_parse_tablet_keyfile(WacomDeviceDatabase *db,
}

device->num_strips = g_key_file_get_integer(keyfile, FEATURES_GROUP, "NumStrips", NULL);
device->num_dials = g_key_file_get_integer(keyfile, FEATURES_GROUP, "NumDials", NULL);
device->buttons = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, g_free);
device->status_leds = g_array_new (FALSE, FALSE, sizeof(WacomStatusLEDs));
Expand Down
26 changes: 26 additions & 0 deletions libwacom/libwacom.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,10 @@ libwacom_copy(const WacomDevice *device)
d->paired = libwacom_match_ref(device->paired);
d->cls = device->cls;
d->num_strips = device->num_strips;
d->num_dials = device->num_dials;
d->features = device->features;
d->strips_num_modes = device->strips_num_modes;
d->dials_num_modes = device->dials_num_modes;
d->ring_num_modes = device->ring_num_modes;
d->ring2_num_modes = device->ring2_num_modes;
d->styli = g_array_sized_new(FALSE, FALSE, sizeof(int),
Expand Down Expand Up @@ -521,12 +523,18 @@ libwacom_compare(const WacomDevice *a, const WacomDevice *b, WacomCompareFlags f
if (a->num_strips != b->num_strips)
return 1;

if (a->num_dials != b->num_dials)
return 1;

if (a->features != b->features)
return 1;

if (a->strips_num_modes != b->strips_num_modes)
return 1;

if (a->dials_num_modes != b->dials_num_modes)
return 1;

if (a->ring_num_modes != b->ring_num_modes)
return 1;

Expand Down Expand Up @@ -842,13 +850,15 @@ static void print_buttons_for_device (int fd, const WacomDevice *device)
print_button_flag_if(fd, device, "Bottom", WACOM_BUTTON_POSITION_BOTTOM);
print_button_flag_if(fd, device, "Touchstrip", WACOM_BUTTON_TOUCHSTRIP_MODESWITCH);
print_button_flag_if(fd, device, "Touchstrip2", WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH);
print_button_flag_if(fd, device, "Dial", WACOM_BUTTON_DIAL_MODESWITCH);
print_button_flag_if(fd, device, "OLEDs", WACOM_BUTTON_OLED);
print_button_flag_if(fd, device, "Ring", WACOM_BUTTON_RING_MODESWITCH);
print_button_flag_if(fd, device, "Ring2", WACOM_BUTTON_RING2_MODESWITCH);
print_button_evdev_codes(fd, device);
dprintf(fd, "RingNumModes=%d\n", libwacom_get_ring_num_modes(device));
dprintf(fd, "Ring2NumModes=%d\n", libwacom_get_ring2_num_modes(device));
dprintf(fd, "StripsNumModes=%d\n", libwacom_get_strips_num_modes(device));
dprintf(fd, "DialsNumModes=%d\n", libwacom_get_dials_num_modes(device));

dprintf(fd, "\n");
}
Expand Down Expand Up @@ -953,6 +963,9 @@ libwacom_print_device_description(int fd, const WacomDevice *device)
dprintf(fd, "NumStrips=%d\n", libwacom_get_num_strips(device));
dprintf(fd, "\n");

dprintf(fd, "NumDials=%d\n", libwacom_get_num_dials(device));
dprintf(fd, "\n");

print_buttons_for_device(fd, device);
}

Expand Down Expand Up @@ -1238,6 +1251,19 @@ libwacom_get_strips_num_modes(const WacomDevice *device)
return device->strips_num_modes;
}

LIBWACOM_EXPORT int
libwacom_get_num_dials(const WacomDevice *device)
{
return device->num_dials;
}

LIBWACOM_EXPORT int
libwacom_get_dials_num_modes(const WacomDevice *device)
{
return device->dials_num_modes;
}


LIBWACOM_EXPORT const WacomStatusLEDs *
libwacom_get_status_leds(const WacomDevice *device, int *num_leds)
{
Expand Down
21 changes: 20 additions & 1 deletion libwacom/libwacom.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,12 @@ typedef enum {
WACOM_BUTTON_TOUCHSTRIP_MODESWITCH = (1 << 7),
WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH = (1 << 8),
WACOM_BUTTON_OLED = (1 << 9),
WACOM_BUTTON_MODESWITCH = (WACOM_BUTTON_RING_MODESWITCH | WACOM_BUTTON_RING2_MODESWITCH | WACOM_BUTTON_TOUCHSTRIP_MODESWITCH | WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH),
WACOM_BUTTON_DIAL_MODESWITCH = (1 << 10),
WACOM_BUTTON_MODESWITCH = (WACOM_BUTTON_RING_MODESWITCH | WACOM_BUTTON_RING2_MODESWITCH | WACOM_BUTTON_TOUCHSTRIP_MODESWITCH | WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH | WACOM_BUTTON_DIAL_MODESWITCH),
WACOM_BUTTON_DIRECTION = (WACOM_BUTTON_POSITION_LEFT | WACOM_BUTTON_POSITION_RIGHT | WACOM_BUTTON_POSITION_TOP | WACOM_BUTTON_POSITION_BOTTOM),
WACOM_BUTTON_RINGS_MODESWITCH = (WACOM_BUTTON_RING_MODESWITCH | WACOM_BUTTON_RING2_MODESWITCH),
WACOM_BUTTON_TOUCHSTRIPS_MODESWITCH = (WACOM_BUTTON_TOUCHSTRIP_MODESWITCH | WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH),
WACOM_BUTTON_DIALS_MODESWITCH = (WACOM_BUTTON_DIAL_MODESWITCH),
} WacomButtonFlags;

/**
Expand Down Expand Up @@ -670,6 +672,23 @@ int libwacom_get_num_strips(const WacomDevice *device);
*/
int libwacom_get_strips_num_modes(const WacomDevice *device);

/**
* @param device The tablet to query
* @return the number of rotary dials on the tablet
* otherwise
*
* @ingroup devices
*/
int libwacom_get_num_dials(const WacomDevice *device);

/**
* @param device The tablet to query
* @return the number of modes for each of the dials, if any
*
* @ingroup devices
*/
int libwacom_get_dials_num_modes(const WacomDevice *device);

/**
* @param device The tablet to query
* @param num_leds Return location for the number of supported status LEDs
Expand Down
2 changes: 2 additions & 0 deletions libwacom/libwacom.sym
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,7 @@ LIBWACOM_2.9 {
} LIBWACOM_2.0;

LIBWACOM_2.12 {
libwacom_get_num_dials;
libwacom_get_dials_num_modes;
libwacom_match_get_uniq;
} LIBWACOM_2.9;
2 changes: 2 additions & 0 deletions libwacom/libwacomint.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ struct _WacomDevice {

WacomClass cls;
int num_strips;
int num_dials;
uint32_t features;
uint32_t integration_flags;

int strips_num_modes;
int dials_num_modes;
int ring_num_modes;
int ring2_num_modes;

Expand Down
2 changes: 2 additions & 0 deletions test/test-load.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ test_intuos4(struct fixture *f, gconstpointer user_data)
g_assert_false(libwacom_has_ring2(device));
g_assert_false(libwacom_has_touchswitch(device));
g_assert_cmpint(libwacom_get_num_strips(device), ==, 0);
g_assert_cmpint(libwacom_get_num_dials(device), ==, 0);
g_assert_cmpint(libwacom_get_integration_flags (device), ==, WACOM_DEVICE_INTEGRATED_NONE);
g_assert_cmpint(libwacom_get_width(device), ==, 8);
g_assert_cmpint(libwacom_get_height(device), ==, 5);
Expand Down Expand Up @@ -173,6 +174,7 @@ test_cintiq21ux(struct fixture *f, gconstpointer user_data)
g_assert_nonnull(device);

g_assert_cmpint(libwacom_get_num_strips(device), ==, 2);
g_assert_cmpint(libwacom_get_num_dials(device), ==, 0);
libwacom_destroy(device);
}

Expand Down
63 changes: 63 additions & 0 deletions test/test-tablet-svg-validity.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,56 @@ check_touchstrip (xmlNodePtr cur, gchar *id)
g_free (class);
}

static void
check_dial (xmlNodePtr cur, gchar *id)
{
char *sub;
char *class;
xmlNodePtr node;

node = verify_has_sub (cur, id);
g_assert (node != NULL);

class = g_strdup_printf ("%s %s", id, "Dial");
verify_has_class (node, class);
g_free (class);

sub = g_strdup_printf ("Label%sUp", id);
node = verify_has_sub (cur, sub);
g_assert (node != NULL);
g_free (sub);

class = g_strdup_printf ("%sUp %s Label", id, id);
verify_has_class (node, class);
g_free (class);

sub = g_strdup_printf ("Label%sDown", id);
node = verify_has_sub (cur, sub);
g_assert (node != NULL);
g_free (sub);

class = g_strdup_printf ("%sDown %s Label", id, id);
verify_has_class (node, class);
g_free (class);

sub = g_strdup_printf ("Leader%sUp", id);
node = verify_has_sub (cur, sub);
g_assert (node != NULL);
g_free (sub);

class = g_strdup_printf ("%sUp %s Leader", id, id);
verify_has_class (node, class);
g_free (class);

sub = g_strdup_printf ("Leader%sDown", id);
node = verify_has_sub (cur, sub);
g_assert (node != NULL);
g_free (sub);

class = g_strdup_printf ("%sDown %s Leader", id, id);
verify_has_class (node, class);
g_free (class);
}

static void
check_touchring (xmlNodePtr cur, gchar *id)
Expand Down Expand Up @@ -292,6 +342,17 @@ test_strips(struct fixture *f, gconstpointer data)
check_touchstrip(f->root, "Strip2");
}

static void
test_dials(struct fixture *f, gconstpointer data)
{
const WacomDevice *device = data;

if (libwacom_get_num_dials(device) > 0)
check_dial(f->root, "Dial");
if (libwacom_get_num_dials(device) > 1)
check_dial(f->root, "Dial");
}

static void
test_buttons(struct fixture *f, gconstpointer data)
{
Expand Down Expand Up @@ -380,6 +441,8 @@ static void setup_tests(WacomDevice *device)
add_test(device, test_rings);
if (libwacom_get_num_strips(device) > 0)
add_test(device, test_strips);
if (libwacom_get_num_dials(device) > 0)
add_test(device, test_dials);
}

static WacomDeviceDatabase *
Expand Down
15 changes: 15 additions & 0 deletions test/test-tablet-validity.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,20 @@ test_strips(gconstpointer data)
WACOM_BUTTON_TOUCHSTRIP_MODESWITCH));
}

static void
test_dials(gconstpointer data)
{
WacomDevice *device = (WacomDevice*)data;

g_assert_cmpint(libwacom_get_num_dials(device), >=, 0);
g_assert_cmpint(libwacom_get_dials_num_modes(device), >=, 0);

if (libwacom_get_num_dials(device) > 0)
g_assert_true(match_mode_switch(device,
libwacom_get_dials_num_modes,
WACOM_BUTTON_DIAL_MODESWITCH));
}

/* Wrapper function to make adding tests simpler. g_test requires
* a unique test case name so we assemble that from the test function and
* the tablet data.
Expand Down Expand Up @@ -339,6 +353,7 @@ static void setup_tests(WacomDevice *device)
add_test(device, test_styli);
add_test(device, test_rings);
add_test(device, test_strips);
add_test(device, test_dials);

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Expand Down

0 comments on commit 1e81d5e

Please sign in to comment.