gtk: gtkgesturestylus: implemented `stylus-only` property
authorFlorian "sp1rit"​ <sp1ritCS@protonmail.com>
Sun, 8 May 2022 14:31:43 +0000 (16:31 +0200)
committerFlorian "sp1rit"​ <sp1rit@disroot.org>
Tue, 22 Nov 2022 08:13:35 +0000 (09:13 +0100)
this allows setting a Gtk.GestureStylus to a state, where it can be
used to handle non-stylus devices (e.g. mice).
This might be useful for applications that handle stylus input, but
want to allow falling back to a mice, if the user is unable to provide
stylus input.

gtk/gtkgesturestylus.c
gtk/gtkgesturestylus.h

index d10dfe1a053f4a789dbbe07fa066802eee524b03..8e187c25457017ea5df38eb6ce7ef76a2607e871 100644 (file)
 #include "gtkmain.h"
 #include "gtknative.h"
 
-G_DEFINE_TYPE (GtkGestureStylus, gtk_gesture_stylus, GTK_TYPE_GESTURE_SINGLE)
+typedef struct {
+  gboolean stylus_only;
+} GtkGestureStylusPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkGestureStylus, gtk_gesture_stylus, GTK_TYPE_GESTURE_SINGLE)
+
+enum {
+  PROP_STYLUS_ONLY = 1,
+  N_PROPERTIES
+};
 
 enum {
   PROXIMITY,
@@ -44,20 +53,55 @@ enum {
   N_SIGNALS
 };
 
+static GParamSpec* obj_properties[N_PROPERTIES] = { NULL, };
 static guint signals[N_SIGNALS] = { 0, };
 
+static void gtk_gesture_stylus_get_property (GObject* object,
+                                             guint prop_id,
+                                             GValue* value,
+                                             GParamSpec* pspec)
+{
+       GtkGestureStylus* gesture = GTK_GESTURE_STYLUS(object);
+
+       switch (prop_id) {
+               case PROP_STYLUS_ONLY:
+                       g_value_set_boolean(value, gtk_gesture_stylus_get_stylus_only(gesture));
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void gtk_gesture_stylus_set_property (GObject* object,
+                                             guint prop_id,
+                                             const GValue* value,
+                                             GParamSpec* pspec)
+{
+       GtkGestureStylus* gesture = GTK_GESTURE_STYLUS(object);
+
+       switch (prop_id) {
+               case PROP_STYLUS_ONLY:
+                       gtk_gesture_stylus_set_stylus_only(gesture, g_value_get_boolean(value));
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
 static gboolean
 gtk_gesture_stylus_handle_event (GtkEventController *controller,
                                  GdkEvent           *event,
                                  double              x,
                                  double              y)
 {
+  GtkGestureStylusPrivate* priv;
   GdkModifierType modifiers;
   guint n_signal;
 
+  priv = gtk_gesture_stylus_get_instance_private(GTK_GESTURE_STYLUS(controller));
   GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_stylus_parent_class)->handle_event (controller, event, x, y);
 
-  if (!gdk_event_get_device_tool (event))
+  if (!(priv->stylus_only || gdk_event_get_device_tool (event)))
     return FALSE;
 
   switch ((guint) gdk_event_get_event_type (event))
@@ -88,8 +132,25 @@ gtk_gesture_stylus_handle_event (GtkEventController *controller,
 static void
 gtk_gesture_stylus_class_init (GtkGestureStylusClass *klass)
 {
+  GObjectClass* object_class;
   GtkEventControllerClass *event_controller_class;
 
+  object_class = G_OBJECT_CLASS (klass);
+  object_class->get_property = gtk_gesture_stylus_get_property;
+  object_class->set_property = gtk_gesture_stylus_set_property;
+
+  /**
+   * GtkGestureStylus:stylus-only: (attributes org.gtk.Property.get=gtk_gesture_stylus_get_stylus_only org.gtk.Property.set=gtk_gesture_stylus_set_stylus_only)
+   *
+   * If this gesture should exclusively react to stylus input devices.
+   */
+  obj_properties[PROP_STYLUS_ONLY] = g_param_spec_boolean("stylus-only",
+                                                     P_("Stylus only"),
+                                                     P_("Should this gesture exclusively react to stylus input devices."),
+                                                     TRUE,
+                                                     G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_CONSTRUCT);
+  g_object_class_install_properties(object_class,  N_PROPERTIES, obj_properties);
+
   event_controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
   event_controller_class->handle_event = gtk_gesture_stylus_handle_event;
 
@@ -177,6 +238,9 @@ gtk_gesture_stylus_class_init (GtkGestureStylusClass *klass)
 static void
 gtk_gesture_stylus_init (GtkGestureStylus *gesture)
 {
+  GtkGestureStylusPrivate* priv = gtk_gesture_stylus_get_instance_private(gesture);
+
+  priv->stylus_only = TRUE;
 }
 
 /**
@@ -193,6 +257,53 @@ gtk_gesture_stylus_new (void)
                        NULL);
 }
 
+/**
+ * gtk_gesture_stylus_get_stylus_only: (attributes org.gtk.Method.get_property=stylus-only)
+ * @gesture: A `GtkGestureStylus`
+ *
+ * gets the state of stylus-only, based on which the gesture will
+ * either exclusively signal events from stylus input devices or
+ * for any input devices (e.g. mice).
+ *
+ * Returns: The state of stylus-only set via [method@Gtk.GestureStylus.set_stylus_only]
+ */
+gboolean
+gtk_gesture_stylus_get_stylus_only(GtkGestureStylus* gesture) {
+  GtkGestureStylusPrivate* priv;
+
+  g_return_val_if_fail(GTK_IS_GESTURE_STYLUS(gesture), FALSE);
+
+  priv = gtk_gesture_stylus_get_instance_private(gesture);
+
+  return priv->stylus_only;
+}
+
+/**
+ * gtk_gesture_stylus_set_stylus_only: (attributes org.gtk.Method.set_property=stylus-only)
+ * @gesture: A `GtkGestureStylus`
+ * @stylus_only: %TRUE if the gesture should process exclusivly handle events from styluses
+ *
+ * sets the state of stylus-only
+ *
+ * If true, the gesture will exclusivly handle events from stylus input deivces,
+ * otherwise it'll handle events from any pointing device.
+ */
+void
+gtk_gesture_stylus_set_stylus_only(GtkGestureStylus* gesture, gboolean stylus_only) {
+  GtkGestureStylusPrivate* priv;
+
+  g_return_if_fail(GTK_IS_GESTURE_STYLUS(gesture));
+
+  priv = gtk_gesture_stylus_get_instance_private(gesture);
+
+  if (priv->stylus_only == stylus_only)
+    return;
+
+  priv->stylus_only = stylus_only;
+
+  g_object_notify_by_pspec (G_OBJECT (gesture), obj_properties[PROP_STYLUS_ONLY]);
+}
+
 /**
  * gtk_gesture_stylus_get_axis:
  * @gesture: a `GtkGestureStylus`
index df31f5277a0a4cf05a79b5ffd92f7f7eaa184a05..4bd06128d9f2399e3b4a096944f2631ac051df7b 100644 (file)
@@ -43,6 +43,12 @@ GType             gtk_gesture_stylus_get_type (void) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
 GtkGesture *      gtk_gesture_stylus_new      (void);
 
+GDK_AVAILABLE_IN_4_8
+gboolean          gtk_gesture_stylus_get_stylus_only (GtkGestureStylus* gesture);
+GDK_AVAILABLE_IN_4_8
+void              gtk_gesture_stylus_set_stylus_only (GtkGestureStylus* gesture,
+                                                    gboolean stylus_only);
+
 GDK_AVAILABLE_IN_ALL
 gboolean          gtk_gesture_stylus_get_axis (GtkGestureStylus *gesture,
                                               GdkAxisUse        axis,