From 8d0a52298b480d4aa0bfdcf25d8187b66caecf46 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Thu, 29 Feb 2024 10:32:00 +1000
Subject: [PATCH] tablet: add support for relative dials

Some tablets provide one or more rotary controls (see e.g. the Huion
Inspiroy Dial 2) that provide delta information effectively equivalent
to a mouse wheel. Expose those in the same way as the strip or ring
controls, with the event matching the wl_pointer.axis_v120 approach.

Like a typical mouse wheel we do not expect there to be a source
information, so this is left out of the interface.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
 stable/tablet/tablet-v2.xml | 101 +++++++++++++++++++++++++++++++++---
 1 file changed, 94 insertions(+), 7 deletions(-)

diff --git a/stable/tablet/tablet-v2.xml b/stable/tablet/tablet-v2.xml
index 0dbbde14..e2550435 100644
--- a/stable/tablet/tablet-v2.xml
+++ b/stable/tablet/tablet-v2.xml
@@ -1016,7 +1016,7 @@
       <description summary="mode switch event">
 	Notification that the mode was switched.
 
-	A mode applies to all buttons, rings and strips in a group
+	A mode applies to all buttons, rings, strips and dials in a group
 	simultaneously, but a client is not required to assign different actions
 	for each mode. For example, a client may have mode-specific button
 	mappings but map the ring to vertical scrolling in all modes. Mode
@@ -1037,20 +1037,33 @@
 	previous mode, the client should immediately issue a
 	wp_tablet_pad.set_feedback request for each changed button.
 
-	If a ring or strip action in the new mode differs from the action
+	If a ring, strip or dial action in the new mode differs from the action
 	in the previous mode, the client should immediately issue a
-	wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback request
-	for each changed ring or strip.
+	wp_tablet_ring.set_feedback, wp_tablet_strip.set_feedback or
+	wp_tablet_dial.set_feedback request for each changed ring, strip or dial.
       </description>
       <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
       <arg name="serial" type="uint"/>
       <arg name="mode" type="uint" summary="the new mode of the pad"/>
     </event>
+
+    <!-- Version 2 additions -->
+
+    <event name="dial" since="2">
+      <description summary="dial announced">
+	Sent on wp_tablet_pad initialization to announce available dials.
+	One event is sent for each dial available on this pad group.
+
+	This event is sent in the initial burst of events before the
+	wp_tablet_pad_group.done event.
+      </description>
+      <arg name="dial" type="new_id" interface="zwp_tablet_pad_dial_v2"/>
+    </event>
   </interface>
 
   <interface name="zwp_tablet_pad_v2" version="2">
-    <description summary="a set of buttons, rings and strips">
-      A pad device is a set of buttons, rings and strips
+    <description summary="a set of buttons, rings, strips and dials">
+      A pad device is a set of buttons, rings, strips and dials
       usually physically present on the tablet device itself. Some
       exceptions exist where the pad device is physically detached, e.g. the
       Wacom ExpressKey Remote.
@@ -1064,7 +1077,7 @@
       This initial event sequence is terminated by a wp_tablet_pad.done
       event.
 
-      All pad features (buttons, rings and strips) are logically divided into
+      All pad features (buttons, rings, strips and dials) are logically divided into
       groups and all pads have at least one group. The available groups are
       notified through the wp_tablet_pad.group event; the compositor will
       emit one event per group before emitting wp_tablet_pad.done.
@@ -1207,4 +1220,78 @@
       </description>
     </event>
   </interface>
+
+  <interface name="zwp_tablet_pad_dial_v2" version="2">
+    <description summary="pad dial">
+      A rotary control, e.g. a dial or a wheel.
+
+      Events on a dial are logically grouped by the wl_tablet_pad_dial.frame
+      event.
+    </description>
+
+    <request name="set_feedback">
+      <description summary="set compositor feedback">
+	Requests the compositor to use the provided feedback string
+	associated with this dial. This request should be issued immediately
+	after a wp_tablet_pad_group.mode_switch event from the corresponding
+	group is received, or whenever the dial is mapped to a different
+	action. See wp_tablet_pad_group.mode_switch for more details.
+
+	Clients are encouraged to provide context-aware descriptions for
+	the actions associated with the dial, and compositors may use this
+	information to offer visual feedback about the button layout
+	(eg. on-screen displays).
+
+	The provided string 'description' is a UTF-8 encoded string to be
+	associated with this ring, and is considered user-visible; general
+	internationalization rules apply.
+
+	The serial argument will be that of the last
+	wp_tablet_pad_group.mode_switch event received for the group of this
+	dial. Requests providing other serials than the most recent one will be
+	ignored.
+      </description>
+      <arg name="description" type="string" summary="dial description"/>
+      <arg name="serial" type="uint" summary="serial of the mode switch event"/>
+    </request>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the dial object">
+	This destroys the client's resource for this dial object.
+      </description>
+    </request>
+
+    <event name="delta">
+      <description summary="delta movement">
+	Sent whenever the position on a dial changes.
+
+	This event carries the wheel delta as multiples or fractions
+	of 120 with each multiple of 120 representing one logical wheel detent.
+	For example, an axis_value120 of 30 is one quarter of
+	a logical wheel step in the positive direction, a value120 of
+	-240 are two logical wheel steps in the negative direction within the
+	same hardware event. See the wl_pointer.axis_value120 for more details.
+
+	The value120 must not be zero.
+      </description>
+      <arg name="value120" type="int" summary="rotation distance as fraction of 120"/>
+    </event>
+
+    <event name="frame">
+      <description summary="end of a dial event sequence">
+	Indicates the end of a set of events that represent one logical
+	hardware dial event. A client is expected to accumulate the data
+	in all events within the frame before proceeding.
+
+	All wp_tablet_pad_dial events before a wp_tablet_pad_dial.frame event belong
+	logically together.
+
+	A wp_tablet_pad_dial.frame event is sent for every logical event
+	group, even if the group only contains a single wp_tablet_pad_dial
+	event. Specifically, a client may get a sequence: delta, frame,
+	delta, frame, etc.
+      </description>
+      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
+    </event>
+  </interface>
 </protocol>
-- 
GitLab