Mnemonics patch
- From: Alexander Larsson <alla lysator liu se>
- To: <gtk-devel-list gnome org>
- Cc: <otaylor redhat com>, <timj gtk org>
- Subject: Mnemonics patch
- Date: Wed, 21 Mar 2001 12:51:02 +0100 (CET)
Ok. Here is the final patch for label uline accelerators, now called
mnemonics. I really like it.
If nobody says otherwise before 20:00 CET today I will check this in,
since I'll be gone for a while snowboarding and I don't want this to
bitrot in my tree while I'm gone.
Index: gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.98
diff -u -p -r1.98 gtkwidget.h
--- gtkwidget.h 2001/03/18 04:50:34 1.98
+++ gtkwidget.h 2001/03/21 11:32:36
@@ -268,6 +268,10 @@ struct _GtkWidgetClass
guint accel_key,
GdkModifierType accel_mods);
+ /* Mnemonics */
+ gboolean (* activate_mnemonic) (GtkWidget *widget,
+ gboolean group_cycling);
+
/* explicit focus */
void (* grab_focus) (GtkWidget *widget);
@@ -464,6 +468,8 @@ guint gtk_widget_accelerator_signal
void gtk_widget_lock_accelerators (GtkWidget *widget);
void gtk_widget_unlock_accelerators (GtkWidget *widget);
gboolean gtk_widget_accelerators_locked (GtkWidget *widget);
+gboolean gtk_widget_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
gboolean gtk_widget_event (GtkWidget *widget,
GdkEvent *event);
gint gtk_widget_send_expose (GtkWidget *widget,
Index: gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.195
diff -u -p -r1.195 gtkwidget.c
--- gtkwidget.c 2001/03/18 04:50:34 1.195
+++ gtkwidget.c 2001/03/21 11:32:36
@@ -62,6 +62,7 @@ enum {
DIRECTION_CHANGED,
ADD_ACCELERATOR,
REMOVE_ACCELERATOR,
+ ACTIVATE_MNEMONIC,
GRAB_FOCUS,
EVENT,
BUTTON_PRESS_EVENT,
@@ -188,6 +189,8 @@ static gint gtk_widget_event_internal
static void gtk_widget_propagate_hierarchy_changed (GtkWidget *widget,
gpointer client_data);
+static gboolean gtk_widget_real_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
static GtkWidgetAuxInfo* gtk_widget_aux_info_new (void);
static void gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info);
@@ -290,6 +293,7 @@ gtk_widget_class_init (GtkWidgetClass *k
klass->direction_changed = gtk_widget_direction_changed;
klass->add_accelerator = (void*) gtk_accel_group_handle_add;
klass->remove_accelerator = (void*) gtk_accel_group_handle_remove;
+ klass->activate_mnemonic = gtk_widget_real_activate_mnemonic;
klass->grab_focus = gtk_widget_real_grab_focus;
klass->event = NULL;
klass->button_press_event = NULL;
@@ -460,6 +464,14 @@ gtk_widget_class_init (GtkWidgetClass *k
widget_signals[REMOVE_ACCELERATOR] =
gtk_accel_group_create_remove (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator));
+ widget_signals[ACTIVATE_MNEMONIC] =
+ gtk_signal_new ("activate_mnemonic",
+ GTK_RUN_LAST,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, activate_mnemonic),
+ gtk_marshal_BOOLEAN__BOOLEAN,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_BOOL);
widget_signals[GRAB_FOCUS] =
gtk_signal_new ("grab_focus",
GTK_RUN_LAST | GTK_RUN_ACTION,
@@ -2174,6 +2186,36 @@ gtk_widget_accelerator_signal (GtkWidget
return ac_entry->signal_id;
return 0;
}
+
+gboolean
+gtk_widget_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ gboolean handled = FALSE;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ return TRUE;
+
+ gtk_signal_emit_by_name (GTK_OBJECT (widget),
+ "activate_mnemonic",
+ group_cycling,
+ &handled);
+ return handled;
+}
+
+static gboolean
+gtk_widget_real_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ if (group_cycling)
+ gtk_widget_grab_focus (widget);
+ else if (!group_cycling)
+ gtk_widget_activate (widget);
+ return TRUE;
+}
+
static gint
gtk_widget_real_key_press_event (GtkWidget *widget,
Index: gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.30
diff -u -p -r1.30 gtkwindow.h
--- gtkwindow.h 2001/03/16 20:12:40 1.30
+++ gtkwindow.h 2001/03/21 11:32:37
@@ -99,6 +99,8 @@ struct _GtkWindow
guint frame_top;
guint frame_right;
guint frame_bottom;
+
+ guint mnemonic_modifier;
};
struct _GtkWindowClass
@@ -174,6 +176,19 @@ GList* gtk_window_list_toplevels
/* Get the "built-in" accel group (convenience thing) */
GtkAccelGroup* gtk_window_get_default_accel_group (GtkWindow *window);
+
+void gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target);
+void gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target);
+gboolean gtk_window_activate_mnemonic (GtkWindow *window,
+ guint keyval,
+ guint modifier);
+void gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ guint modifier);
+
void gtk_window_present (GtkWindow *window);
void gtk_window_iconify (GtkWindow *window);
Index: gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.106
diff -u -p -r1.106 gtkwindow.c
--- gtkwindow.c 2001/03/18 04:50:34 1.106
+++ gtkwindow.c 2001/03/21 11:32:37
@@ -99,6 +99,14 @@ typedef struct {
GtkWindowLastGeometryInfo last;
} GtkWindowGeometryInfo;
+typedef struct {
+ GtkWindow *window;
+ guint keyval;
+
+ GSList *targets;
+} GtkWindowMnemonic;
+
+
static void gtk_window_class_init (GtkWindowClass *klass);
static void gtk_window_init (GtkWindow *window);
static void gtk_window_shutdown (GObject *object);
@@ -182,6 +190,7 @@ static void gtk_window_geometry_destroy
static GSList *toplevel_list = NULL;
+static GHashTable *mnemonic_hash_table = NULL;
static GtkBinClass *parent_class = NULL;
static guint window_signals[LAST_SIGNAL] = { 0 };
@@ -194,6 +203,36 @@ static void gtk_window_get_property (GOb
GValue *value,
GParamSpec *pspec);
+
+static guint
+mnemonic_hash (gconstpointer key)
+{
+ const GtkWindowMnemonic *k;
+ guint h;
+
+ k = (GtkWindowMnemonic *)key;
+
+ h = (gulong) k->window;
+ h ^= k->keyval << 16;
+ h ^= k->keyval >> 16;
+
+ return h;
+}
+
+static gboolean
+mnemonic_equal (gconstpointer a, gconstpointer b)
+{
+ const GtkWindowMnemonic *ka;
+ const GtkWindowMnemonic *kb;
+
+ ka = (GtkWindowMnemonic *)a;
+ kb = (GtkWindowMnemonic *)b;
+
+ return
+ (ka->window == kb->window) &&
+ (ka->keyval == kb->keyval);
+}
+
GtkType
gtk_window_get_type (void)
{
@@ -373,6 +412,11 @@ gtk_window_class_init (GtkWindowClass *k
gtk_marshal_BOOLEAN__BOXED,
GTK_TYPE_BOOL, 1,
GTK_TYPE_GDK_EVENT);
+
+
+ if (!mnemonic_hash_table)
+ mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
+ mnemonic_equal);
}
static void
@@ -407,6 +451,7 @@ gtk_window_init (GtkWindow *window)
window->frame_bottom = 0;
window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
window->decorated = TRUE;
+ window->mnemonic_modifier = GDK_MOD1_MASK;
gtk_widget_ref (GTK_WIDGET (window));
gtk_object_sink (GTK_OBJECT (window));
@@ -801,6 +846,132 @@ gtk_window_get_default_accel_group (GtkW
}
void
+gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ key.window = window;
+ key.keyval = keyval;
+
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ if (mnemonic)
+ mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
+ else
+ {
+ mnemonic = g_new (GtkWindowMnemonic, 1);
+ *mnemonic = key;
+ mnemonic->targets = g_slist_prepend (NULL, target);
+ g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
+ }
+}
+
+void
+gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ key.window = window;
+ key.keyval = keyval;
+
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ g_assert (mnemonic);
+
+ if (mnemonic)
+ {
+ mnemonic->targets = g_slist_remove (mnemonic->targets, target);
+
+ if (mnemonic->targets == NULL)
+ {
+ g_hash_table_remove (mnemonic_hash_table, mnemonic);
+ g_free (mnemonic);
+ }
+ }
+}
+
+gboolean
+gtk_window_activate_mnemonic (GtkWindow *window,
+ guint keyval,
+ guint modifier)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+ GSList *list;
+ GtkWidget *widget, *chosen_widget;
+ gboolean overloaded;
+
+ g_return_val_if_fail (window != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ if (modifier != window->mnemonic_modifier)
+ return FALSE;
+
+ key.window = window;
+ key.keyval = keyval;
+
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ if (!mnemonic)
+ return FALSE;
+
+ overloaded = FALSE;
+ chosen_widget = NULL;
+ list = mnemonic->targets;
+ while (list)
+ {
+ widget = GTK_WIDGET (list->data);
+
+ if (GTK_WIDGET_IS_SENSITIVE (widget) &&
+ GTK_WIDGET_MAPPED (widget))
+ {
+ if (chosen_widget)
+ {
+ overloaded = TRUE;
+ break;
+ }
+ else
+ chosen_widget = widget;
+ }
+ list = g_slist_next (list);
+ }
+
+ if (chosen_widget)
+ {
+ /* For round robin we put the activated entry on
+ * the end of the list after activation */
+ mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
+ mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
+ return gtk_widget_activate_mnemonic (chosen_widget, overloaded);
+ }
+ return FALSE;
+}
+
+void
+gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ guint modifier)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ window->mnemonic_modifier = modifier;
+}
+
+void
gtk_window_set_position (GtkWindow *window,
GtkWindowPosition position)
{
@@ -1358,6 +1529,24 @@ gtk_window_destroy (GtkObject *object)
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
+static gboolean
+gtk_window_mnemonic_hash_remove (gpointer key,
+ gpointer value,
+ gpointer user)
+{
+ GtkWindowMnemonic *mnemonic = key;
+ GtkWindow *window = user;
+
+ if (mnemonic->window == window)
+ {
+ g_slist_free (mnemonic->targets);
+ g_free (mnemonic);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void
gtk_window_finalize (GObject *object)
{
@@ -1373,6 +1562,10 @@ gtk_window_finalize (GObject *object)
g_free (window->wmclass_name);
g_free (window->wmclass_class);
+ g_hash_table_foreach_remove (mnemonic_hash_table,
+ gtk_window_mnemonic_hash_remove,
+ window);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -1877,7 +2070,12 @@ gtk_window_key_press_event (GtkWidget
{
handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
}
-
+
+ if (!handled)
+ handled = gtk_window_activate_mnemonic (window,
+ event->keyval,
+ event->state);
+
if (!handled)
handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
Index: gtklabel.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtklabel.h,v
retrieving revision 1.26
diff -u -p -r1.26 gtklabel.h
--- gtklabel.h 2001/03/07 21:10:44 1.26
+++ gtklabel.h 2001/03/21 11:32:34
@@ -29,6 +29,8 @@
#include <gdk/gdk.h>
#include <gtk/gtkmisc.h>
+#include <gtk/gtkmnemonicactivator.h>
+#include <gtk/gtkwindow.h>
#ifdef __cplusplus
@@ -60,13 +62,16 @@ struct _GtkLabel
guint use_underline : 1;
guint use_markup : 1;
- guint accel_keyval;
+ guint mnemonic_keyval;
gchar *text;
PangoAttrList *attrs;
PangoLayout *layout;
+ GtkWidget *mnemonic_widget;
+ GtkWindow *mnemonic_window;
+
GtkLabelSelectionInfo *select_info;
};
@@ -75,8 +80,9 @@ struct _GtkLabelClass
GtkMiscClass parent_class;
};
-GtkType gtk_label_get_type (void) G_GNUC_CONST;
-GtkWidget *gtk_label_new (const char *str);
+GtkType gtk_label_get_type (void) G_GNUC_CONST;
+GtkWidget *gtk_label_new (const char *str);
+GtkWidget *gtk_label_new_with_mnemonic (const char *str);
void gtk_label_set_text (GtkLabel *label,
const char *str);
@@ -86,23 +92,27 @@ void gtk_label_set_attributes (Gtk
PangoAttrList *attrs);
void gtk_label_set_markup (GtkLabel *label,
- const gchar *str);
-guint gtk_label_set_markup_with_accel (GtkLabel *label,
const gchar *str);
-
-guint gtk_label_get_accel_keyval (GtkLabel *label);
-void gtk_label_set_justify (GtkLabel *label,
- GtkJustification jtype);
-void gtk_label_set_pattern (GtkLabel *label,
- const gchar *pattern);
-void gtk_label_set_line_wrap (GtkLabel *label,
- gboolean wrap);
+void gtk_label_set_markup_with_mnemonic (GtkLabel *label,
+ const gchar *str);
+
+guint gtk_label_get_mnemonic_keyval (GtkLabel *label);
+void gtk_label_set_justify (GtkLabel *label,
+ GtkJustification jtype);
+void gtk_label_set_pattern (GtkLabel *label,
+ const gchar *pattern);
+void gtk_label_set_line_wrap (GtkLabel *label,
+ gboolean wrap);
/* Convenience function to set the name and pattern by parsing
* a string with embedded underscores, and return the appropriate
* key symbol for the accelerator.
*/
-guint gtk_label_parse_uline (GtkLabel *label,
- const gchar *string);
+guint gtk_label_parse_uline (GtkLabel *label,
+ const gchar *string);
+void gtk_label_set_text_with_mnemonic (GtkLabel *label,
+ const gchar *string);
+void gtk_label_set_mnemonic_widget (GtkLabel *label,
+ GtkWidget *widget);
void gtk_label_set_selectable (GtkLabel *label,
gboolean setting);
Index: gtklabel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtklabel.c,v
retrieving revision 1.79
diff -u -p -r1.79 gtklabel.c
--- gtklabel.c 2001/03/09 16:43:15 1.79
+++ gtklabel.c 2001/03/21 11:32:34
@@ -26,11 +26,15 @@
#include <math.h>
#include <string.h>
#include "gtklabel.h"
+#include "gtksignal.h"
+#include "gtkwindow.h"
#include "gdk/gdkkeysyms.h"
#include "gtkclipboard.h"
#include "gdk/gdki18n.h"
#include <pango/pango.h>
#include "gtkintl.h"
+#include "gtkmenuitem.h"
+#include "gtknotebook.h"
struct _GtkLabelSelectionInfo
{
@@ -39,6 +43,7 @@ struct _GtkLabelSelectionInfo
gint selection_end;
};
+
enum {
PROP_0,
PROP_LABEL,
@@ -49,7 +54,7 @@ enum {
PROP_PATTERN,
PROP_WRAP,
PROP_SELECTABLE,
- PROP_ACCEL_KEYVAL
+ PROP_MNEMONIC_KEYVAL
};
static void gtk_label_class_init (GtkLabelClass *klass);
@@ -57,13 +62,11 @@ static void gtk_label_init
static void gtk_label_set_property (GObject *object,
guint prop_id,
const GValue *value,
- GParamSpec *pspec,
- const gchar *trailer);
+ GParamSpec *pspec);
static void gtk_label_get_property (GObject *object,
guint prop_id,
GValue *value,
- GParamSpec *pspec,
- const gchar *trailer);
+ GParamSpec *pspec);
static void gtk_label_finalize (GObject *object);
static void gtk_label_size_request (GtkWidget *widget,
GtkRequisition *requisition);
@@ -106,6 +109,7 @@ static void set_markup
const gchar *str,
gboolean with_uline);
static void gtk_label_recalculate (GtkLabel *label);
+static void gtk_label_hierarchy_changed (GtkWidget *widget);
static void gtk_label_create_window (GtkLabel *label);
static void gtk_label_destroy_window (GtkLabel *label);
@@ -117,6 +121,9 @@ static void gtk_label_select_region_inde
gint anchor_index,
gint end_index);
+static gboolean gtk_label_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
+
static GtkMiscClass *parent_class = NULL;
@@ -175,6 +182,8 @@ gtk_label_class_init (GtkLabelClass *cla
widget_class->button_press_event = gtk_label_button_press;
widget_class->button_release_event = gtk_label_button_release;
widget_class->motion_notify_event = gtk_label_motion;
+ widget_class->hierarchy_changed = gtk_label_hierarchy_changed;
+ widget_class->activate_mnemonic = gtk_label_activate_mnemonic;
g_object_class_install_property (G_OBJECT_CLASS(object_class),
PROP_LABEL,
@@ -201,7 +210,7 @@ gtk_label_class_init (GtkLabelClass *cla
PROP_USE_UNDERLINE,
g_param_spec_boolean ("use_underline",
_("Use underline"),
- _("If set, an underline in the text indicates the next character should be used for the accelerator key"),
+ _("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
FALSE,
G_PARAM_READWRITE));
@@ -237,22 +246,22 @@ gtk_label_class_init (GtkLabelClass *cla
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
- PROP_ACCEL_KEYVAL,
- g_param_spec_uint ("accel_keyval",
- _("Accelerator key value"),
- _("The accelerator key for this label."),
+ PROP_MNEMONIC_KEYVAL,
+ g_param_spec_uint ("mnemonic_keyval",
+ _("Mnemonic accelerator key value"),
+ _("The mnemonic accelerator key for this label."),
0,
G_MAXUINT,
GDK_VoidSymbol,
G_PARAM_READABLE));
+
}
static void
gtk_label_set_property (GObject *object,
guint prop_id,
const GValue *value,
- GParamSpec *pspec,
- const gchar *trailer)
+ GParamSpec *pspec)
{
GtkLabel *label;
@@ -298,8 +307,7 @@ static void
gtk_label_get_property (GObject *object,
guint prop_id,
GValue *value,
- GParamSpec *pspec,
- const gchar *trailer)
+ GParamSpec *pspec)
{
GtkLabel *label;
@@ -328,8 +336,8 @@ gtk_label_get_property (GObject *obj
case PROP_SELECTABLE:
g_value_set_boolean (value, gtk_label_get_selectable (label));
break;
- case PROP_ACCEL_KEYVAL:
- g_value_set_uint (value, label->accel_keyval);
+ case PROP_MNEMONIC_KEYVAL:
+ g_value_set_uint (value, label->mnemonic_keyval);
break;
default:
@@ -351,14 +359,24 @@ gtk_label_init (GtkLabel *label)
label->use_underline = FALSE;
label->use_markup = FALSE;
- label->accel_keyval = GDK_VoidSymbol;
+ label->mnemonic_keyval = GDK_VoidSymbol;
label->layout = NULL;
label->text = NULL;
label->attrs = NULL;
+
+ label->mnemonic_widget = NULL;
+ label->mnemonic_window = NULL;
gtk_label_set_text (label, "");
}
+/**
+ * gtk_label_new:
+ * @str: The text of the label
+ * @returns: a new #GtkLabel
+ *
+ * Creates a new #GtkLabel, containing the text in @str.
+ **/
GtkWidget*
gtk_label_new (const gchar *str)
{
@@ -373,20 +391,135 @@ gtk_label_new (const gchar *str)
}
/**
- * gtk_label_get_accel_keyval:
+ * gtk_label_new_with_mnemonic:
+ * @str: The text of the label, with an underscore in front of the
+ * mnemonic character
+ * @returns: a new #GtkLabel
+ *
+ * Creates a new #GtkLabel, containing the text in @str.
+ *
+ * If characters in @str are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * The mnemonic key can be used to activate another widget, chosen automatically,
+ * or explicitly using @gtk_label_set_mnemonic_widget.
+ **/
+GtkWidget*
+gtk_label_new_with_mnemonic (const gchar *str)
+{
+ GtkLabel *label;
+
+ label = gtk_type_new (GTK_TYPE_LABEL);
+
+ if (str && *str)
+ gtk_label_set_text_with_mnemonic (label, str);
+
+ return GTK_WIDGET (label);
+}
+
+static gboolean
+gtk_label_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ GtkWidget *parent;
+
+ if (GTK_LABEL (widget)->mnemonic_widget)
+ return gtk_widget_activate_mnemonic (GTK_LABEL (widget)->mnemonic_widget, group_cycling);
+
+ /* Try to find the widget to activate by traversing the widget
+ * hierarachy.
+ */
+
+ parent = widget->parent;
+ while (parent)
+ {
+ if (GTK_WIDGET_CAN_FOCUS (parent) ||
+ (!group_cycling && GTK_WIDGET_GET_CLASS (parent)->activate_signal) ||
+ (parent->parent && GTK_IS_NOTEBOOK (parent->parent)) ||
+ (GTK_IS_MENU_ITEM (parent)))
+ return gtk_widget_activate_mnemonic (parent, group_cycling);
+ parent = parent->parent;
+ }
+
+ g_warning ("Couldn't find a target for a mnemonic activation.");
+ gdk_beep ();
+
+ return FALSE;
+}
+
+static void
+gtk_label_setup_mnemonic (GtkLabel *label, guint last_key)
+{
+ GtkWidget *toplevel;
+
+ if ((last_key != GDK_VoidSymbol) && label->mnemonic_window)
+ gtk_window_remove_mnemonic (label->mnemonic_window,
+ last_key,
+ GTK_WIDGET (label));
+
+ if (label->mnemonic_keyval == GDK_VoidSymbol)
+ return;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
+
+ if (GTK_IS_WINDOW (toplevel))
+ gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
+ label->mnemonic_keyval,
+ GTK_WIDGET (label));
+}
+
+static void
+gtk_label_hierarchy_changed (GtkWidget *widget)
+{
+ GtkLabel *label = GTK_LABEL (widget);
+
+ gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
+}
+
+
+/**
+ * gtk_label_set_mnemonic_widget:
* @label: a #GtkLabel
+ * @widget: the target #GtkWidget
+ *
+ * If the label has been set so that it has an mnemonic key (using i.e.
+ * @gtk_label_set_markup_with_mnemonic, @gtk_label_set_text_with_mnemonic,
+ * @gtk_label_new_with_mnemonic or the use_underline property) the label can be
+ * associated with a widget that is the target of the mnemonic. When the label
+ * is inside a widget (like a #GtkButton or a #GtkNotebook tab) it is automatically
+ * associated with the correct widget, but sometimes (i.e. when the target is
+ * a #GtkEntry next to the label) you need to set it explicitly using this
+ * function.
+ *
+ * The target widget will be accelerated by emitting "activate_mnemonic" on it.
+ * The default handler for this signal will activate the widget if there are no
+ * mnemonic collisions and toggle focus between the colliding widgets otherwise.
+ **/
+void
+gtk_label_set_mnemonic_widget (GtkLabel *label,
+ GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ label->mnemonic_widget = widget;
+}
+
+
+/**
+ * gtk_label_get_mnemonic_keyval:
+ * @label: a #GtkLabel
* @Returns: GDK keyval usable for accelerators, or GDK_VoidSymbol
*
- * If the label text was set using gtk_label_set_markup_with_accel,
- * gtk_label_parse_uline, or using the use_underline property this function
- * returns the keyval for the first underlined accelerator.
+ * If the label has been set so that it has an mnemonic key this function
+ * returns the keyval used for the mnemonic accelerator. If there is no
+ * mnemonic set up it returns #GDK_VoidSymbol.
**/
guint
-gtk_label_get_accel_keyval (GtkLabel *label)
+gtk_label_get_mnemonic_keyval (GtkLabel *label)
{
g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
- return label->accel_keyval;
+ return label->mnemonic_keyval;
}
static void
@@ -446,7 +579,7 @@ gtk_label_set_attributes_internal (GtkLa
}
-/* Calculates text, attrs and accel_keyval from
+/* Calculates text, attrs and mnemonic_keyval from
* label, use_underline and use_markup */
static void
gtk_label_recalculate (GtkLabel *label)
@@ -465,12 +598,25 @@ gtk_label_recalculate (GtkLabel *label)
}
if (!label->use_underline)
- label->accel_keyval = GDK_VoidSymbol;
+ {
+ guint keyval = label->mnemonic_keyval;
+ label->mnemonic_keyval = GDK_VoidSymbol;
+ gtk_label_setup_mnemonic (label, keyval);
+ }
gtk_label_clear_layout (label);
gtk_widget_queue_resize (GTK_WIDGET (label));
}
+/**
+ * gtk_label_set_text:
+ * label: a #GtkLabel
+ * str: a string
+ *
+ * Sets the text of the label to @str.
+ *
+ * This will also clear any previously set mnemonic accelerators.
+ **/
void
gtk_label_set_text (GtkLabel *label,
const gchar *str)
@@ -538,9 +684,9 @@ set_markup (GtkLabel *label,
}
if (accel_char != 0)
- label->accel_keyval = gdk_keyval_to_lower (gdk_unicode_to_keyval (accel_char));
+ label->mnemonic_keyval = gdk_keyval_to_lower (gdk_unicode_to_keyval (accel_char));
else
- label->accel_keyval = GDK_VoidSymbol;
+ label->mnemonic_keyval = GDK_VoidSymbol;
}
/**
@@ -565,31 +711,32 @@ gtk_label_set_markup (GtkLabel *label
}
/**
- * gtk_label_set_markup_with_accel:
+ * gtk_label_set_markup_with_mnemonic:
* @label: a #GtkLabel
* @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
*
* Parses @str which is marked up with the Pango text markup language,
* setting the label's text and attribute list based on the parse results.
* If characters in @str are preceded by an underscore, they are underlined
- * indicating that they represent a keyboard accelerator, and the GDK
- * keyval for the first underlined accelerator is returned. If there are
- * no underlines in the text, GDK_VoidSymbol will be returned.
+ * indicating that they represent a keyboard accelerator called a mnemonic.
*
- * Return value: GDK keyval for accelerator
+ * The mnemonic key can be used to activate another widget, chosen automatically,
+ * or explicitly using @gtk_label_set_mnemonic_widget.
**/
-guint
-gtk_label_set_markup_with_accel (GtkLabel *label,
- const gchar *str)
+void
+gtk_label_set_markup_with_mnemonic (GtkLabel *label,
+ const gchar *str)
{
- g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
+ guint last_keyval;
+ g_return_if_fail (GTK_IS_LABEL (label));
+ last_keyval = label->mnemonic_keyval;
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, TRUE);
gtk_label_set_use_underline_internal (label, TRUE);
gtk_label_recalculate (label);
- return label->accel_keyval;
+ gtk_label_setup_mnemonic (label, last_keyval);
}
/**
@@ -741,7 +888,7 @@ gtk_label_finalize (GObject *object)
pango_attr_list_unref (label->attrs);
g_free (label->select_info);
-
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -1207,22 +1354,64 @@ gtk_label_set_uline_text_internal (GtkLa
g_free (pattern);
- label->accel_keyval = accel_key;
+ label->mnemonic_keyval = accel_key;
}
guint
gtk_label_parse_uline (GtkLabel *label,
const gchar *str)
{
+ guint keyval;
+ guint orig_keyval;
+
g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
g_return_val_if_fail (str != NULL, GDK_VoidSymbol);
+ orig_keyval = label->mnemonic_keyval;
+
+ gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
+ gtk_label_set_use_markup_internal (label, FALSE);
+ gtk_label_set_use_underline_internal (label, TRUE);
+
+ gtk_label_recalculate (label);
+
+ keyval = label->mnemonic_keyval;
+ label->mnemonic_keyval = GDK_VoidSymbol;
+
+ gtk_label_setup_mnemonic (label, orig_keyval);
+
+ return keyval;
+}
+
+/**
+ * gtk_label_set_text_with_mnemonic:
+ * @label: a #GtkLabel
+ * @str: a string
+ *
+ * Sets the label's text from the string @str.
+ * If characters in @str are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * The mnemonic key can be used to activate another widget, chosen automatically,
+ * or explicitly using @gtk_label_set_mnemonic_widget.
+ **/
+void
+gtk_label_set_text_with_mnemonic (GtkLabel *label,
+ const gchar *str)
+{
+ guint last_keyval;
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (str != NULL);
+
+ last_keyval = label->mnemonic_keyval;
+
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, FALSE);
gtk_label_set_use_underline_internal (label, TRUE);
gtk_label_recalculate (label);
- return label->accel_keyval;
+
+ gtk_label_setup_mnemonic (label, last_keyval);
}
@@ -1659,8 +1848,6 @@ gtk_label_select_region (GtkLabel *labe
if (label->text && label->select_info)
{
- GtkClipboard *clipboard;
-
if (start_offset < 0)
start_offset = 0;
Index: gtkbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.c,v
retrieving revision 1.55
diff -u -p -r1.55 gtkbutton.c
--- gtkbutton.c 2001/03/16 20:12:39 1.55
+++ gtkbutton.c 2001/03/21 11:32:33
@@ -319,9 +319,17 @@ gtk_button_new_with_label (const gchar *
return button;
}
+/**
+ * gtk_button_new_from_stock:
+ * @stock_id: the name of the stock item
+ * @returns: a new #GtkButton
+ *
+ * Creates a new #GtkButton containing the image and text from a stock item.
+ * Some stock ids have preprocessor macros like #GTK_STOCK_BUTTON_OK and
+ * #GTK_STOCK_BUTTON_APPLY.
+ **/
GtkWidget*
-gtk_button_new_stock (const gchar *stock_id,
- GtkAccelGroup *accel_group)
+gtk_button_new_from_stock (const gchar *stock_id)
{
GtkWidget *button;
GtkStockItem item;
@@ -331,35 +339,13 @@ gtk_button_new_stock (const gchar *sto
GtkWidget *label;
GtkWidget *image;
GtkWidget *hbox;
- guint keyval;
button = gtk_button_new ();
- label = gtk_label_new (NULL);
- keyval = gtk_label_parse_uline (GTK_LABEL (label),
- item.label);
-
- if (keyval && accel_group)
- {
- gtk_widget_add_accelerator (button,
- "clicked",
- accel_group,
- keyval,
- GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
- }
-
- /* Also add the stock accelerator if one was specified. */
- if (item.keyval && accel_group)
- {
- gtk_widget_add_accelerator (button,
- "clicked",
- accel_group,
- item.keyval,
- item.modifier,
- GTK_ACCEL_LOCKED);
- }
+ label = gtk_label_new_with_mnemonic (item.label);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
+
image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
hbox = gtk_hbox_new (FALSE, 0);
@@ -371,37 +357,37 @@ gtk_button_new_stock (const gchar *sto
}
else
{
- button = gtk_button_new_accel (stock_id, accel_group);
+ button = gtk_button_new_with_mnemonic (stock_id);
}
return button;
}
+/**
+ * gtk_button_new_with_mnemonic:
+ * @label: The text of the button, with an underscore in front of the
+ * mnemonic character
+ * @returns: a new #GtkButton
+ *
+ * Creates a new #GtkButton containing a label.
+ * If characters in @label are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * Pressing Alt and that key activates the button.
+ **/
GtkWidget*
-gtk_button_new_accel (const gchar *uline_label,
- GtkAccelGroup *accel_group)
+gtk_button_new_with_mnemonic (const gchar *label)
{
GtkWidget *button;
- GtkWidget *label;
- guint keyval;
+ GtkWidget *label_widget;
button = gtk_button_new ();
- label = gtk_label_new (NULL);
- keyval = gtk_label_parse_uline (GTK_LABEL (label), uline_label);
+ label_widget = gtk_label_new_with_mnemonic (label);
- if (keyval && accel_group)
- {
- gtk_widget_add_accelerator (button,
- "clicked",
- accel_group,
- keyval,
- GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
- }
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label_widget), button);
- gtk_container_add (GTK_CONTAINER (button), label);
- gtk_widget_show (label);
+ gtk_container_add (GTK_CONTAINER (button), label_widget);
+ gtk_widget_show (label_widget);
return button;
}
Index: gtkbutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.h,v
retrieving revision 1.15
diff -u -p -r1.15 gtkbutton.h
--- gtkbutton.h 2001/03/06 15:51:09 1.15
+++ gtkbutton.h 2001/03/21 11:32:33
@@ -77,20 +77,18 @@ struct _GtkButtonClass
GtkType gtk_button_get_type (void) G_GNUC_CONST;
-GtkWidget* gtk_button_new (void);
-GtkWidget* gtk_button_new_with_label (const gchar *label);
-GtkWidget* gtk_button_new_stock (const gchar *stock_id,
- GtkAccelGroup *accel_group);
-GtkWidget* gtk_button_new_accel (const gchar *uline_label,
- GtkAccelGroup *accel_group);
-void gtk_button_pressed (GtkButton *button);
-void gtk_button_released (GtkButton *button);
-void gtk_button_clicked (GtkButton *button);
-void gtk_button_enter (GtkButton *button);
-void gtk_button_leave (GtkButton *button);
-void gtk_button_set_relief (GtkButton *button,
- GtkReliefStyle newstyle);
-GtkReliefStyle gtk_button_get_relief (GtkButton *button);
+GtkWidget* gtk_button_new (void);
+GtkWidget* gtk_button_new_with_label (const gchar *label);
+GtkWidget* gtk_button_new_from_stock (const gchar *stock_id);
+GtkWidget* gtk_button_new_with_mnemonic (const gchar *label);
+void gtk_button_pressed (GtkButton *button);
+void gtk_button_released (GtkButton *button);
+void gtk_button_clicked (GtkButton *button);
+void gtk_button_enter (GtkButton *button);
+void gtk_button_leave (GtkButton *button);
+void gtk_button_set_relief (GtkButton *button,
+ GtkReliefStyle newstyle);
+GtkReliefStyle gtk_button_get_relief (GtkButton *button);
#ifdef __cplusplus
Index: gtkcheckbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcheckbutton.c,v
retrieving revision 1.26
diff -u -p -r1.26 gtkcheckbutton.c
--- gtkcheckbutton.c 2001/03/09 13:28:23 1.26
+++ gtkcheckbutton.c 2001/03/21 11:32:33
@@ -123,6 +123,35 @@ gtk_check_button_new_with_label (const g
return check_button;
}
+/**
+ * gtk_check_button_new_with_mnemonic:
+ * @label: The text of the button, with an underscore in front of the
+ * mnemonic character
+ * @returns: a new #GtkCheckButton
+ *
+ * Creates a new #GtkCheckButton containing a label.
+ * If characters in @label are preceded by an underscore, they are underlined
+ * indicating that they represent a keyboard accelerator called a mnemonic.
+ * Pressing Alt and that key activates the checkbutton.
+ **/
+GtkWidget*
+gtk_check_button_new_with_mnemonic (const gchar *label)
+{
+ GtkWidget *check_button;
+ GtkWidget *label_widget;
+
+ check_button = gtk_check_button_new ();
+ label_widget = gtk_label_new_with_mnemonic (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label_widget), check_button);
+
+ gtk_container_add (GTK_CONTAINER (check_button), label_widget);
+ gtk_widget_show (label_widget);
+
+ return check_button;
+}
+
+
/* This should only be called when toggle_button->draw_indicator
* is true.
*/
Index: gtkcheckbutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcheckbutton.h,v
retrieving revision 1.7
diff -u -p -r1.7 gtkcheckbutton.h
--- gtkcheckbutton.h 2000/08/30 00:33:37 1.7
+++ gtkcheckbutton.h 2001/03/21 11:32:33
@@ -66,8 +66,9 @@ struct _GtkCheckButtonClass
GtkType gtk_check_button_get_type (void) G_GNUC_CONST;
-GtkWidget* gtk_check_button_new (void);
-GtkWidget* gtk_check_button_new_with_label (const gchar *label);
+GtkWidget* gtk_check_button_new (void);
+GtkWidget* gtk_check_button_new_with_label (const gchar *label);
+GtkWidget* gtk_check_button_new_with_mnemonic (const gchar *label);
#ifdef __cplusplus
Index: gtkdialog.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdialog.c,v
retrieving revision 1.21
diff -u -p -r1.21 gtkdialog.c
--- gtkdialog.c 2001/03/07 21:32:50 1.21
+++ gtkdialog.c 2001/03/21 11:32:33
@@ -471,8 +471,7 @@ gtk_dialog_add_button (GtkDialog *dial
g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
g_return_val_if_fail (button_text != NULL, NULL);
- button = gtk_button_new_stock (button_text,
- gtk_window_get_default_accel_group (GTK_WINDOW (dialog)));
+ button = gtk_button_new_from_stock (button_text);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
Index: gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.115
diff -u -p -r1.115 gtkentry.c
--- gtkentry.c 2001/03/16 01:44:54 1.115
+++ gtkentry.c 2001/03/21 11:32:33
@@ -250,6 +250,8 @@ static void gtk_entry_paste
static void gtk_entry_update_primary_selection (GtkEntry *entry);
static void gtk_entry_popup_menu (GtkEntry *entry,
GdkEventButton *event);
+static gboolean gtk_entry_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
static GtkWidgetClass *parent_class = NULL;
@@ -341,6 +343,7 @@ gtk_entry_class_init (GtkEntryClass *cla
widget_class->style_set = gtk_entry_style_set;
widget_class->direction_changed = gtk_entry_direction_changed;
widget_class->state_changed = gtk_entry_state_changed;
+ widget_class->activate_mnemonic = gtk_entry_activate_mnemonic;
widget_class->drag_motion = gtk_entry_drag_motion;
widget_class->drag_leave = gtk_entry_drag_leave;
@@ -3131,6 +3134,15 @@ activate_cb (GtkWidget *menuitem,
{
const gchar *signal = gtk_object_get_data (GTK_OBJECT (menuitem), "gtk-signal");
gtk_signal_emit_by_name (GTK_OBJECT (entry), signal);
+}
+
+
+static gboolean
+gtk_entry_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ gtk_widget_grab_focus (widget);
+ return TRUE;
}
static void
Index: gtkitemfactory.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkitemfactory.c,v
retrieving revision 1.34
diff -u -p -r1.34 gtkitemfactory.c
--- gtkitemfactory.c 2001/03/19 21:06:37 1.34
+++ gtkitemfactory.c 2001/03/21 11:32:33
@@ -1227,25 +1276,8 @@ gtk_item_factory_create_item (GtkItemFac
"GtkAccelLabel::accel_widget", widget,
"GtkMisc::xalign", 0.0,
NULL);
-
- accel_key = gtk_label_parse_uline (GTK_LABEL (label), name);
- if (accel_key != GDK_VoidSymbol)
- {
- if (GTK_IS_MENU_BAR (parent))
- gtk_widget_add_accelerator (widget,
- "activate_item",
- ifactory->accel_group,
- accel_key, GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
-
- if (GTK_IS_MENU (parent))
- gtk_widget_add_accelerator (widget,
- "activate_item",
- gtk_menu_ensure_uline_accel_group (GTK_MENU (parent)),
- accel_key, 0,
- GTK_ACCEL_LOCKED);
- }
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
}
g_free (name);
Index: gtkmarshal.list
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmarshal.list,v
retrieving revision 1.24
diff -u -p -r1.24 gtkmarshal.list
--- gtkmarshal.list 2001/03/09 14:49:00 1.24
+++ gtkmarshal.list 2001/03/21 11:32:34
@@ -25,6 +25,7 @@ BOOLEAN:BOXED
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
BOOLEAN:VOID
+BOOLEAN:BOOLEAN
ENUM:ENUM
INT:OBJECT,BOXED,BOXED
INT:POINTER
Index: gtkmenu.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.c,v
retrieving revision 1.59
diff -u -p -r1.59 gtkmenu.c
--- gtkmenu.c 2001/03/09 13:28:25 1.59
+++ gtkmenu.c 2001/03/21 11:32:34
@@ -116,7 +116,6 @@ static void gtk_menu_remove (Gtk
static GtkMenuShellClass *parent_class = NULL;
static const gchar *attach_data_key = "gtk-menu-attach-data";
-static GQuark quark_uline_accel_group = 0;
GtkType
gtk_menu_get_type (void)
@@ -248,6 +247,7 @@ gtk_menu_init (GtkMenu *menu)
NULL);
gtk_window_set_policy (GTK_WINDOW (menu->toplevel),
FALSE, FALSE, TRUE);
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (menu->toplevel), 0);
/* Refloat the menu, so that reference counting for the menu isn't
* affected by it being a child of the toplevel
@@ -739,38 +739,6 @@ gtk_menu_get_accel_group (GtkMenu *menu)
return menu->accel_group;
}
-GtkAccelGroup*
-gtk_menu_ensure_uline_accel_group (GtkMenu *menu)
-{
- GtkAccelGroup *accel_group;
-
- g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
-
- if (!quark_uline_accel_group)
- quark_uline_accel_group = g_quark_from_static_string ("GtkMenu-uline-accel-group");
-
- accel_group = gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_uline_accel_group);
- if (!accel_group)
- {
- accel_group = gtk_accel_group_new ();
- gtk_accel_group_attach (accel_group, GTK_OBJECT (menu));
- gtk_object_set_data_by_id_full (GTK_OBJECT (menu),
- quark_uline_accel_group,
- accel_group,
- (GtkDestroyNotify) gtk_accel_group_unref);
- }
-
- return accel_group;
-}
-
-GtkAccelGroup*
-gtk_menu_get_uline_accel_group (GtkMenu *menu)
-{
- g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
-
- return gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_uline_accel_group);
-}
-
void
gtk_menu_reposition (GtkMenu *menu)
{
@@ -844,6 +812,7 @@ gtk_menu_set_tearoff_state (GtkMenu *me
NULL);
gtk_window_set_type_hint (GTK_WINDOW (menu->tearoff_window),
GDK_WINDOW_TYPE_HINT_MENU);
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (menu->tearoff_window), 0);
gtk_widget_set_app_paintable (menu->tearoff_window, TRUE);
gtk_signal_connect (GTK_OBJECT (menu->tearoff_window),
"event",
@@ -1420,7 +1389,6 @@ gtk_menu_key_press (GtkWidget *widget,
(delete ||
(gtk_accelerator_valid (event->keyval, event->state) &&
(event->state ||
- !gtk_menu_get_uline_accel_group (GTK_MENU (menu_shell)) ||
(event->keyval >= GDK_F1 && event->keyval <= GDK_F35)))))
{
GtkMenuItem *menu_item;
Index: gtkmenu.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.h,v
retrieving revision 1.23
diff -u -p -r1.23 gtkmenu.h
--- gtkmenu.h 2000/11/08 17:34:52 1.23
+++ gtkmenu.h 2001/03/21 11:32:34
@@ -147,12 +147,6 @@ void gtk_menu_set_accel_group (
GtkAccelGroup *accel_group);
GtkAccelGroup* gtk_menu_get_accel_group (GtkMenu *menu);
-/* get the accelerator group that is used internally by the menu for
- * underline accelerators while the menu is popped up.
- */
-GtkAccelGroup* gtk_menu_get_uline_accel_group (GtkMenu *menu);
-GtkAccelGroup* gtk_menu_ensure_uline_accel_group (GtkMenu *menu);
-
/* A reference count is kept for a widget when it is attached to
* a particular widget. This is typically a menu item; it may also
Index: gtkmenuitem.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenuitem.c,v
retrieving revision 1.48
diff -u -p -r1.48 gtkmenuitem.c
--- gtkmenuitem.c 2001/03/16 20:12:39 1.48
+++ gtkmenuitem.c 2001/03/21 11:32:34
@@ -67,6 +67,8 @@ static void gtk_real_menu_item_toggle_si
gint *requisition);
static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
gint allocation);
+static gboolean gtk_menu_item_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling);
static gint gtk_menu_item_select_timeout (gpointer data);
static void gtk_menu_item_popup_submenu (gpointer data);
@@ -82,6 +84,7 @@ static void gtk_menu_item_forall
GtkCallback callback,
gpointer callback_data);
+
static GtkItemClass *parent_class;
static guint menu_item_signals[LAST_SIGNAL] = { 0 };
static guint32 last_submenu_deselect_time = 0;
@@ -137,6 +140,7 @@ gtk_menu_item_class_init (GtkMenuItemCla
widget_class->expose_event = gtk_menu_item_expose;
widget_class->show_all = gtk_menu_item_show_all;
widget_class->hide_all = gtk_menu_item_hide_all;
+ widget_class->activate_mnemonic = gtk_menu_item_activate_mnemonic;
container_class->forall = gtk_menu_item_forall;
@@ -600,6 +604,25 @@ gtk_real_menu_item_deselect (GtkItem *it
gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
}
+
+static gboolean
+gtk_menu_item_activate_mnemonic (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ if (group_cycling)
+ {
+ if (widget->parent &&
+ GTK_IS_MENU_SHELL (widget->parent))
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent),
+ widget);
+
+ }
+ else
+ gtk_signal_emit (GTK_OBJECT (widget), menu_item_signals[ACTIVATE_ITEM]);
+
+ return TRUE;
+}
+
static void
gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
Index: gtkmenushell.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenushell.c,v
retrieving revision 1.39
diff -u -p -r1.39 gtkmenushell.c
--- gtkmenushell.c 2001/03/06 15:51:10 1.39
+++ gtkmenushell.c 2001/03/21 11:32:35
@@ -31,8 +31,8 @@
#include "gtktearoffmenuitem.h" /* FIXME */
#include "gtkmenushell.h"
#include "gtksignal.h"
+#include "gtkwindow.h"
-
#define MENU_SHELL_TIMEOUT 500
@@ -551,6 +551,7 @@ gtk_menu_shell_key_press (GtkWidget *wid
GdkEventKey *event)
{
GtkMenuShell *menu_shell;
+ GtkWidget *toplevel;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
@@ -566,6 +567,13 @@ gtk_menu_shell_key_press (GtkWidget *wid
event->state))
return TRUE;
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (GTK_IS_WINDOW (toplevel) &&
+ gtk_window_activate_mnemonic (GTK_WINDOW (toplevel),
+ event->keyval,
+ event->state))
+ return TRUE;
+
if (gtk_accel_groups_activate (GTK_OBJECT (widget), event->keyval, event->state))
return TRUE;
Index: gtknotebook.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.c,v
retrieving revision 1.82
diff -u -p -r1.82 gtknotebook.c
--- gtknotebook.c 2001/03/09 13:28:25 1.82
+++ gtknotebook.c 2001/03/21 11:32:35
@@ -94,6 +94,8 @@ struct _GtkNotebookPage
GtkRequisition requisition;
GtkAllocation allocation;
+
+ guint activate_mnemonic_signal;
};
#ifdef G_DISABLE_CHECKS
@@ -1972,6 +1974,10 @@ gtk_notebook_real_remove (GtkNotebook *n
if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
need_resize = TRUE;
+ if (page->tab_label && page->activate_mnemonic_signal)
+ gtk_signal_disconnect (page->tab_label,
+ page->activate_mnemonic_signal);
+
gtk_widget_unparent (page->child);
if (page->tab_label)
@@ -3618,6 +3624,35 @@ gtk_notebook_insert_page (GtkNotebook *n
gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
}
+
+static gint
+gtk_notebook_page_compare_tab (gconstpointer a,
+ gconstpointer b)
+{
+ return (((GtkNotebookPage *) a)->tab_label != b);
+}
+
+static gboolean
+gtk_notebook_activate_mnemonic_switch_page (GtkWidget *child,
+ gboolean overload,
+ gpointer data)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (data);
+ GtkNotebookPage *page;
+ GList *list;
+
+ list = g_list_find_custom (notebook->children, child,
+ gtk_notebook_page_compare_tab);
+ if (!list)
+ return TRUE;
+
+
+ page = list->data;
+
+ gtk_notebook_switch_page (notebook, page, -1);
+ return TRUE;
+}
+
/**
* gtk_notebook_insert_page_menu:
* @notebook: a #GtkNotebook
@@ -3661,6 +3696,7 @@ gtk_notebook_insert_page_menu (GtkNotebo
page->allocation.height = 0;
page->default_menu = FALSE;
page->default_tab = FALSE;
+ page->activate_mnemonic_signal = 0;
nchildren = g_list_length (notebook->children);
if ((position < 0) || (position > nchildren))
@@ -3741,6 +3777,13 @@ gtk_notebook_insert_page_menu (GtkNotebo
gtk_widget_hide (tab_label);
}
}
+
+ if (tab_label)
+ page->activate_mnemonic_signal =
+ gtk_signal_connect (GTK_OBJECT (tab_label),
+ "activate_mnemonic",
+ (GtkSignalFunc) gtk_notebook_activate_mnemonic_switch_page,
+ notebook);
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]