widget: Add gtk_widget_class_add_shortcut()

This allows adding shortcuts as a replacement for keybindings.
This commit is contained in:
Benjamin Otte 2018-08-04 12:16:00 +02:00 committed by Matthias Clasen
parent d8603864a9
commit 0eb1228902
5 changed files with 130 additions and 2 deletions

View File

@ -4035,6 +4035,8 @@ gtk_widget_add_tick_callback
gtk_widget_remove_tick_callback
gtk_widget_size_allocate
gtk_widget_allocate
gtk_widget_class_add_shortcut
gtk_widget_class_add_binding_signal
gtk_widget_add_accelerator
gtk_widget_remove_accelerator
gtk_widget_set_accel_path

View File

@ -33,6 +33,8 @@
#include "gtkeventcontrollerprivate.h"
#include "gtkbindings.h"
#include "gtkshortcut.h"
#include "gtkwidgetprivate.h"
#include <gdk/gdk.h>
@ -57,18 +59,41 @@ gtk_shortcut_controller_finalize (GObject *object)
G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->finalize (object);
}
static gboolean
gtk_shortcut_controller_trigger_shortcut (GtkShortcutController *self,
GtkShortcut *shortcut,
const GdkEvent *event)
{
if (!gtk_shortcut_trigger (shortcut, event))
return FALSE;
return gtk_shortcut_activate (shortcut, gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
}
static gboolean
gtk_shortcut_controller_handle_event (GtkEventController *controller,
GdkEvent *event,
double x,
double y)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
GdkEventType event_type = gdk_event_get_event_type (event);
GtkWidget *widget;
const GSList *l;
widget = gtk_event_controller_get_widget (controller);
if (event_type == GDK_KEY_PRESS ||
event_type == GDK_KEY_RELEASE)
return gtk_bindings_activate_event (G_OBJECT (gtk_event_controller_get_widget (controller)),
event);
{
if (gtk_bindings_activate_event (G_OBJECT (widget), event))
return TRUE;
}
for (l = gtk_widget_class_get_shortcuts (GTK_WIDGET_GET_CLASS (widget)); l; l = l->next)
{
if (gtk_shortcut_controller_trigger_shortcut (self, l->data, event))
return TRUE;
}
return FALSE;
}

View File

@ -59,6 +59,7 @@
#include "gtknativeprivate.h"
#include "gtkscrollable.h"
#include "gtksettingsprivate.h"
#include "gtkshortcut.h"
#include "gtkshortcutcontroller.h"
#include "gtksizegroup-private.h"
#include "gtksnapshotprivate.h"
@ -1703,6 +1704,7 @@ static void
gtk_widget_base_class_finalize (GtkWidgetClass *klass)
{
template_data_free (klass->priv->template);
g_slist_free_full (klass->priv->shortcuts, g_object_unref);
}
static void
@ -4301,6 +4303,91 @@ gtk_widget_real_size_allocate (GtkWidget *widget,
{
}
/**
* gtk_widget_class_add_binding_signal: (skip)
* @widget_class: the class to add the binding to
* @mods: key modifier of binding to install
* @keyval: key value of binding to install
* @signal: the signal to execute
* @format_string: GVariant format string for arguments or %NULL for
* no arguments
* @...: arguments, as given by format string.
*
* Creates a new shortcut for @widget_class that emits the given action
* @signal with arguments read according to @format_string.
* The arguments and format string must be provided in the same way as
* with g_variant_new().
*
* This function is a convenience wrapper around
* gtk_widget_class_add_shortcut() and must be called during class
* initialization.
*/
void
gtk_widget_class_add_binding_signal (GtkWidgetClass *widget_class,
GdkModifierType mods,
guint keyval,
const gchar *signal,
const gchar *format_string,
...)
{
GtkShortcut *shortcut;
g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
g_return_if_fail (g_signal_lookup (signal, G_TYPE_FROM_CLASS (widget_class)));
/* XXX: validate variant format for signal */
shortcut = gtk_shortcut_new ();
gtk_shortcut_set_keyval (shortcut, mods, keyval);
gtk_shortcut_set_signal (shortcut, signal);
if (format_string)
{
va_list args;
va_start (args, format_string);
gtk_shortcut_set_arguments (shortcut,
g_variant_new_va (format_string, NULL, &args));
va_end (args);
}
gtk_widget_class_add_shortcut (widget_class, shortcut);
g_object_unref (shortcut);
}
/**
* gtk_widget_class_add_shortcut:
* @widget_class: the class to add the shortcut to
* @shortcut: (transfer none): the #GtkShortcut to add
*
* Installs a shortcut in @widget_class. Every instance created for
* @widget_class or its subclasses will inherit this shortcut and
* trigger it.
*
* Shortcuts added this way will be triggered in the @GTK_PHASE_BUBBLE
* phase, which means they may also trigger if child widgets have focus.
*
* This function must only be used in class initialization functions
* otherwise it is not guaranteed that the shortcut will be installed.
**/
void
gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
GtkShortcut *shortcut)
{
GtkWidgetClassPrivate *priv;
g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
priv = widget_class->priv;
priv->shortcuts = g_slist_prepend (priv->shortcuts, g_object_ref (shortcut));
}
const GSList *
gtk_widget_class_get_shortcuts (GtkWidgetClass *widget_class)
{
return widget_class->priv->shortcuts;
}
static gboolean
gtk_widget_real_can_activate_accel (GtkWidget *widget,
guint signal_id)

View File

@ -373,6 +373,18 @@ void gtk_widget_class_set_layout_manager_type (GtkWidg
GDK_AVAILABLE_IN_ALL
GType gtk_widget_class_get_layout_manager_type (GtkWidgetClass *widget_class);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_add_binding_signal
(GtkWidgetClass *widget_class,
GdkModifierType mods,
guint keyval,
const gchar *signal,
const gchar *format_string,
...);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
GtkShortcut *shortcut);
GDK_AVAILABLE_IN_ALL
void gtk_widget_add_accelerator (GtkWidget *widget,
const gchar *accel_signal,

View File

@ -211,6 +211,7 @@ typedef struct
struct _GtkWidgetClassPrivate
{
GtkWidgetTemplate *template;
GSList *shortcuts;
GType accessible_type;
AtkRole accessible_role;
GQuark css_name;
@ -249,6 +250,7 @@ void _gtk_widget_remove_attached_window (GtkWidget *widget,
const gchar* _gtk_widget_get_accel_path (GtkWidget *widget,
gboolean *locked);
const GSList * gtk_widget_class_get_shortcuts (GtkWidgetClass *widget_class);
AtkObject * _gtk_widget_peek_accessible (GtkWidget *widget);