gtk2/gtk/gtkshortcutcontroller.c

836 lines
24 KiB
C
Raw Normal View History

/*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
/**
* SECTION:gtkshortcutcontroller
* @Short_description: Event controller for shortcuts
* @Title: GtkShortcutController
* @See_also: #GtkEventController, #GtkShortcut
*
* #GtkShortcutController is an event controller that manages shortcuts.
*
2020-03-24 20:29:47 +00:00
* Most common shortcuts are using this controller implicitly, e.g. by
* adding a mnemonic underline to a #GtkLabel, or by installing a key
* binding using gtk_widget_class_add_binding(), or by adding accelerators
* to global actions using gtk_application_set_accels_for_action().
*
* But it is possible to create your own shortcut controller, and add
* shortcuts to it.
*
* #GtkShortcutController implements #GListModel for querying the shortcuts that
* have been added to it.
**/
#include "config.h"
#include "gtkshortcutcontrollerprivate.h"
#include "gtkflattenlistmodel.h"
#include "gtkbuildable.h"
#include "gtkeventcontrollerprivate.h"
#include "gtkintl.h"
#include "gtkshortcut.h"
#include "gtkshortcutmanager.h"
#include "gtkshortcuttrigger.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gtknative.h"
#include <gdk/gdk.h>
struct _GtkShortcutController
{
GtkEventController parent_instance;
GListModel *shortcuts;
GtkShortcutScope scope;
GdkModifierType mnemonics_modifiers;
guint custom_shortcuts : 1;
guint last_activated;
};
struct _GtkShortcutControllerClass
{
GtkEventControllerClass parent_class;
};
enum {
PROP_0,
PROP_MNEMONICS_MODIFIERS,
PROP_MODEL,
PROP_SCOPE,
N_PROPS
};
static GParamSpec *properties[N_PROPS] = { NULL, };
static GType
gtk_shortcut_controller_list_model_get_item_type (GListModel *list)
{
return GTK_TYPE_SHORTCUT;
}
static guint
gtk_shortcut_controller_list_model_get_n_items (GListModel *list)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (list);
return g_list_model_get_n_items (self->shortcuts);
}
static gpointer
gtk_shortcut_controller_list_model_get_item (GListModel *list,
guint position)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (list);
return g_list_model_get_item (self->shortcuts, position);
}
static void
gtk_shortcut_controller_list_model_init (GListModelInterface *iface)
{
iface->get_item_type = gtk_shortcut_controller_list_model_get_item_type;
iface->get_n_items = gtk_shortcut_controller_list_model_get_n_items;
iface->get_item = gtk_shortcut_controller_list_model_get_item;
}
static void
gtk_shortcut_controller_buildable_add_child (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const gchar *type)
{
if (type != NULL)
{
GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
}
if (GTK_IS_SHORTCUT (child))
{
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (buildable), GTK_SHORTCUT (child));
}
else
{
g_warning ("Cannot add an object of type %s to a controller of type %s",
g_type_name (G_OBJECT_TYPE (child)), g_type_name (G_OBJECT_TYPE (buildable)));
}
}
static void
gtk_shortcut_controller_buildable_init (GtkBuildableIface *iface)
{
iface->add_child = gtk_shortcut_controller_buildable_add_child;
}
G_DEFINE_TYPE_WITH_CODE (GtkShortcutController, gtk_shortcut_controller,
GTK_TYPE_EVENT_CONTROLLER,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_shortcut_controller_list_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_shortcut_controller_buildable_init))
static gboolean
gtk_shortcut_controller_is_rooted (GtkShortcutController *self)
{
GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
if (widget == NULL)
return FALSE;
return gtk_widget_get_root (widget) != NULL;
}
static void
gtk_shortcut_controller_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
switch (prop_id)
{
case PROP_MNEMONICS_MODIFIERS:
gtk_shortcut_controller_set_mnemonics_modifiers (self, g_value_get_flags (value));
break;
case PROP_MODEL:
{
GListModel *model = g_value_get_object (value);
if (model && g_list_model_get_item_type (model) != GTK_TYPE_SHORTCUT)
{
g_warning ("Setting a model with type '%s' on a shortcut controller that requires 'GtkShortcut'",
g_type_name (g_list_model_get_item_type (model)));
model = NULL;
}
if (model == NULL)
{
self->shortcuts = G_LIST_MODEL (g_list_store_new (GTK_TYPE_SHORTCUT));
self->custom_shortcuts = TRUE;
}
else
{
self->shortcuts = g_object_ref (model);
self->custom_shortcuts = FALSE;
}
g_signal_connect_swapped (self->shortcuts, "items-changed", G_CALLBACK (g_list_model_items_changed), self);
}
break;
case PROP_SCOPE:
gtk_shortcut_controller_set_scope (self, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gtk_shortcut_controller_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
switch (prop_id)
{
case PROP_MNEMONICS_MODIFIERS:
g_value_set_flags (value, self->mnemonics_modifiers);
break;
case PROP_SCOPE:
g_value_set_enum (value, self->scope);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gtk_shortcut_controller_dispose (GObject *object)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
if (self->custom_shortcuts)
g_list_store_remove_all (G_LIST_STORE (self->shortcuts));
G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->dispose (object);
}
static void
gtk_shortcut_controller_finalize (GObject *object)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
g_signal_handlers_disconnect_by_func (self->shortcuts, g_list_model_items_changed, self);
g_clear_object (&self->shortcuts);
G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->finalize (object);
}
typedef struct {
GtkShortcut *shortcut;
GtkWidget *widget;
guint index;
} ShortcutData;
static void
shortcut_data_free (gpointer data)
{
ShortcutData *sdata = data;
g_object_unref (sdata->shortcut);
g_free (sdata);
}
static gboolean
gtk_shortcut_controller_run_controllers (GtkEventController *controller,
GdkEvent *event,
double x,
double y,
gboolean enable_mnemonics)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
guint i;
GSList *shortcuts = NULL;
GSList *l;
gboolean has_exact = FALSE;
gboolean retval = FALSE;
for (i = 0; i < g_list_model_get_n_items (self->shortcuts); i++)
{
GtkShortcut *shortcut;
ShortcutData *data;
guint index;
GtkWidget *widget;
GtkNative *native;
index = (self->last_activated + 1 + i) % g_list_model_get_n_items (self->shortcuts);
shortcut = g_list_model_get_item (self->shortcuts, index);
switch (gtk_shortcut_trigger_trigger (gtk_shortcut_get_trigger (shortcut), event, enable_mnemonics))
{
case GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL:
if (!has_exact)
break;
G_GNUC_FALLTHROUGH;
case GTK_SHORTCUT_TRIGGER_MATCH_NONE:
g_object_unref (shortcut);
continue;
case GTK_SHORTCUT_TRIGGER_MATCH_EXACT:
if (!has_exact)
{
g_slist_free_full (shortcuts, shortcut_data_free);
shortcuts = NULL;
}
has_exact = TRUE;
break;
default:
g_assert_not_reached ();
}
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
if (!self->custom_shortcuts &&
GTK_IS_FLATTEN_LIST_MODEL (self->shortcuts))
{
GListModel *model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (self->shortcuts), index);
if (GTK_IS_SHORTCUT_CONTROLLER (model))
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (model));
}
native = gtk_widget_get_native (widget);
if (!gtk_widget_is_sensitive (widget) ||
!gtk_widget_get_mapped (widget) ||
!gdk_surface_is_viewable (gtk_native_get_surface (native)))
{
g_object_unref (shortcut);
continue;
}
data = g_new0 (ShortcutData, 1);
data->shortcut = shortcut;
data->index = index;
data->widget = widget;
shortcuts = g_slist_append (shortcuts, data);
}
for (l = shortcuts; l; l = l->next)
{
ShortcutData *data = l->data;
if (gtk_shortcut_action_activate (gtk_shortcut_get_action (data->shortcut),
shortcuts->next == NULL ? GTK_SHORTCUT_ACTION_EXCLUSIVE : 0,
data->widget,
gtk_shortcut_get_arguments (data->shortcut)))
{
self->last_activated = data->index;
retval = TRUE;
break;
}
}
g_slist_free_full (shortcuts, shortcut_data_free);
return retval;
}
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);
gboolean enable_mnemonics;
if (self->scope != GTK_SHORTCUT_SCOPE_LOCAL)
return FALSE;
if (event_type != GDK_KEY_PRESS && event_type != GDK_KEY_RELEASE)
return FALSE;
if (event_type == GDK_KEY_PRESS)
{
GdkModifierType modifiers;
modifiers = gdk_event_get_modifier_state (event);
enable_mnemonics = (modifiers & gtk_accelerator_get_default_mod_mask ()) == self->mnemonics_modifiers;
}
else
{
enable_mnemonics = FALSE;
}
return gtk_shortcut_controller_run_controllers (controller, event, x, y, enable_mnemonics);
}
static void
update_accel (GtkShortcut *shortcut,
GtkWidget *widget,
gboolean set)
{
GtkShortcutTrigger *trigger;
GtkShortcutAction *action;
GtkActionMuxer *muxer;
GVariant *target;
const char *action_name;
char *action_and_target;
char *accel = NULL;
trigger = gtk_shortcut_get_trigger (shortcut);
action = gtk_shortcut_get_action (shortcut);
if (!GTK_IS_NAMED_ACTION (action) ||
!GTK_IS_KEYVAL_TRIGGER (trigger))
return;
muxer = _gtk_widget_get_action_muxer (widget, set);
if (!muxer)
return;
target = gtk_shortcut_get_arguments (shortcut);
action_name = gtk_named_action_get_action_name (GTK_NAMED_ACTION (action));
action_and_target = gtk_print_action_and_target (NULL, action_name, target);
if (set)
accel = gtk_shortcut_trigger_to_string (trigger);
gtk_action_muxer_set_primary_accel (muxer, action_and_target, accel);
g_free (action_and_target);
g_free (accel);
}
static void
gtk_shortcut_controller_set_widget (GtkEventController *controller,
GtkWidget *widget)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
int i;
GTK_EVENT_CONTROLLER_CLASS (gtk_shortcut_controller_parent_class)->set_widget (controller, widget);
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (controller)); i++)
{
GtkShortcut *shortcut = g_list_model_get_item (G_LIST_MODEL (controller), i);
update_accel (shortcut, widget, TRUE);
g_object_unref (shortcut);
}
if (_gtk_widget_get_root (widget))
gtk_shortcut_controller_root (self);
}
static void
gtk_shortcut_controller_unset_widget (GtkEventController *controller)
{
GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
GtkWidget *widget = gtk_event_controller_get_widget (controller);
if (_gtk_widget_get_root (widget))
gtk_shortcut_controller_unroot (self);
#if 0
int i;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (controller)); i++)
{
GtkShortcut *shortcut = g_list_model_get_item (G_LIST_MODEL (controller), i);
update_accel (shortcut, widget, FALSE);
g_object_unref (shortcut);
}
#endif
GTK_EVENT_CONTROLLER_CLASS (gtk_shortcut_controller_parent_class)->unset_widget (controller);
}
static void
gtk_shortcut_controller_class_init (GtkShortcutControllerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
object_class->dispose = gtk_shortcut_controller_dispose;
object_class->finalize = gtk_shortcut_controller_finalize;
object_class->set_property = gtk_shortcut_controller_set_property;
object_class->get_property = gtk_shortcut_controller_get_property;
controller_class->handle_event = gtk_shortcut_controller_handle_event;
controller_class->set_widget = gtk_shortcut_controller_set_widget;
controller_class->unset_widget = gtk_shortcut_controller_unset_widget;
/**
* GtkShortcutController:mnemonic-modifiers:
*
* The modifiers that need to be pressed to allow mnemonics activation.
*/
properties[PROP_MNEMONICS_MODIFIERS] =
g_param_spec_flags ("mnemonic-modifiers",
P_("Mnemonic modifers"),
P_("The modifiers to be pressed to allow mnemonics activation"),
GDK_TYPE_MODIFIER_TYPE,
GDK_MOD1_MASK,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkShortcutController:model:
*
* A list model to take shortcuts from
*/
properties[PROP_MODEL] =
g_param_spec_object ("model",
P_("Model"),
P_("A list model to take shortcuts from"),
G_TYPE_LIST_MODEL,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkShortcutController:scope:
*
* What scope the shortcuts will be handled in.
*/
properties[PROP_SCOPE] =
g_param_spec_enum ("scope",
P_("Scope"),
P_("What scope the shortcuts will be handled in"),
GTK_TYPE_SHORTCUT_SCOPE,
GTK_SHORTCUT_SCOPE_LOCAL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
gtk_shortcut_controller_init (GtkShortcutController *self)
{
self->mnemonics_modifiers = GDK_MOD1_MASK;
}
void
gtk_shortcut_controller_root (GtkShortcutController *self)
{
GtkShortcutManager *manager;
switch (self->scope)
{
case GTK_SHORTCUT_SCOPE_LOCAL:
return;
case GTK_SHORTCUT_SCOPE_MANAGED:
{
GtkWidget *widget;
for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
!GTK_IS_SHORTCUT_MANAGER (widget);
widget = _gtk_widget_get_parent (widget))
;
if (!GTK_IS_SHORTCUT_MANAGER (widget))
return;
manager = GTK_SHORTCUT_MANAGER (widget);
}
break;
case GTK_SHORTCUT_SCOPE_GLOBAL:
{
GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
if (!GTK_IS_SHORTCUT_MANAGER (root))
return;
manager = GTK_SHORTCUT_MANAGER (root);
}
break;
default:
g_assert_not_reached ();
return;
}
GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->add_controller (manager, self);
}
void
gtk_shortcut_controller_unroot (GtkShortcutController *self)
{
GtkShortcutManager *manager;
switch (self->scope)
{
case GTK_SHORTCUT_SCOPE_LOCAL:
return;
case GTK_SHORTCUT_SCOPE_MANAGED:
{
GtkWidget *widget;
for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
!GTK_IS_SHORTCUT_MANAGER (widget);
widget = _gtk_widget_get_parent (widget))
;
if (!GTK_IS_SHORTCUT_MANAGER (widget))
return;
manager = GTK_SHORTCUT_MANAGER (widget);
}
break;
case GTK_SHORTCUT_SCOPE_GLOBAL:
{
GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
if (!GTK_IS_SHORTCUT_MANAGER (root))
return;
manager = GTK_SHORTCUT_MANAGER (root);
}
break;
default:
g_assert_not_reached ();
return;
}
GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->remove_controller (manager, self);
}
2020-03-24 20:29:47 +00:00
/**
* gtk_shortcut_controller_new:
*
* Creates a new shortcut controller.
*
* Returns: a newly created shortcut controller
*/
GtkEventController *
gtk_shortcut_controller_new (void)
{
return g_object_new (GTK_TYPE_SHORTCUT_CONTROLLER,
NULL);
}
2020-03-24 20:29:47 +00:00
/**
* gtk_shortcut_controller_new_for_model:
* @model: a #GListModel containing shortcuts
*
* Creates a new shortcut controller that takes its shortcuts from
* the given list model.
*
* A controller created by this function does not let you add or
* remove individual shortcuts using the shortcut controller api,
* but you can change the contents of the model.
*
* Returns: a newly created shortcut controller
*/
GtkEventController *
gtk_shortcut_controller_new_for_model (GListModel *model)
{
g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
g_return_val_if_fail (g_list_model_get_item_type (model) == GTK_TYPE_SHORTCUT, NULL);
return g_object_new (GTK_TYPE_SHORTCUT_CONTROLLER,
"model", model,
NULL);
}
/**
* gtk_shortcut_controller_add_shortcut:
* @self: the controller
* @shortcut: a #GtkShortcut
*
* Adds @shortcut to the list of shortcuts handled by @self.
*
2020-03-24 20:29:47 +00:00
* If this controller uses an external shortcut list, this
* function does nothing.
**/
void
gtk_shortcut_controller_add_shortcut (GtkShortcutController *self,
GtkShortcut *shortcut)
{
GtkWidget *widget;
g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
if (!self->custom_shortcuts)
return;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
if (widget)
update_accel (shortcut, widget, TRUE);
g_list_store_append (G_LIST_STORE (self->shortcuts), shortcut);
}
/**
* gtk_shortcut_controller_remove_shortcut:
* @self: the controller
* @shortcut: a #GtkShortcut
*
* Removes @shortcut from the list of shortcuts handled by @self.
*
* If @shortcut had not been added to @controller or this controller
* uses an external shortcut list, this function does nothing.
**/
void
gtk_shortcut_controller_remove_shortcut (GtkShortcutController *self,
GtkShortcut *shortcut)
{
GtkWidget *widget;
guint i;
g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
if (!self->custom_shortcuts)
return;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
if (widget)
update_accel (shortcut, widget, FALSE);
for (i = 0; i < g_list_model_get_n_items (self->shortcuts); i++)
{
GtkShortcut *item = g_list_model_get_item (self->shortcuts, i);
if (item == shortcut)
{
g_object_unref (item);
g_list_store_remove (G_LIST_STORE (self->shortcuts), i);
return;
}
g_object_unref (item);
}
}
/**
* gtk_shortcut_controller_set_scope:
* @self: a #GtkShortcutController
* @scope: the new scope to use
*
* Sets the controller to have the given @scope.
*
* The scope allows shortcuts to be activated outside of the normal
* event propagation. In particular, it allows installing global
* keyboard shortcuts that can be activated even when a widget does
* not have focus.
2020-03-24 20:29:47 +00:00
*
* With %GTK_SHORTCUT_SCOPE_LOCAL, shortcuts will only be activated
* when the widget has focus.
**/
void
gtk_shortcut_controller_set_scope (GtkShortcutController *self,
GtkShortcutScope scope)
{
gboolean rooted;
g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
if (self->scope == scope)
return;
rooted = gtk_shortcut_controller_is_rooted (self);
if (rooted)
gtk_shortcut_controller_unroot (self);
self->scope = scope;
if (rooted)
gtk_shortcut_controller_root (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SCOPE]);
}
/**
* gtk_shortcut_controller_get_scope:
* @self: a #GtkShortcutController
*
* Gets the scope for when this controller activates its shortcuts. See
* gtk_shortcut_controller_set_scope() for details.
*
* Returns: the controller's scope
**/
GtkShortcutScope
gtk_shortcut_controller_get_scope (GtkShortcutController *self)
{
g_return_val_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self), GTK_SHORTCUT_SCOPE_LOCAL);
return self->scope;
}
/**
* gtk_shortcut_controller_set_mnemonics_modifiers:
* @self: a #GtkShortcutController
* @modifiers: the new mnemonics_modifiers to use
*
* Sets the controller to have the given @mnemonics_modifiers.
*
* The mnemonics modifiers determines which modifiers need to be pressed to allow
* activation of shortcuts with mnemonics triggers.
*
2020-03-24 20:29:47 +00:00
* GTK normally uses the Alt modifier for mnemonics, except in #GtkPopoverMenus,
* where mnemonics can be triggered without any modifiers. It should be very
* rarely necessary to change this, and doing so is likely to interfere with
* other shortcuts.
*
* This value is only relevant for local shortcut controllers. Global and managed
* shortcut controllers will have their shortcuts activated from other places which
* have their own modifiers for activating mnemonics.
**/
void
gtk_shortcut_controller_set_mnemonics_modifiers (GtkShortcutController *self,
GdkModifierType modifiers)
{
g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
if (self->mnemonics_modifiers == modifiers)
return;
self->mnemonics_modifiers = modifiers;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MNEMONICS_MODIFIERS]);
}
/**
* gtk_shortcut_controller_get_mnemonics_modifiers:
* @self: a #GtkShortcutController
*
* Gets the mnemonics modifiers for when this controller activates its shortcuts. See
* gtk_shortcut_controller_set_mnemonics_modifiers() for details.
*
* Returns: the controller's mnemonics modifiers
**/
GdkModifierType
gtk_shortcut_controller_get_mnemonics_modifiers (GtkShortcutController *self)
{
g_return_val_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self), GTK_SHORTCUT_SCOPE_LOCAL);
return self->mnemonics_modifiers;
}