mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-15 13:10:08 +00:00
gtk: Add GtkShortcut
This is the base class for what is about to take over all sorts of keyboard shortcuts. The initial version barely deals with keybindings.
This commit is contained in:
parent
fed7d3833f
commit
ff13ee4b66
@ -339,6 +339,11 @@
|
||||
<xi:include href="xml/gtkshortcutcontroller.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
<title>Keyboard shortcuts</title>
|
||||
<xi:include href="xml/gtkshortcut.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
<title>Data exchange, clipboards and Drag-and-Drop</title>
|
||||
<xi:include href="xml/gtkdragsource.xml"/>
|
||||
|
@ -6062,6 +6062,30 @@ GTK_EVENT_CONTROLLER_MOTION_GET_CLASS
|
||||
gtk_event_controller_motion_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkshortcut</FILE>
|
||||
<TITLE>GtkShortcut</TITLE>
|
||||
GtkShortcut
|
||||
gtk_shortcut_new
|
||||
gtk_shortcut_set_keyval
|
||||
gtk_shortcut_activate
|
||||
gtk_shortcut_get_arguments
|
||||
gtk_shortcut_set_arguments
|
||||
gtk_shortcut_get_signal
|
||||
gtk_shortcut_set_signal
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_SHORTCUT
|
||||
GTK_SHORTCUT
|
||||
GTK_SHORTCUT_CLASS
|
||||
GTK_IS_SHORTCUT
|
||||
GTK_IS_SHORTCUT_CLASS
|
||||
GTK_SHORTCUT_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
gtk_shortcut_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkshortcutcontroller</FILE>
|
||||
<TITLE>GtkShortcutController</TITLE>
|
||||
|
@ -165,6 +165,7 @@ gtk_search_entry_get_type
|
||||
gtk_selection_model_get_type
|
||||
gtk_separator_get_type
|
||||
gtk_settings_get_type
|
||||
gtk_shortcut_get_type
|
||||
gtk_shortcut_controller_get_type
|
||||
gtk_shortcut_label_get_type
|
||||
gtk_shortcuts_window_get_type
|
||||
|
@ -198,6 +198,7 @@
|
||||
#include <gtk/gtkselectionmodel.h>
|
||||
#include <gtk/gtkseparator.h>
|
||||
#include <gtk/gtksettings.h>
|
||||
#include <gtk/gtkshortcut.h>
|
||||
#include <gtk/gtkshortcutcontroller.h>
|
||||
#include <gtk/gtkshortcutlabel.h>
|
||||
#include <gtk/gtkshortcutsgroup.h>
|
||||
|
317
gtk/gtkshortcut.c
Normal file
317
gtk/gtkshortcut.c
Normal file
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkshortcut.h"
|
||||
|
||||
#include "gtkbindingsprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkwidget.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkshortcut
|
||||
* @title: GtkShortcut
|
||||
* @short_description: An object describing a keyboard shortcut
|
||||
* @see_also: #GtkShortcutController, #GtkShortcutTrigger
|
||||
*
|
||||
* GtkShortcut is the low level object used for managing keyboard
|
||||
* shortcuts.
|
||||
*
|
||||
* It contains a description of how to trigger the shortcut via a
|
||||
* #GtkShortcutTrigger and a way to activate the shortcut on a widget
|
||||
* with gtk_shortcut_activate().
|
||||
*
|
||||
* The actual work is usually done via #GtkShortcutController, which
|
||||
* decides if and when to activate a shortcut. Using that controller
|
||||
* directly however is rarely necessary as Various higher level
|
||||
* convenience APIs exist on #GtkWidgets that make it easier to use
|
||||
* shortcuts in GTK.
|
||||
*
|
||||
* #GtkShortcut does provide functionality to make it easy for users
|
||||
* to work with shortcuts, either by providing informational strings
|
||||
* for display purposes or by allowing shortcuts to be configured.
|
||||
*/
|
||||
|
||||
struct _GtkShortcut
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkModifierType mods;
|
||||
guint keyval;
|
||||
|
||||
char *signal;
|
||||
GVariant *args;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ARGUMENTS,
|
||||
PROP_SIGNAL,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkShortcut, gtk_shortcut, G_TYPE_OBJECT)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_shortcut_dispose (GObject *object)
|
||||
{
|
||||
GtkShortcut *self = GTK_SHORTCUT (object);
|
||||
|
||||
g_clear_pointer (&self->signal, g_free);
|
||||
g_clear_pointer (&self->args, g_variant_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shortcut_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shortcut_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkShortcut *self = GTK_SHORTCUT (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ARGUMENTS:
|
||||
g_value_set_variant (value, self->args);
|
||||
break;
|
||||
|
||||
case PROP_SIGNAL:
|
||||
g_value_set_string (value, self->signal);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shortcut_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkShortcut *self = GTK_SHORTCUT (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ARGUMENTS:
|
||||
gtk_shortcut_set_arguments (self, g_value_get_variant (value));
|
||||
break;
|
||||
|
||||
case PROP_SIGNAL:
|
||||
gtk_shortcut_set_signal (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shortcut_class_init (GtkShortcutClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gtk_shortcut_dispose;
|
||||
gobject_class->get_property = gtk_shortcut_get_property;
|
||||
gobject_class->set_property = gtk_shortcut_set_property;
|
||||
|
||||
/**
|
||||
* GtkShortcut:arguments:
|
||||
*
|
||||
* Arguments passed to activation.
|
||||
*/
|
||||
properties[PROP_ARGUMENTS] =
|
||||
g_param_spec_variant ("arguments",
|
||||
P_("Arguments"),
|
||||
P_("Arguments passed to activation"),
|
||||
G_VARIANT_TYPE_ANY,
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GtkShortcut:signal:
|
||||
*
|
||||
* The action signal to emit on the widget upon activation.
|
||||
*/
|
||||
properties[PROP_SIGNAL] =
|
||||
g_param_spec_string ("signal",
|
||||
P_("Signal"),
|
||||
P_("The action signal to emit"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shortcut_init (GtkShortcut *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_shortcut_new:
|
||||
*
|
||||
* Creates a new empty #GtkShortcut that never triggers and activates nothing.
|
||||
*
|
||||
* Returns: a new #GtkShortcut
|
||||
**/
|
||||
GtkShortcut *
|
||||
gtk_shortcut_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_SHORTCUT, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shortcut_set_keyval (GtkShortcut *self,
|
||||
guint keyval,
|
||||
GdkModifierType mods)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SHORTCUT (self));
|
||||
|
||||
/* To deal with <Shift>, we need to uppercase
|
||||
* or lowercase depending on situation.
|
||||
*/
|
||||
if (mods & GDK_SHIFT_MASK)
|
||||
{
|
||||
if (keyval == GDK_KEY_Tab)
|
||||
keyval = GDK_KEY_ISO_Left_Tab;
|
||||
else
|
||||
keyval = gdk_keyval_to_upper (keyval);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (keyval == GDK_KEY_ISO_Left_Tab)
|
||||
keyval = GDK_KEY_Tab;
|
||||
else
|
||||
keyval = gdk_keyval_to_lower (keyval);
|
||||
}
|
||||
|
||||
self->keyval = keyval;
|
||||
self->mods = mods;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_shortcut_trigger (GtkShortcut *self,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkModifierType mods;
|
||||
guint keyval;
|
||||
|
||||
if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
|
||||
return FALSE;
|
||||
|
||||
/* XXX: This needs to deal with groups */
|
||||
mods = gdk_event_get_modifier_state (event);
|
||||
keyval = gdk_key_event_get_keyval (event);
|
||||
|
||||
return keyval == self->keyval && mods == self->mods;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_shortcut_activate (GtkShortcut *self,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SHORTCUT (self), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
if (self->signal)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean handled;
|
||||
|
||||
if (!gtk_binding_emit_signal (G_OBJECT (widget),
|
||||
self->signal,
|
||||
self->args,
|
||||
&handled,
|
||||
&error))
|
||||
{
|
||||
char *accelerator = gtk_accelerator_name (self->keyval, self->mods);
|
||||
g_warning ("gtk_shortcut_activate(): \":%s\": %s",
|
||||
accelerator,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* shortcut is a dud */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
GVariant *
|
||||
gtk_shortcut_get_arguments (GtkShortcut *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
|
||||
|
||||
return self->args;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shortcut_set_arguments (GtkShortcut *self,
|
||||
GVariant *args)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SHORTCUT (self));
|
||||
|
||||
if (self->args == args)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->args, g_variant_unref);
|
||||
if (args)
|
||||
self->args = g_variant_ref_sink (args);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARGUMENTS]);
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_shortcut_get_signal (GtkShortcut *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
|
||||
|
||||
return self->signal;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shortcut_set_signal (GtkShortcut *self,
|
||||
const gchar *signal)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SHORTCUT (self));
|
||||
|
||||
if (g_strcmp0 (self->signal, signal) == 0)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->signal, g_free);
|
||||
self->signal = g_strdup (signal);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SIGNAL]);
|
||||
}
|
||||
|
60
gtk/gtkshortcut.h
Normal file
60
gtk/gtkshortcut.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_SHORTCUT_H__
|
||||
#define __GTK_SHORTCUT_H__
|
||||
|
||||
#include <gtk/gtktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHORTCUT (gtk_shortcut_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkShortcut, gtk_shortcut, GTK, SHORTCUT, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkShortcut * gtk_shortcut_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_shortcut_set_keyval (GtkShortcut *self,
|
||||
guint keyval,
|
||||
GdkModifierType mods);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_shortcut_trigger (GtkShortcut *self,
|
||||
GdkEvent *event);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_shortcut_activate (GtkShortcut *self,
|
||||
GtkWidget *widget);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GVariant * gtk_shortcut_get_arguments (GtkShortcut *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_shortcut_set_arguments (GtkShortcut *self,
|
||||
GVariant *args);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_shortcut_get_signal (GtkShortcut *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_shortcut_set_signal (GtkShortcut *self,
|
||||
const gchar *signal);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SHORTCUT_H__ */
|
@ -45,6 +45,7 @@ typedef struct _GtkNative GtkNative;
|
||||
typedef struct _GtkRequisition GtkRequisition;
|
||||
typedef struct _GtkRoot GtkRoot;
|
||||
typedef struct _GtkSettings GtkSettings;
|
||||
typedef struct _GtkShortcut GtkShortcut;
|
||||
typedef GdkSnapshot GtkSnapshot;
|
||||
typedef struct _GtkStyleContext GtkStyleContext;
|
||||
typedef struct _GtkTooltip GtkTooltip;
|
||||
|
@ -331,6 +331,7 @@ gtk_public_sources = files([
|
||||
'gtkselectionmodel.c',
|
||||
'gtkseparator.c',
|
||||
'gtksettings.c',
|
||||
'gtkshortcut.c',
|
||||
'gtkshortcutcontroller.c',
|
||||
'gtkshortcutlabel.c',
|
||||
'gtkshortcutsgroup.c',
|
||||
@ -569,6 +570,7 @@ gtk_public_headers = files([
|
||||
'gtkselectionmodel.h',
|
||||
'gtkseparator.h',
|
||||
'gtksettings.h',
|
||||
'gtkshortcut.h',
|
||||
'gtkshortcutcontroller.h',
|
||||
'gtkshortcutlabel.h',
|
||||
'gtkshortcutsgroup.h',
|
||||
|
Loading…
Reference in New Issue
Block a user