mirror of https://github.com/GNOME/gimp.git
app: store keys as keyval/modifiers rather than string.
There is really no need to make back and forth between a string and int/enum representations, and it actually cause problems at times. It's also a problem for the button representation where a modifier will be represented as a key.
This commit is contained in:
parent
9d3ef444ea
commit
100bdeddd9
|
@ -33,6 +33,11 @@
|
|||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
ACCELERATOR_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
@ -41,7 +46,8 @@ enum
|
|||
|
||||
struct _GimpShortcutButtonPrivate
|
||||
{
|
||||
gchar *accelerator;
|
||||
guint keyval;
|
||||
GdkModifierType modifiers;
|
||||
|
||||
GtkWidget *stack;
|
||||
|
||||
|
@ -54,36 +60,39 @@ struct _GimpShortcutButtonPrivate
|
|||
};
|
||||
|
||||
|
||||
static void gimp_shortcut_button_constructed (GObject *object);
|
||||
static void gimp_shortcut_button_finalize (GObject *object);
|
||||
static void gimp_shortcut_button_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_shortcut_button_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_shortcut_button_constructed (GObject *object);
|
||||
static void gimp_shortcut_button_finalize (GObject *object);
|
||||
static void gimp_shortcut_button_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_shortcut_button_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static gboolean gimp_shortcut_button_key_press_event (GtkWidget *button,
|
||||
GdkEventKey *event,
|
||||
gpointer user_data);
|
||||
static gboolean gimp_shortcut_button_focus_out_event (GimpShortcutButton* button,
|
||||
GdkEventFocus event,
|
||||
gpointer user_data);
|
||||
static void gimp_shortcut_button_toggled (GimpShortcutButton* button,
|
||||
gpointer user_data);
|
||||
static gboolean gimp_shortcut_button_key_press_event (GtkWidget *button,
|
||||
GdkEventKey *event,
|
||||
gpointer user_data);
|
||||
static gboolean gimp_shortcut_button_focus_out_event (GimpShortcutButton *button,
|
||||
GdkEventFocus event,
|
||||
gpointer user_data);
|
||||
static void gimp_shortcut_button_toggled (GimpShortcutButton *button,
|
||||
gpointer user_data);
|
||||
|
||||
static void gimp_shortcut_button_update_label (GimpShortcutButton *button);
|
||||
static void gimp_shortcut_button_update_label (GimpShortcutButton *button);
|
||||
|
||||
static gboolean gimp_shortcut_button_timeout (GimpShortcutButton *button);
|
||||
static gboolean gimp_shortcut_button_timeout (GimpShortcutButton *button);
|
||||
|
||||
static void gimp_shortcut_button_keyval_to_modifiers (guint keyval,
|
||||
GdkModifierType *modifiers);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpShortcutButton, gimp_shortcut_button,
|
||||
GTK_TYPE_TOGGLE_BUTTON)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpShortcutButton, gimp_shortcut_button, GTK_TYPE_TOGGLE_BUTTON)
|
||||
|
||||
#define parent_class gimp_shortcut_button_parent_class
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
gimp_shortcut_button_class_init (GimpShortcutButtonClass *klass)
|
||||
|
@ -100,6 +109,16 @@ gimp_shortcut_button_class_init (GimpShortcutButtonClass *klass)
|
|||
NULL, NULL, NULL,
|
||||
GIMP_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY));
|
||||
|
||||
signals[ACCELERATOR_CHANGED] = g_signal_new ("accelerator-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpShortcutButtonClass, accelerator_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
klass->accelerator_changed = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -151,7 +170,6 @@ gimp_shortcut_button_finalize (GObject *object)
|
|||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
|
||||
g_free (button->priv->accelerator);
|
||||
if (button->priv->timer != 0)
|
||||
{
|
||||
g_source_remove (button->priv->timer);
|
||||
|
@ -170,7 +188,7 @@ gimp_shortcut_button_set_property (GObject *object,
|
|||
switch (property_id)
|
||||
{
|
||||
case PROP_ACCELERATOR:
|
||||
gimp_shortcut_button_set_accelerator (button, g_value_get_string (value));
|
||||
gimp_shortcut_button_set_accelerator (button, g_value_get_string (value), 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -190,7 +208,12 @@ gimp_shortcut_button_get_property (GObject *object,
|
|||
switch (property_id)
|
||||
{
|
||||
case PROP_ACCELERATOR:
|
||||
g_value_set_string (value, button->priv->accelerator);
|
||||
{
|
||||
gchar *name = gtk_accelerator_name (button->priv->keyval, button->priv->modifiers);
|
||||
|
||||
g_value_set_string (value, gtk_accelerator_name (button->priv->keyval, button->priv->modifiers));
|
||||
g_free (name);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -213,33 +236,71 @@ gimp_shortcut_button_new (const gchar *accelerator)
|
|||
return GTK_WIDGET (button);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gchar *
|
||||
gimp_shortcut_button_get_accelerator (GimpShortcutButton *button)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_SHORTCUT_BUTTON (button), NULL);
|
||||
|
||||
return button->priv->accelerator;
|
||||
return gtk_accelerator_name (button->priv->keyval, button->priv->modifiers);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_shortcut_button_get_keys (GimpShortcutButton *button,
|
||||
guint *keyval,
|
||||
GdkModifierType *modifiers)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_SHORTCUT_BUTTON (button));
|
||||
|
||||
if (keyval)
|
||||
*keyval = button->priv->keyval;
|
||||
if (modifiers)
|
||||
*modifiers = button->priv->modifiers;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_shortcut_button_set_accelerator (GimpShortcutButton *button,
|
||||
const gchar *accelerator)
|
||||
const gchar *accelerator,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_SHORTCUT_BUTTON (button));
|
||||
|
||||
if (g_strcmp0 (accelerator, button->priv->accelerator) != 0)
|
||||
if (accelerator)
|
||||
gtk_accelerator_parse (accelerator, &keyval, &modifiers);
|
||||
|
||||
if (button->priv->modifier_only_accepted && keyval != 0)
|
||||
{
|
||||
if (button->priv->single_modifier)
|
||||
modifiers = 0;
|
||||
gimp_shortcut_button_keyval_to_modifiers (keyval, &modifiers);
|
||||
keyval = 0;
|
||||
}
|
||||
|
||||
if (keyval != button->priv->keyval || modifiers != button->priv->modifiers)
|
||||
{
|
||||
GtkWidget *label;
|
||||
gchar *previous_accel;
|
||||
gchar *accel;
|
||||
|
||||
previous_accel = gtk_accelerator_name (button->priv->keyval, button->priv->modifiers);
|
||||
button->priv->keyval = keyval;
|
||||
button->priv->modifiers = modifiers;
|
||||
|
||||
label = gtk_stack_get_child_by_name (GTK_STACK (button->priv->stack),
|
||||
"shortcut-label");
|
||||
|
||||
g_free (button->priv->accelerator);
|
||||
button->priv->accelerator = accelerator ? g_strdup (accelerator) : NULL;
|
||||
|
||||
gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (label), accelerator);
|
||||
accel = gtk_accelerator_name (keyval, modifiers);
|
||||
gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (label), accel);
|
||||
g_free (accel);
|
||||
|
||||
g_object_notify (G_OBJECT (button), "accelerator");
|
||||
|
||||
g_signal_emit (button, signals[ACCELERATOR_CHANGED], 0,
|
||||
previous_accel);
|
||||
g_free (previous_accel);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), keyval != 0 || modifiers == 0);
|
||||
gimp_shortcut_button_toggled (GIMP_SHORTCUT_BUTTON (button), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,12 +354,8 @@ gimp_shortcut_button_key_press_event (GtkWidget *widget,
|
|||
{
|
||||
if (event->is_modifier)
|
||||
{
|
||||
gchar *accelerator;
|
||||
|
||||
accelerator = gtk_accelerator_name (event->keyval, 0);
|
||||
gimp_shortcut_button_set_accelerator (button, accelerator);
|
||||
gimp_shortcut_button_set_accelerator (button, NULL, event->keyval, 0);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
|
||||
g_free (accelerator);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -315,12 +372,8 @@ gimp_shortcut_button_key_press_event (GtkWidget *widget,
|
|||
}
|
||||
else if (! event->is_modifier)
|
||||
{
|
||||
gchar *accelerator;
|
||||
|
||||
accelerator = gtk_accelerator_name (event->keyval, accel_mods);
|
||||
gimp_shortcut_button_set_accelerator (button, accelerator);
|
||||
gimp_shortcut_button_set_accelerator (button, NULL, event->keyval, event->state);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
|
||||
g_free (accelerator);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -355,7 +408,7 @@ gimp_shortcut_button_toggled (GimpShortcutButton* button,
|
|||
gimp_shortcut_button_update_label (button);
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ||
|
||||
button->priv->accelerator == NULL)
|
||||
(button->priv->keyval == 0 && button->priv->modifiers == 0))
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (button->priv->stack), "label");
|
||||
else
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (button->priv->stack), "shortcut-label");
|
||||
|
@ -393,12 +446,9 @@ gimp_shortcut_button_update_label (GimpShortcutButton *button)
|
|||
static gboolean
|
||||
gimp_shortcut_button_timeout (GimpShortcutButton *button)
|
||||
{
|
||||
gchar *accelerator;
|
||||
|
||||
accelerator = gtk_accelerator_name (button->priv->last_keyval,
|
||||
button->priv->last_modifiers);
|
||||
gimp_shortcut_button_set_accelerator (button, accelerator);
|
||||
g_free (accelerator);
|
||||
gimp_shortcut_button_set_accelerator (button, NULL,
|
||||
button->priv->last_keyval,
|
||||
button->priv->last_modifiers);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
|
||||
|
||||
|
@ -406,3 +456,41 @@ gimp_shortcut_button_timeout (GimpShortcutButton *button)
|
|||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_shortcut_button_keyval_to_modifiers (guint keyval,
|
||||
GdkModifierType *modifiers)
|
||||
{
|
||||
/* XXX I believe that more keysyms are considered modifiers, but let's
|
||||
* start with this. This basic list is basically taken from GDK code
|
||||
* in gdk/quartz/gdkevents-quartz.c file.
|
||||
*/
|
||||
GdkModifierType mask = 0;
|
||||
|
||||
switch (keyval)
|
||||
{
|
||||
case GDK_KEY_Meta_R:
|
||||
case GDK_KEY_Meta_L:
|
||||
mask = GDK_MOD2_MASK;
|
||||
break;
|
||||
case GDK_KEY_Shift_R:
|
||||
case GDK_KEY_Shift_L:
|
||||
mask = GDK_SHIFT_MASK;
|
||||
break;
|
||||
case GDK_KEY_Caps_Lock:
|
||||
mask = GDK_LOCK_MASK;
|
||||
break;
|
||||
case GDK_KEY_Alt_R:
|
||||
case GDK_KEY_Alt_L:
|
||||
mask = GDK_MOD1_MASK;
|
||||
break;
|
||||
case GDK_KEY_Control_R:
|
||||
case GDK_KEY_Control_L:
|
||||
mask = GDK_CONTROL_MASK;
|
||||
break;
|
||||
default:
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
*modifiers |= mask;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ struct _GimpShortcutButton
|
|||
struct _GimpShortcutButtonClass
|
||||
{
|
||||
GtkToggleButtonClass parent_class;
|
||||
|
||||
void (* accelerator_changed) (GimpShortcutButton *button,
|
||||
const gchar *previous_accelerator);
|
||||
};
|
||||
|
||||
|
||||
|
@ -50,9 +53,14 @@ GType gimp_shortcut_button_get_type (void) G_GNUC_CONST;
|
|||
|
||||
GtkWidget * gimp_shortcut_button_new (const gchar *accelerator);
|
||||
|
||||
const gchar * gimp_shortcut_button_get_accelerator (GimpShortcutButton *button);
|
||||
gchar * gimp_shortcut_button_get_accelerator (GimpShortcutButton *button);
|
||||
void gimp_shortcut_button_get_keys (GimpShortcutButton *button,
|
||||
guint *keyval,
|
||||
GdkModifierType *modifiers);
|
||||
void gimp_shortcut_button_set_accelerator (GimpShortcutButton *button,
|
||||
const gchar *accelerator);
|
||||
const gchar *accelerator,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers);
|
||||
|
||||
void gimp_shortcut_button_accepts_modifier (GimpShortcutButton *button,
|
||||
gboolean only,
|
||||
|
|
Loading…
Reference in New Issue