forked from AuroraMiddleware/gtk
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
2004-12-10 Matthias Clasen <mclasen@redhat.com> Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor) * gtk/gtkwindow.c: Factor out mnemonic hash code into a separate file. * gtk/gtkmnemonichash.[hc]: Factored out mnemonic hash code from gtkwindow.c. * gtk/Makefile.am (gtk_c_sources): Add gtkmnemonichash.[hc]. * gtk/gtkmenushell.c (struct _GtkMenuShellPrivate): Give menu shells their own mnemonic hash. * gtk/gtkmenushell.h: Add private api to support mnemonics. * gtk/gtklabel.c (gtk_label_setup_mnemonic): Add mnemonic to the menushell mnemonic hash when inside a menu.
This commit is contained in:
parent
5c98a5ebee
commit
f3a74ace5f
20
ChangeLog
20
ChangeLog
@ -1,3 +1,23 @@
|
||||
2004-12-10 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
|
||||
|
||||
* gtk/gtkwindow.c: Factor out mnemonic hash code into
|
||||
a separate file.
|
||||
|
||||
* gtk/gtkmnemonichash.[hc]: Factored out mnemonic hash
|
||||
code from gtkwindow.c.
|
||||
|
||||
* gtk/Makefile.am (gtk_c_sources): Add gtkmnemonichash.[hc].
|
||||
|
||||
* gtk/gtkmenushell.c (struct _GtkMenuShellPrivate): Give
|
||||
menu shells their own mnemonic hash.
|
||||
|
||||
* gtk/gtkmenushell.h: Add private api to support mnemonics.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_setup_mnemonic): Add mnemonic to
|
||||
the menushell mnemonic hash when inside a menu.
|
||||
|
||||
Fri Dec 10 13:59:32 2004 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* gtk/gtk.symbols: add recent new functions.
|
||||
|
@ -1,3 +1,23 @@
|
||||
2004-12-10 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
|
||||
|
||||
* gtk/gtkwindow.c: Factor out mnemonic hash code into
|
||||
a separate file.
|
||||
|
||||
* gtk/gtkmnemonichash.[hc]: Factored out mnemonic hash
|
||||
code from gtkwindow.c.
|
||||
|
||||
* gtk/Makefile.am (gtk_c_sources): Add gtkmnemonichash.[hc].
|
||||
|
||||
* gtk/gtkmenushell.c (struct _GtkMenuShellPrivate): Give
|
||||
menu shells their own mnemonic hash.
|
||||
|
||||
* gtk/gtkmenushell.h: Add private api to support mnemonics.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_setup_mnemonic): Add mnemonic to
|
||||
the menushell mnemonic hash when inside a menu.
|
||||
|
||||
Fri Dec 10 13:59:32 2004 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* gtk/gtk.symbols: add recent new functions.
|
||||
|
@ -1,3 +1,23 @@
|
||||
2004-12-10 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
|
||||
|
||||
* gtk/gtkwindow.c: Factor out mnemonic hash code into
|
||||
a separate file.
|
||||
|
||||
* gtk/gtkmnemonichash.[hc]: Factored out mnemonic hash
|
||||
code from gtkwindow.c.
|
||||
|
||||
* gtk/Makefile.am (gtk_c_sources): Add gtkmnemonichash.[hc].
|
||||
|
||||
* gtk/gtkmenushell.c (struct _GtkMenuShellPrivate): Give
|
||||
menu shells their own mnemonic hash.
|
||||
|
||||
* gtk/gtkmenushell.h: Add private api to support mnemonics.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_setup_mnemonic): Add mnemonic to
|
||||
the menushell mnemonic hash when inside a menu.
|
||||
|
||||
Fri Dec 10 13:59:32 2004 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* gtk/gtk.symbols: add recent new functions.
|
||||
|
@ -1,3 +1,23 @@
|
||||
2004-12-10 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
|
||||
|
||||
* gtk/gtkwindow.c: Factor out mnemonic hash code into
|
||||
a separate file.
|
||||
|
||||
* gtk/gtkmnemonichash.[hc]: Factored out mnemonic hash
|
||||
code from gtkwindow.c.
|
||||
|
||||
* gtk/Makefile.am (gtk_c_sources): Add gtkmnemonichash.[hc].
|
||||
|
||||
* gtk/gtkmenushell.c (struct _GtkMenuShellPrivate): Give
|
||||
menu shells their own mnemonic hash.
|
||||
|
||||
* gtk/gtkmenushell.h: Add private api to support mnemonics.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_setup_mnemonic): Add mnemonic to
|
||||
the menushell mnemonic hash when inside a menu.
|
||||
|
||||
Fri Dec 10 13:59:32 2004 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* gtk/gtk.symbols: add recent new functions.
|
||||
|
@ -425,6 +425,8 @@ gtk_c_sources = \
|
||||
gtkmenutoolbutton.c \
|
||||
gtkmessagedialog.c \
|
||||
gtkmisc.c \
|
||||
gtkmnemonichash.c \
|
||||
gtkmnemonichash.h \
|
||||
gtkmodules.c \
|
||||
gtknotebook.c \
|
||||
gtkobject.c \
|
||||
|
@ -833,27 +833,59 @@ static void
|
||||
gtk_label_setup_mnemonic (GtkLabel *label,
|
||||
guint last_key)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (label);
|
||||
GtkWidget *toplevel;
|
||||
|
||||
if (last_key != GDK_VoidSymbol && label->mnemonic_window)
|
||||
GtkWidget *mnemonic_menu;
|
||||
|
||||
mnemonic_menu = g_object_get_data (G_OBJECT (label), "gtk-mnemonic-menu");
|
||||
|
||||
if (last_key != GDK_VoidSymbol)
|
||||
{
|
||||
gtk_window_remove_mnemonic (label->mnemonic_window,
|
||||
last_key,
|
||||
GTK_WIDGET (label));
|
||||
label->mnemonic_window = NULL;
|
||||
if (label->mnemonic_window)
|
||||
{
|
||||
gtk_window_remove_mnemonic (label->mnemonic_window,
|
||||
last_key,
|
||||
widget);
|
||||
label->mnemonic_window = NULL;
|
||||
}
|
||||
if (mnemonic_menu)
|
||||
{
|
||||
_gtk_menu_shell_remove_mnemonic (GTK_MENU_SHELL (mnemonic_menu),
|
||||
last_key,
|
||||
widget);
|
||||
label->mnemonic_window = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (label->mnemonic_keyval == GDK_VoidSymbol)
|
||||
return;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
if (GTK_WIDGET_TOPLEVEL (toplevel))
|
||||
{
|
||||
gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
|
||||
label->mnemonic_keyval,
|
||||
GTK_WIDGET (label));
|
||||
label->mnemonic_window = GTK_WINDOW (toplevel);
|
||||
GtkWidget *menu_shell;
|
||||
|
||||
menu_shell = gtk_widget_get_ancestor (widget,
|
||||
GTK_TYPE_MENU_SHELL);
|
||||
|
||||
if (menu_shell)
|
||||
{
|
||||
_gtk_menu_shell_add_mnemonic (GTK_MENU_SHELL (menu_shell),
|
||||
label->mnemonic_keyval,
|
||||
widget);
|
||||
mnemonic_menu = menu_shell;
|
||||
}
|
||||
|
||||
if (!(menu_shell && GTK_IS_MENU (menu_shell)))
|
||||
{
|
||||
gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
|
||||
label->mnemonic_keyval,
|
||||
widget);
|
||||
label->mnemonic_window = GTK_WINDOW (toplevel);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_set_data (G_OBJECT (label), "gtk-mnemonic-menu", mnemonic_menu);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -30,11 +30,13 @@
|
||||
#include "gdk/gdkkeysyms.h"
|
||||
#include "gtkalias.h"
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkkeyhash.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkmenubar.h"
|
||||
#include "gtkmenuitem.h"
|
||||
#include "gtkmenushell.h"
|
||||
#include "gtkmnemonichash.h"
|
||||
#include "gtktearoffmenuitem.h"
|
||||
#include "gtkwindow.h"
|
||||
|
||||
@ -112,9 +114,20 @@ typedef void (*GtkMenuShellSignal2) (GtkObject *object,
|
||||
* Cancels the current selection
|
||||
*/
|
||||
|
||||
#define GTK_MENU_SHELL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_MENU_SHELL, GtkMenuShellPrivate))
|
||||
|
||||
typedef struct _GtkMenuShellPrivate GtkMenuShellPrivate;
|
||||
|
||||
struct _GtkMenuShellPrivate
|
||||
{
|
||||
GtkMnemonicHash *mnemonic_hash;
|
||||
GtkKeyHash *key_hash;
|
||||
};
|
||||
|
||||
static void gtk_menu_shell_class_init (GtkMenuShellClass *klass);
|
||||
static void gtk_menu_shell_init (GtkMenuShell *menu_shell);
|
||||
static void gtk_menu_shell_realize (GtkWidget *widget);
|
||||
static void gtk_menu_shell_finalize (GObject *object);
|
||||
static gint gtk_menu_shell_button_press (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static gint gtk_menu_shell_button_release (GtkWidget *widget,
|
||||
@ -125,6 +138,8 @@ static gint gtk_menu_shell_enter_notify (GtkWidget *widget,
|
||||
GdkEventCrossing *event);
|
||||
static gint gtk_menu_shell_leave_notify (GtkWidget *widget,
|
||||
GdkEventCrossing *event);
|
||||
static void gtk_menu_shell_screen_changed (GtkWidget *widget,
|
||||
GdkScreen *previous_screen);
|
||||
static void gtk_menu_shell_add (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_menu_shell_remove (GtkContainer *container,
|
||||
@ -154,6 +169,10 @@ static void gtk_real_menu_shell_cancel (GtkMenuShell *menu_shell)
|
||||
static void gtk_real_menu_shell_cycle_focus (GtkMenuShell *menu_shell,
|
||||
GtkDirectionType dir);
|
||||
|
||||
static void gtk_menu_shell_reset_key_hash (GtkMenuShell *menu_shell);
|
||||
static gboolean gtk_menu_shell_activate_mnemonic (GtkMenuShell *menu_shell,
|
||||
GdkEventKey *event);
|
||||
|
||||
static GtkContainerClass *parent_class = NULL;
|
||||
static guint menu_shell_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
@ -202,12 +221,15 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass)
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
object_class->finalize = gtk_menu_shell_finalize;
|
||||
|
||||
widget_class->realize = gtk_menu_shell_realize;
|
||||
widget_class->button_press_event = gtk_menu_shell_button_press;
|
||||
widget_class->button_release_event = gtk_menu_shell_button_release;
|
||||
widget_class->key_press_event = gtk_menu_shell_key_press;
|
||||
widget_class->enter_notify_event = gtk_menu_shell_enter_notify;
|
||||
widget_class->leave_notify_event = gtk_menu_shell_leave_notify;
|
||||
widget_class->screen_changed = gtk_menu_shell_screen_changed;
|
||||
|
||||
container_class->add = gtk_menu_shell_add;
|
||||
container_class->remove = gtk_menu_shell_remove;
|
||||
@ -308,6 +330,8 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass)
|
||||
GDK_F10, GDK_SHIFT_MASK,
|
||||
"cycle_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GtkMenuShellPrivate));
|
||||
}
|
||||
|
||||
static GType
|
||||
@ -319,6 +343,8 @@ gtk_menu_shell_child_type (GtkContainer *container)
|
||||
static void
|
||||
gtk_menu_shell_init (GtkMenuShell *menu_shell)
|
||||
{
|
||||
GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
|
||||
|
||||
menu_shell->children = NULL;
|
||||
menu_shell->active_menu_item = NULL;
|
||||
menu_shell->parent_menu_shell = NULL;
|
||||
@ -327,8 +353,26 @@ gtk_menu_shell_init (GtkMenuShell *menu_shell)
|
||||
menu_shell->have_xgrab = FALSE;
|
||||
menu_shell->button = 0;
|
||||
menu_shell->activate_time = 0;
|
||||
|
||||
priv->mnemonic_hash = NULL;
|
||||
priv->key_hash = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_shell_finalize (GObject *object)
|
||||
{
|
||||
GtkMenuShell *menu_shell = GTK_MENU_SHELL (object);
|
||||
GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
|
||||
|
||||
if (priv->mnemonic_hash)
|
||||
_gtk_mnemonic_hash_free (priv->mnemonic_hash);
|
||||
if (priv->key_hash)
|
||||
_gtk_key_hash_free (priv->key_hash);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gtk_menu_shell_append (GtkMenuShell *menu_shell,
|
||||
GtkWidget *child)
|
||||
@ -563,11 +607,10 @@ gtk_menu_shell_button_release (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_menu_shell_key_press (GtkWidget *widget,
|
||||
gtk_menu_shell_key_press (GtkWidget *widget,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
GtkMenuShell *menu_shell;
|
||||
GtkWidget *toplevel;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
@ -580,12 +623,7 @@ gtk_menu_shell_key_press (GtkWidget *widget,
|
||||
if (gtk_bindings_activate_event (GTK_OBJECT (widget), event))
|
||||
return TRUE;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
if (GTK_IS_WINDOW (toplevel) &&
|
||||
gtk_window_activate_key (GTK_WINDOW (toplevel), event))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
return gtk_menu_shell_activate_mnemonic (menu_shell, event);
|
||||
}
|
||||
|
||||
static gint
|
||||
@ -673,6 +711,13 @@ gtk_menu_shell_leave_notify (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_shell_screen_changed (GtkWidget *widget,
|
||||
GdkScreen *previous_screen)
|
||||
{
|
||||
gtk_menu_shell_reset_key_hash (GTK_MENU_SHELL (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_shell_add (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
@ -1218,3 +1263,120 @@ gtk_menu_shell_cancel (GtkMenuShell *menu_shell)
|
||||
|
||||
g_signal_emit (menu_shell, menu_shell_signals[CANCEL], 0);
|
||||
}
|
||||
|
||||
static GtkMnemonicHash *
|
||||
gtk_menu_shell_get_mnemonic_hash (GtkMenuShell *menu_shell,
|
||||
gboolean create)
|
||||
{
|
||||
GtkMenuShellPrivate *private = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
|
||||
|
||||
if (!private->mnemonic_hash && create)
|
||||
private->mnemonic_hash = _gtk_mnemonic_hash_new ();
|
||||
|
||||
return private->mnemonic_hash;
|
||||
}
|
||||
|
||||
static void
|
||||
menu_shell_add_mnemonic_foreach (guint keyval,
|
||||
GSList *targets,
|
||||
gpointer data)
|
||||
{
|
||||
GtkKeyHash *key_hash = data;
|
||||
|
||||
_gtk_key_hash_add_entry (key_hash, keyval, 0, GUINT_TO_POINTER (keyval));
|
||||
}
|
||||
|
||||
static GtkKeyHash *
|
||||
gtk_menu_shell_get_key_hash (GtkMenuShell *menu_shell,
|
||||
gboolean create)
|
||||
{
|
||||
GtkMenuShellPrivate *private = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
|
||||
GtkWidget *widget = GTK_WIDGET (menu_shell);
|
||||
|
||||
if (!private->key_hash && create && gtk_widget_has_screen (widget))
|
||||
{
|
||||
GtkMnemonicHash *mnemonic_hash = gtk_menu_shell_get_mnemonic_hash (menu_shell, FALSE);
|
||||
GdkScreen *screen = gtk_widget_get_screen (widget);
|
||||
GdkKeymap *keymap = gdk_keymap_get_for_display (gdk_screen_get_display (screen));
|
||||
|
||||
if (!mnemonic_hash)
|
||||
return NULL;
|
||||
|
||||
private->key_hash = _gtk_key_hash_new (keymap, NULL);
|
||||
|
||||
_gtk_mnemonic_hash_foreach (mnemonic_hash,
|
||||
menu_shell_add_mnemonic_foreach,
|
||||
private->key_hash);
|
||||
}
|
||||
|
||||
return private->key_hash;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_shell_reset_key_hash (GtkMenuShell *menu_shell)
|
||||
{
|
||||
GtkMenuShellPrivate *private = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
|
||||
|
||||
if (private->key_hash)
|
||||
{
|
||||
_gtk_key_hash_free (private->key_hash);
|
||||
private->key_hash = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_menu_shell_activate_mnemonic (GtkMenuShell *menu_shell,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
GtkMnemonicHash *mnemonic_hash;
|
||||
GtkKeyHash *key_hash;
|
||||
GSList *entries;
|
||||
gboolean result = FALSE;
|
||||
|
||||
mnemonic_hash = gtk_menu_shell_get_mnemonic_hash (menu_shell, FALSE);
|
||||
if (!mnemonic_hash)
|
||||
return FALSE;
|
||||
|
||||
key_hash = gtk_menu_shell_get_key_hash (menu_shell, TRUE);
|
||||
if (!key_hash)
|
||||
return FALSE;
|
||||
|
||||
entries = _gtk_key_hash_lookup (key_hash,
|
||||
event->hardware_keycode,
|
||||
event->state,
|
||||
gtk_accelerator_get_default_mod_mask (),
|
||||
event->group);
|
||||
|
||||
if (entries)
|
||||
result = _gtk_mnemonic_hash_activate (mnemonic_hash,
|
||||
GPOINTER_TO_UINT (entries->data));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_menu_shell_add_mnemonic (GtkMenuShell *menu_shell,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
|
||||
g_return_if_fail (GTK_IS_WIDGET (target));
|
||||
|
||||
_gtk_mnemonic_hash_add (gtk_menu_shell_get_mnemonic_hash (menu_shell, TRUE),
|
||||
keyval, target);
|
||||
gtk_menu_shell_reset_key_hash (menu_shell);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_menu_shell_remove_mnemonic (GtkMenuShell *menu_shell,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
|
||||
g_return_if_fail (GTK_IS_WIDGET (target));
|
||||
|
||||
_gtk_mnemonic_hash_remove (gtk_menu_shell_get_mnemonic_hash (menu_shell, TRUE),
|
||||
keyval, target);
|
||||
gtk_menu_shell_reset_key_hash (menu_shell);
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,13 @@ void _gtk_menu_shell_activate (GtkMenuShell *menu_shell);
|
||||
gint _gtk_menu_shell_get_popup_delay (GtkMenuShell *menu_shell);
|
||||
void gtk_menu_shell_cancel (GtkMenuShell *menu_shell);
|
||||
|
||||
void _gtk_menu_shell_add_mnemonic (GtkMenuShell *menu_shell,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
void _gtk_menu_shell_remove_mnemonic (GtkMenuShell *menu_shell,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
197
gtk/gtkmnemonichash.c
Normal file
197
gtk/gtkmnemonichash.c
Normal file
@ -0,0 +1,197 @@
|
||||
/* gtkmnemonichash.c: Sets of mnemonics with cycling
|
||||
*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2002, Red Hat Inc.
|
||||
*
|
||||
* 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 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gtkmnemonichash.h"
|
||||
|
||||
struct _GtkMnemnonicHash
|
||||
{
|
||||
GHashTable *hash;
|
||||
};
|
||||
|
||||
|
||||
GtkMnemonicHash *
|
||||
_gtk_mnemonic_hash_new (void)
|
||||
{
|
||||
GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1);
|
||||
|
||||
mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL);
|
||||
|
||||
return mnemonic_hash;
|
||||
}
|
||||
|
||||
static void
|
||||
mnemonic_hash_free_foreach (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user)
|
||||
{
|
||||
guint keyval = GPOINTER_TO_UINT (key);
|
||||
GSList *targets = value;
|
||||
|
||||
gchar *name = gtk_accelerator_name (keyval, 0);
|
||||
|
||||
g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
|
||||
name, targets->data);
|
||||
g_free (name);
|
||||
|
||||
g_slist_free (targets);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash)
|
||||
{
|
||||
g_hash_table_foreach (mnemonic_hash->hash,
|
||||
mnemonic_hash_free_foreach,
|
||||
NULL);
|
||||
|
||||
g_hash_table_destroy (mnemonic_hash->hash);
|
||||
g_free (mnemonic_hash);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
gpointer key = GUINT_TO_POINTER (keyval);
|
||||
GSList *targets, *new_targets;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (target));
|
||||
|
||||
targets = g_hash_table_lookup (mnemonic_hash->hash, key);
|
||||
g_return_if_fail (g_slist_find (targets, target) == NULL);
|
||||
|
||||
new_targets = g_slist_append (targets, target);
|
||||
if (new_targets != targets)
|
||||
g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
gpointer key = GUINT_TO_POINTER (keyval);
|
||||
GSList *targets, *new_targets;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (target));
|
||||
|
||||
targets = g_hash_table_lookup (mnemonic_hash->hash, key);
|
||||
|
||||
g_return_if_fail (targets && g_slist_find (targets, target) != NULL);
|
||||
|
||||
new_targets = g_slist_remove (targets, target);
|
||||
if (new_targets != targets)
|
||||
{
|
||||
if (new_targets == NULL)
|
||||
g_hash_table_remove (mnemonic_hash->hash, key);
|
||||
else
|
||||
g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval)
|
||||
{
|
||||
GSList *list, *targets;
|
||||
GtkWidget *widget, *chosen_widget;
|
||||
gboolean overloaded;
|
||||
|
||||
targets = g_hash_table_lookup (mnemonic_hash->hash,
|
||||
GUINT_TO_POINTER (keyval));
|
||||
if (!targets)
|
||||
return FALSE;
|
||||
|
||||
overloaded = FALSE;
|
||||
chosen_widget = NULL;
|
||||
for (list = targets; list; list = list->next)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (chosen_widget)
|
||||
{
|
||||
/* For round robin we put the activated entry on
|
||||
* the end of the list after activation
|
||||
*/
|
||||
targets = g_slist_remove (targets, chosen_widget);
|
||||
targets = g_slist_append (targets, chosen_widget);
|
||||
g_hash_table_insert (mnemonic_hash->hash,
|
||||
GUINT_TO_POINTER (keyval),
|
||||
targets);
|
||||
|
||||
return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GSList *
|
||||
_gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval)
|
||||
{
|
||||
return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval));
|
||||
}
|
||||
|
||||
static void
|
||||
mnemonic_hash_foreach_func (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct {
|
||||
GtkMnemonicHashForeach func;
|
||||
gpointer func_data;
|
||||
} *info = data;
|
||||
|
||||
guint keyval = GPOINTER_TO_UINT (key);
|
||||
GSList *targets = value;
|
||||
|
||||
(*info->func) (keyval, targets, info->func_data);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_mnemonic_hash_foreach (GtkMnemonicHash *mnemonic_hash,
|
||||
GtkMnemonicHashForeach func,
|
||||
gpointer func_data)
|
||||
{
|
||||
struct {
|
||||
GtkMnemonicHashForeach func;
|
||||
gpointer func_data;
|
||||
} info;
|
||||
|
||||
info.func = func;
|
||||
info.func_data = func_data;
|
||||
|
||||
g_hash_table_foreach (mnemonic_hash->hash,
|
||||
mnemonic_hash_foreach_func,
|
||||
&info);
|
||||
}
|
54
gtk/gtkmnemonichash.h
Normal file
54
gtk/gtkmnemonichash.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* gtkmnemonichash.h: Sets of mnemonics with cycling
|
||||
*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2002, Red Hat Inc.
|
||||
*
|
||||
* 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 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_MNEMONIC_HASH_H__
|
||||
#define __GTK_MNEMONIC_HASH_H__
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkMnemnonicHash GtkMnemonicHash;
|
||||
|
||||
typedef void (*GtkMnemonicHashForeach) (guint keyval,
|
||||
GSList *targets,
|
||||
gpointer data);
|
||||
|
||||
GtkMnemonicHash *_gtk_mnemonic_hash_new (void);
|
||||
void _gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash);
|
||||
void _gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
void _gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval,
|
||||
GtkWidget *target);
|
||||
gboolean _gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval);
|
||||
GSList * _gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
|
||||
guint keyval);
|
||||
void _gtk_mnemonic_hash_foreach (GtkMnemonicHash *mnemonic_hash,
|
||||
GtkMnemonicHashForeach func,
|
||||
gpointer func_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_MNEMONIC_HASH_H__ */
|
206
gtk/gtkwindow.c
206
gtk/gtkwindow.c
@ -38,6 +38,7 @@
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkkeyhash.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkmnemonichash.h"
|
||||
#include "gtkiconfactory.h"
|
||||
#include "gtkicontheme.h"
|
||||
#include "gtkintl.h"
|
||||
@ -147,21 +148,14 @@ struct _GtkWindowGeometryInfo
|
||||
GtkWindowLastGeometryInfo last;
|
||||
};
|
||||
|
||||
typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
|
||||
|
||||
struct _GtkWindowMnemonic {
|
||||
GtkWindow *window;
|
||||
guint keyval;
|
||||
|
||||
GSList *targets;
|
||||
};
|
||||
|
||||
#define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
|
||||
|
||||
typedef struct _GtkWindowPrivate GtkWindowPrivate;
|
||||
|
||||
struct _GtkWindowPrivate
|
||||
{
|
||||
GtkMnemonicHash *mnemonic_hash;
|
||||
|
||||
guint above_initially : 1;
|
||||
guint below_initially : 1;
|
||||
guint fullscreen_initially : 1;
|
||||
@ -278,7 +272,6 @@ static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
|
||||
static void gtk_window_free_key_hash (GtkWindow *window);
|
||||
|
||||
static GSList *toplevel_list = NULL;
|
||||
static GHashTable *mnemonic_hash_table = NULL;
|
||||
static GtkBinClass *parent_class = NULL;
|
||||
static guint window_signals[LAST_SIGNAL] = { 0 };
|
||||
static GList *default_icon_list = NULL;
|
||||
@ -297,35 +290,6 @@ static void gtk_window_get_property (GObject *object,
|
||||
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);
|
||||
}
|
||||
|
||||
GType
|
||||
gtk_window_get_type (void)
|
||||
{
|
||||
@ -403,8 +367,6 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
|
||||
|
||||
gobject_class->dispose = gtk_window_dispose;
|
||||
gobject_class->finalize = gtk_window_finalize;
|
||||
|
||||
@ -1404,6 +1366,17 @@ gtk_window_remove_accel_group (GtkWindow *window,
|
||||
_gtk_accel_group_detach (accel_group, G_OBJECT (window));
|
||||
}
|
||||
|
||||
static GtkMnemonicHash *
|
||||
gtk_window_get_mnemonic_hash (GtkWindow *window,
|
||||
gboolean create)
|
||||
{
|
||||
GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
|
||||
if (!private->mnemonic_hash && create)
|
||||
private->mnemonic_hash = _gtk_mnemonic_hash_new ();
|
||||
|
||||
return private->mnemonic_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_add_mnemonic:
|
||||
* @window: a #GtkWindow
|
||||
@ -1417,28 +1390,11 @@ gtk_window_add_mnemonic (GtkWindow *window,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
GtkWindowMnemonic key;
|
||||
GtkWindowMnemonic *mnemonic;
|
||||
|
||||
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)
|
||||
{
|
||||
g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
|
||||
mnemonic->targets = g_slist_append (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);
|
||||
}
|
||||
_gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
|
||||
keyval, target);
|
||||
gtk_window_notify_keys_changed (window);
|
||||
}
|
||||
|
||||
@ -1455,24 +1411,11 @@ gtk_window_remove_mnemonic (GtkWindow *window,
|
||||
guint keyval,
|
||||
GtkWidget *target)
|
||||
{
|
||||
GtkWindowMnemonic key;
|
||||
GtkWindowMnemonic *mnemonic;
|
||||
|
||||
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_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
|
||||
|
||||
mnemonic->targets = g_slist_remove (mnemonic->targets, target);
|
||||
if (mnemonic->targets == NULL)
|
||||
{
|
||||
g_hash_table_remove (mnemonic_hash_table, mnemonic);
|
||||
g_free (mnemonic);
|
||||
}
|
||||
_gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
|
||||
keyval, target);
|
||||
gtk_window_notify_keys_changed (window);
|
||||
}
|
||||
|
||||
@ -1490,56 +1433,15 @@ gtk_window_mnemonic_activate (GtkWindow *window,
|
||||
guint keyval,
|
||||
GdkModifierType modifier)
|
||||
{
|
||||
GtkWindowMnemonic key;
|
||||
GtkWindowMnemonic *mnemonic;
|
||||
GSList *list;
|
||||
GtkWidget *widget, *chosen_widget;
|
||||
gboolean overloaded;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
|
||||
return FALSE;
|
||||
|
||||
key.window = window;
|
||||
key.keyval = keyval;
|
||||
mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
|
||||
if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
|
||||
{
|
||||
GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
|
||||
if (mnemonic_hash)
|
||||
return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
|
||||
}
|
||||
|
||||
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_DRAWABLE (widget) &&
|
||||
gdk_window_is_viewable (widget->window))
|
||||
{
|
||||
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_mnemonic_activate (chosen_widget, overloaded);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -3847,45 +3749,21 @@ 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)
|
||||
{
|
||||
if (mnemonic->targets)
|
||||
{
|
||||
gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
|
||||
|
||||
g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
|
||||
name, mnemonic->targets->data);
|
||||
g_free (name);
|
||||
}
|
||||
g_slist_free (mnemonic->targets);
|
||||
g_free (mnemonic);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_finalize (GObject *object)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (object);
|
||||
GtkMnemonicHash *mnemonic_hash;
|
||||
|
||||
g_free (window->title);
|
||||
g_free (window->wmclass_name);
|
||||
g_free (window->wmclass_class);
|
||||
g_free (window->wm_role);
|
||||
|
||||
g_hash_table_foreach_remove (mnemonic_hash_table,
|
||||
gtk_window_mnemonic_hash_remove,
|
||||
window);
|
||||
mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
|
||||
if (mnemonic_hash)
|
||||
_gtk_mnemonic_hash_free (mnemonic_hash);
|
||||
|
||||
if (window->geometry_info)
|
||||
{
|
||||
if (window->geometry_info->widget)
|
||||
@ -4500,11 +4378,8 @@ _gtk_window_query_nonaccels (GtkWindow *window,
|
||||
/* mnemonics are considered locked accels */
|
||||
if (accel_mods == window->mnemonic_modifier)
|
||||
{
|
||||
GtkWindowMnemonic mkey;
|
||||
|
||||
mkey.window = window;
|
||||
mkey.keyval = accel_key;
|
||||
if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
|
||||
GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
|
||||
if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -7288,9 +7163,9 @@ gtk_window_parse_geometry (GtkWindow *window,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_mnemonic_hash_foreach (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
gtk_window_mnemonic_hash_foreach (guint keyval,
|
||||
GSList *targets,
|
||||
gpointer data)
|
||||
{
|
||||
struct {
|
||||
GtkWindow *window;
|
||||
@ -7298,10 +7173,7 @@ gtk_window_mnemonic_hash_foreach (gpointer key,
|
||||
gpointer func_data;
|
||||
} *info = data;
|
||||
|
||||
GtkWindowMnemonic *mnemonic = value;
|
||||
|
||||
if (mnemonic->window == info->window)
|
||||
(*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
|
||||
(*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
|
||||
}
|
||||
|
||||
void
|
||||
@ -7310,6 +7182,7 @@ _gtk_window_keys_foreach (GtkWindow *window,
|
||||
gpointer func_data)
|
||||
{
|
||||
GSList *groups;
|
||||
GtkMnemonicHash *mnemonic_hash;
|
||||
|
||||
struct {
|
||||
GtkWindow *window;
|
||||
@ -7321,9 +7194,10 @@ _gtk_window_keys_foreach (GtkWindow *window,
|
||||
info.func = func;
|
||||
info.func_data = func_data;
|
||||
|
||||
g_hash_table_foreach (mnemonic_hash_table,
|
||||
gtk_window_mnemonic_hash_foreach,
|
||||
&info);
|
||||
mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
|
||||
if (mnemonic_hash)
|
||||
_gtk_mnemonic_hash_foreach (mnemonic_hash,
|
||||
gtk_window_mnemonic_hash_foreach, &info);
|
||||
|
||||
groups = gtk_accel_groups_from_object (G_OBJECT (window));
|
||||
while (groups)
|
||||
|
Loading…
Reference in New Issue
Block a user