[gtk/wip/matthiasc/shortcut: 12/91] trigger: Add an alternative trigger



commit 109452a5d5f63a8e44a4a9e7493b972bf2c90251
Author: Benjamin Otte <otte redhat com>
Date:   Sun Aug 5 04:10:11 2018 +0200

    trigger: Add an alternative trigger
    
    And use it.
    
    I just added it to GtkWidget just to show that I can.
    The real reason I want it is for gamepad/joystick triggers
    in games, so that it becomes possible to select 2 different
    triggers (gamepad and keyboard) for the same shortcut.

 gtk/gtkshortcuttrigger.c | 169 ++++++++++++++++++++++++++++++++++++++++-------
 gtk/gtkshortcuttrigger.h |  15 ++++-
 gtk/gtkwindow.c          |  24 ++++---
 3 files changed, 172 insertions(+), 36 deletions(-)
---
diff --git a/gtk/gtkshortcuttrigger.c b/gtk/gtkshortcuttrigger.c
index ed75b35e67..39797f177c 100644
--- a/gtk/gtkshortcuttrigger.c
+++ b/gtk/gtkshortcuttrigger.c
@@ -65,10 +65,6 @@ struct _GtkShortcutTriggerClass
                                    GString             *string);
 };
 
-static GtkShortcutTrigger *     gtk_shortcut_trigger_new                (const GtkShortcutTriggerClass  
*trigger_class,
-                                                                         gsize                           
extra_size);
-
-
 G_DEFINE_BOXED_TYPE (GtkShortcutTrigger, gtk_shortcut_trigger,
                      gtk_shortcut_trigger_ref,
                      gtk_shortcut_trigger_unref)
@@ -87,15 +83,14 @@ gtk_shortcut_trigger_finalize (GtkShortcutTrigger *self)
  *
  * Returns: (transfer full): the newly created #GtkShortcutTrigger
  */
-GtkShortcutTrigger *
-gtk_shortcut_trigger_new (const GtkShortcutTriggerClass *trigger_class,
-                          gsize                          extra_size)
+static GtkShortcutTrigger *
+gtk_shortcut_trigger_new (const GtkShortcutTriggerClass *trigger_class)
 {
   GtkShortcutTrigger *self;
 
   g_return_val_if_fail (trigger_class != NULL, NULL);
 
-  self = g_malloc0 (trigger_class->struct_size + extra_size);
+  self = g_malloc0 (trigger_class->struct_size);
   g_atomic_ref_count_init (&self->ref_count);
 
   self->trigger_class = trigger_class;
@@ -232,21 +227,20 @@ struct _GtkNeverTrigger
 };
 
 static void
-gsk_never_trigger_finalize (GtkShortcutTrigger *trigger)
+gtk_never_trigger_finalize (GtkShortcutTrigger *trigger)
 {
   g_assert_not_reached ();
 }
 
 static gboolean
-gsk_never_trigger_trigger (GtkShortcutTrigger *trigger,
+gtk_never_trigger_trigger (GtkShortcutTrigger *trigger,
                            GdkEvent           *event)
-                  
 {
   return FALSE;
 }
 
 static void
-gsk_never_trigger_print (GtkShortcutTrigger *trigger,
+gtk_never_trigger_print (GtkShortcutTrigger *trigger,
                          GString            *string)
                   
 {
@@ -257,15 +251,15 @@ static const GtkShortcutTriggerClass GTK_NEVER_TRIGGER_CLASS = {
   GTK_SHORTCUT_TRIGGER_NEVER,
   sizeof (GtkNeverTrigger),
   "GtkNeverTrigger",
-  gsk_never_trigger_finalize,
-  gsk_never_trigger_trigger,
-  gsk_never_trigger_print
+  gtk_never_trigger_finalize,
+  gtk_never_trigger_trigger,
+  gtk_never_trigger_print
 };
 
 static GtkNeverTrigger never = { { &GTK_NEVER_TRIGGER_CLASS, 1 } };
 
 /**
- * gsk_never_trigger_get:
+ * gtk_never_trigger_get:
  *
  * Gets the never trigger. This is a singleton for a trigger
  * that never triggers. Use this trigger instead of %NULL
@@ -292,12 +286,12 @@ struct _GtkKeyvalTrigger
 };
 
 static void
-gsk_keyval_trigger_finalize (GtkShortcutTrigger *trigger)
+gtk_keyval_trigger_finalize (GtkShortcutTrigger *trigger)
 {
 }
 
 static gboolean
-gsk_keyval_trigger_trigger (GtkShortcutTrigger *trigger,
+gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger,
                             GdkEvent           *event)
 {
   GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
@@ -320,7 +314,7 @@ gsk_keyval_trigger_trigger (GtkShortcutTrigger *trigger,
 }
 
 static void
-gsk_keyval_trigger_print (GtkShortcutTrigger *trigger,
+gtk_keyval_trigger_print (GtkShortcutTrigger *trigger,
                           GString            *string)
                   
 {
@@ -336,13 +330,13 @@ static const GtkShortcutTriggerClass GTK_KEYVAL_TRIGGER_CLASS = {
   GTK_SHORTCUT_TRIGGER_KEYVAL,
   sizeof (GtkKeyvalTrigger),
   "GtkKeyvalTrigger",
-  gsk_keyval_trigger_finalize,
-  gsk_keyval_trigger_trigger,
-  gsk_keyval_trigger_print
+  gtk_keyval_trigger_finalize,
+  gtk_keyval_trigger_trigger,
+  gtk_keyval_trigger_print
 };
 
 /**
- * gsk_keyval_trigger_new:
+ * gtk_keyval_trigger_new:
  * @keyval: The keyval to trigger for
  * @modifiers: the modifiers that need to be present
  *
@@ -357,7 +351,7 @@ gtk_keyval_trigger_new (guint           keyval,
 {
   GtkKeyvalTrigger *self;
 
-  self = (GtkKeyvalTrigger *) gtk_shortcut_trigger_new (&GTK_KEYVAL_TRIGGER_CLASS, 0);
+  self = (GtkKeyvalTrigger *) gtk_shortcut_trigger_new (&GTK_KEYVAL_TRIGGER_CLASS);
 
   /* We store keyvals as lower key */
   if (keyval == GDK_KEY_ISO_Left_Tab)
@@ -406,3 +400,130 @@ gtk_keyval_trigger_get_keyval (GtkShortcutTrigger *self)
 
   return trigger->keyval;
 }
+
+/*** GTK_ALTERNATIVE_TRIGGER ***/
+
+typedef struct _GtkAlternativeTrigger GtkAlternativeTrigger;
+
+struct _GtkAlternativeTrigger
+{
+  GtkShortcutTrigger trigger;
+
+  GtkShortcutTrigger *first;
+  GtkShortcutTrigger *second;
+};
+
+static void
+gtk_alternative_trigger_finalize (GtkShortcutTrigger *trigger)
+{
+  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
+
+  gtk_shortcut_trigger_unref (self->first);
+  gtk_shortcut_trigger_unref (self->second);
+}
+
+static gboolean
+gtk_alternative_trigger_trigger (GtkShortcutTrigger *trigger,
+                                 GdkEvent           *event)
+{
+  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
+
+  if (gtk_shortcut_trigger_trigger (self->first, event))
+    return TRUE;
+
+  if (gtk_shortcut_trigger_trigger (self->second, event))
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+gtk_alternative_trigger_print (GtkShortcutTrigger *trigger,
+                               GString            *string)
+                  
+{
+  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
+
+  gtk_shortcut_trigger_print (self->first, string);
+  g_string_append (string, ", ");
+  gtk_shortcut_trigger_print (self->second, string);
+}
+
+static const GtkShortcutTriggerClass GTK_ALTERNATIVE_TRIGGER_CLASS = {
+  GTK_SHORTCUT_TRIGGER_ALTERNATIVE,
+  sizeof (GtkAlternativeTrigger),
+  "GtkAlternativeTrigger",
+  gtk_alternative_trigger_finalize,
+  gtk_alternative_trigger_trigger,
+  gtk_alternative_trigger_print
+};
+
+/**
+ * gtk_alternative_trigger_new:
+ * @first: (transfer full): The first trigger that may trigger
+ * @second: (transfer full): The second trigger that may trigger
+ *
+ * Creates a #GtkShortcutTrigger that will trigger whenever
+ * either of the two given triggers gets triggered.
+ *
+ * Note that nesting is allowed, so if you want more than two
+ * alternative, create a new alternative trigger for each option.
+ *
+ * Returns: a new #GtkShortcutTrigger
+ */
+GtkShortcutTrigger *
+gtk_alternative_trigger_new (GtkShortcutTrigger *first,
+                             GtkShortcutTrigger *second)
+{
+  GtkAlternativeTrigger *self;
+
+  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (first), NULL);
+  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (second), NULL);
+
+  self = (GtkAlternativeTrigger *) gtk_shortcut_trigger_new (&GTK_ALTERNATIVE_TRIGGER_CLASS);
+
+  self->first = first;
+  self->second = second;
+
+  return &self->trigger;
+}
+
+/**
+ * gtk_alternative_trigger_get_first:
+ * @self: an alternative #GtkShortcutTrigger
+ *
+ * Gets the first of the two alternative triggers that may
+ * trigger @self. gtk_alternative_trigger_get_second() will
+ * return the other one.
+ *
+ * Returns: (transfer none): the first alternative trigger
+ **/
+GtkShortcutTrigger *
+gtk_alternative_trigger_get_first (GtkShortcutTrigger *self)
+{
+  GtkAlternativeTrigger *trigger = (GtkAlternativeTrigger *) self;
+
+  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_ALTERNATIVE), 0);
+
+  return trigger->first;
+}
+
+/**
+ * gtk_alternative_trigger_get_second:
+ * @self: an alternative #GtkShortcutTrigger
+ *
+ * Gets the second of the two alternative triggers that may
+ * trigger @self. gtk_alternative_trigger_get_first() will
+ * return the other one.
+ *
+ * Returns: (transfer none): the second alternative trigger
+ **/
+GtkShortcutTrigger *
+gtk_alternative_trigger_get_second (GtkShortcutTrigger *self)
+{
+  GtkAlternativeTrigger *trigger = (GtkAlternativeTrigger *) self;
+
+  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_ALTERNATIVE), 0);
+
+  return trigger->second;
+}
diff --git a/gtk/gtkshortcuttrigger.h b/gtk/gtkshortcuttrigger.h
index 582a389f45..d37fbcc222 100644
--- a/gtk/gtkshortcuttrigger.h
+++ b/gtk/gtkshortcuttrigger.h
@@ -35,14 +35,17 @@ G_BEGIN_DECLS
 /**
  * GtkShortcutTriggerType:
  * @GTK_SHORTCUT_TRIGGER_NEVER: Never ever trigger
- * @GTK_SHORTCUT_TRIGGER_KEYVAL: Trigger if a key even with matching
+ * @GTK_SHORTCUT_TRIGGER_KEYVAL: Trigger if a key event with matching
  *     modifiers and keyval is received.
+ * @GTK_SHORTCUT_TRIGGER_ALTERNAITVE: Trigger if either if two
+ *     alternatives triggers
  *
  * The type of a trigger determines what the trigger triggers on.
  **/
 typedef enum {
   GTK_SHORTCUT_TRIGGER_NEVER,
-  GTK_SHORTCUT_TRIGGER_KEYVAL
+  GTK_SHORTCUT_TRIGGER_KEYVAL,
+  GTK_SHORTCUT_TRIGGER_ALTERNATIVE
 } GtkShortcutTriggerType;
 
 GDK_AVAILABLE_IN_ALL
@@ -77,6 +80,14 @@ GdkModifierType         gtk_keyval_trigger_get_modifiers        (GtkShortcutTrig
 GDK_AVAILABLE_IN_ALL
 guint                   gtk_keyval_trigger_get_keyval           (GtkShortcutTrigger *self);
 
+GDK_AVAILABLE_IN_ALL
+GtkShortcutTrigger *    gtk_alternative_trigger_new             (GtkShortcutTrigger *one,
+                                                                 GtkShortcutTrigger *two);
+GDK_AVAILABLE_IN_ALL
+GtkShortcutTrigger *    gtk_alternative_trigger_get_first       (GtkShortcutTrigger *self);
+GDK_AVAILABLE_IN_ALL
+GtkShortcutTrigger *    gtk_alternative_trigger_get_second      (GtkShortcutTrigger *self);
+
 G_END_DECLS
 
 #endif /* __GTK_SHORTCUT_TRIGGER_H__ */
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index a0d2993d9d..17ca0a7f3d 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -62,6 +62,8 @@
 #include "gtkroot.h"
 #include "gtknative.h"
 #include "gtksettings.h"
+#include "gtkshortcut.h"
+#include "gtkshortcuttrigger.h"
 #include "gtksnapshot.h"
 #include "gtkstylecontextprivate.h"
 #include "gtktypebuiltins.h"
@@ -569,16 +571,18 @@ add_tab_bindings (GtkWidgetClass   *widget_class,
                  GdkModifierType   modifiers,
                  GtkDirectionType  direction)
 {
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Tab, modifiers,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Tab, modifiers,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
+  GtkShortcut *shortcut;
+
+  shortcut = gtk_shortcut_new ();
+  gtk_shortcut_set_trigger (shortcut,
+                            gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_Tab, modifiers),
+                                                         gtk_keyval_trigger_new (GDK_KEY_KP_Tab, 
modifiers)));
+  gtk_shortcut_set_signal (shortcut, "move-focus");
+  gtk_shortcut_set_arguments (shortcut, g_variant_new_tuple ((GVariant*[1]) { g_variant_new_int32 
(direction) }, 1));
+
+  gtk_widget_class_add_shortcut (widget_class, shortcut);
+
+  g_object_unref (shortcut);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]