include gdkkeysysms.h if compiling gdk_keyval_convert_case.

Thu Feb 28 19:55:01 2002  Owen Taylor  <otaylor@redhat.com>

        * gdk/gdkkeys.c: include gdkkeysysms.h if
        compiling gdk_keyval_convert_case.

        * gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
        <Control>Tab <Control><Shift>Tab to cycle between
        all menu bars in a toplevel once one is up.

        * tests/testgtk.c: Add a second menubar, this
        example is already full of crack anyways.

        * gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
        unhandled events up to the parent menu shell.

        * gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
        pop up the menu if the parent menu shell is still active.

        * gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
        old_focus argument, export privately.
This commit is contained in:
Owen Taylor 2002-03-01 01:05:11 +00:00 committed by Owen Taylor
parent 8b26dc2cf1
commit fce84d0535
15 changed files with 362 additions and 55 deletions

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -1,3 +1,24 @@
Thu Feb 28 19:55:01 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.c: include gdkkeysysms.h if
compiling gdk_keyval_convert_case.
* gtk/gtkmenubar.c (gtk_menu_bar_cycle_focus): Implement
<Control>Tab <Control><Shift>Tab to cycle between
all menu bars in a toplevel once one is up.
* tests/testgtk.c: Add a second menubar, this
example is already full of crack anyways.
* gtk/gtkmenushell.c (gtk_menu_shell_key_press): Padd
unhandled events up to the parent menu shell.
* gtk/gtkmenuitem.c (gtk_menu_item_select_timeout): Only
pop up the menu if the parent menu shell is still active.
* gtk/gtkcontainer.[ch] (_gtk_container_focus_sort): Add a
old_focus argument, export privately.
2002-02-28 Darin Adler <darin@bentspoon.com>
* gtk/gtkfilesel.c: (open_new_dir): Add missing NULL check.

View File

@ -95,6 +95,8 @@ gdk_keymap_class_init (GdkKeymapClass *klass)
*/
#ifndef HAVE_XCONVERTCASE
#include "gdkkeysyms.h"
/* compatibility function from X11R6.3, since XConvertCase is not
* supplied by X11R5.
*/

View File

@ -81,9 +81,6 @@ static gboolean gtk_container_focus (GtkWidget *widget,
GtkDirectionType direction);
static void gtk_container_real_set_focus_child (GtkContainer *container,
GtkWidget *widget);
static GList * gtk_container_focus_sort (GtkContainer *container,
GList *children,
GtkDirectionType direction);
static gboolean gtk_container_focus_move (GtkContainer *container,
GList *children,
@ -1434,7 +1431,7 @@ gtk_container_focus (GtkWidget *widget,
sorted_children = g_list_reverse (sorted_children);
}
else
sorted_children = gtk_container_focus_sort (container, children, direction);
sorted_children = _gtk_container_focus_sort (container, children, direction, NULL);
return_val = gtk_container_focus_move (container, sorted_children, direction);
@ -1469,7 +1466,8 @@ tab_compare (gconstpointer a,
static GList *
gtk_container_focus_sort_tab (GtkContainer *container,
GList *children,
GtkDirectionType direction)
GtkDirectionType direction,
GtkWidget *old_focus)
{
children = g_list_sort (children, tab_compare);
@ -1588,16 +1586,18 @@ up_down_compare (gconstpointer a,
static GList *
gtk_container_focus_sort_up_down (GtkContainer *container,
GList *children,
GtkDirectionType direction)
GtkDirectionType direction,
GtkWidget *old_focus)
{
CompareInfo compare;
GList *tmp_list;
GtkWidget *old_focus;
compare.container = container;
compare.reverse = (direction == GTK_DIR_UP);
old_focus = find_old_focus (container, children);
if (!old_focus)
old_focus = find_old_focus (container, children);
if (old_focus)
{
GdkRectangle old_allocation;
@ -1712,16 +1712,18 @@ left_right_compare (gconstpointer a,
static GList *
gtk_container_focus_sort_left_right (GtkContainer *container,
GList *children,
GtkDirectionType direction)
GtkDirectionType direction,
GtkWidget *old_focus)
{
CompareInfo compare;
GList *tmp_list;
GtkWidget *old_focus;
compare.container = container;
compare.reverse = (direction == GTK_DIR_LEFT);
if (!old_focus)
old_focus = find_old_focus (container, children);
old_focus = find_old_focus (container, children);
if (old_focus)
{
GdkRectangle old_allocation;
@ -1810,6 +1812,11 @@ gtk_container_focus_sort_left_right (GtkContainer *container,
* @children: a list of descendents of @container (they don't
* have to be direct children.
* @direction: focus direction
* @old_focus: widget to use for the starting position, or %NULL
* to determine this automatically.
* [ Note, this argument isn't used for GTK_DIR_TAB_*,
* which is the only @direction we use currently,
* so perhaps this argument should be removed ]
*
* Sorts @children in the correct order for focusing with
* direction type @direction.
@ -1818,10 +1825,11 @@ gtk_container_focus_sort_left_right (GtkContainer *container,
* with children that aren't suitable for focusing in this direction
* removed.
**/
static GList *
gtk_container_focus_sort (GtkContainer *container,
GList *children,
GtkDirectionType direction)
GList *
_gtk_container_focus_sort (GtkContainer *container,
GList *children,
GtkDirectionType direction,
GtkWidget *old_focus)
{
children = g_list_copy (children);
@ -1829,13 +1837,13 @@ gtk_container_focus_sort (GtkContainer *container,
{
case GTK_DIR_TAB_FORWARD:
case GTK_DIR_TAB_BACKWARD:
return gtk_container_focus_sort_tab (container, children, direction);
return gtk_container_focus_sort_tab (container, children, direction, old_focus);
case GTK_DIR_UP:
case GTK_DIR_DOWN:
return gtk_container_focus_sort_up_down (container, children, direction);
return gtk_container_focus_sort_up_down (container, children, direction, old_focus);
case GTK_DIR_LEFT:
case GTK_DIR_RIGHT:
return gtk_container_focus_sort_left_right (container, children, direction);
return gtk_container_focus_sort_left_right (container, children, direction, old_focus);
}
g_assert_not_reached ();

View File

@ -212,6 +212,10 @@ void _gtk_container_clear_resize_widgets (GtkContainer *container);
gchar* _gtk_container_child_composite_name (GtkContainer *container,
GtkWidget *child);
void _gtk_container_dequeue_resize_handler (GtkContainer *container);
GList *_gtk_container_focus_sort (GtkContainer *container,
GList *children,
GtkDirectionType direction,
GtkWidget *old_focus);
#ifndef GTK_DISABLE_DEPRECATED
#define gtk_container_border_width gtk_container_set_border_width

View File

@ -29,6 +29,7 @@
#include "gdk/gdkkeysyms.h"
#include "gtkbindings.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenubar.h"
#include "gtkmenuitem.h"
#include "gtksettings.h"
@ -52,8 +53,17 @@ static gint gtk_menu_bar_expose (GtkWidget *widget,
GdkEventExpose *event);
static void gtk_menu_bar_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel);
static void gtk_menu_bar_cycle_focus (GtkMenuBar *menubar,
GtkDirectionType dir);
static GtkShadowType get_shadow_type (GtkMenuBar *menubar);
enum {
CYCLE_FOCUS,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static GtkMenuShellClass *parent_class = NULL;
GtkType
@ -81,6 +91,35 @@ gtk_menu_bar_get_type (void)
return menu_bar_type;
}
static guint
binding_signal_new (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
GCallback handler,
GSignalAccumulator accumulator,
gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
...)
{
va_list args;
guint signal_id;
g_return_val_if_fail (signal_name != NULL, 0);
va_start (args, n_params);
signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
g_cclosure_new (handler, NULL, NULL),
accumulator, accu_data, c_marshaller,
return_type, n_params, args);
va_end (args);
return signal_id;
}
static void
gtk_menu_bar_class_init (GtkMenuBarClass *class)
{
@ -103,6 +142,16 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class)
menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
signals[CYCLE_FOCUS] =
binding_signal_new ("cycle_focus",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
G_CALLBACK (gtk_menu_bar_cycle_focus),
NULL, NULL,
_gtk_marshal_VOID__ENUM,
GTK_TYPE_NONE, 1,
GTK_TYPE_DIRECTION_TYPE);
binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set,
GDK_Left, 0,
@ -144,6 +193,22 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class)
"move_current", 1,
GTK_TYPE_MENU_DIRECTION_TYPE,
GTK_MENU_DIR_CHILD);
gtk_binding_entry_add_signal (binding_set,
GDK_Tab, GDK_CONTROL_MASK,
"move_focus", 1,
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
gtk_binding_entry_add_signal (binding_set,
GDK_KP_Tab, GDK_CONTROL_MASK,
"move_focus", 1,
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
gtk_binding_entry_add_signal (binding_set,
GDK_Tab, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
"move_focus", 1,
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
gtk_binding_entry_add_signal (binding_set,
GDK_KP_Tab, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
"move_focus", 1,
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
gtk_widget_class_install_style_property (widget_class,
g_param_spec_enum ("shadow_type",
@ -365,6 +430,19 @@ gtk_menu_bar_expose (GtkWidget *widget,
return FALSE;
}
static GList *
get_menu_bars (GtkWindow *window)
{
return g_object_get_data (G_OBJECT (window), "gtk-menu-bar-list");
}
static void
set_menu_bars (GtkWindow *window,
GList *menubars)
{
g_object_set_data (G_OBJECT (window), "gtk-menu-bar-list", menubars);
}
static gboolean
window_key_press_handler (GtkWidget *widget,
GdkEventKey *event,
@ -396,19 +474,23 @@ window_key_press_handler (GtkWidget *widget,
((event->state & gtk_accelerator_get_default_mod_mask ()) ==
(mods & gtk_accelerator_get_default_mod_mask ())))
{
GtkMenuBar *menubar;
GtkMenuShell *menushell;
menubar = GTK_MENU_BAR (data);
menushell = GTK_MENU_SHELL (menubar);
GList *menubars = get_menu_bars (GTK_WINDOW (widget));
if (menushell->children)
{
gtk_signal_emit_by_name (GTK_OBJECT (menushell->children->data),
"activate_item");
retval = TRUE;
}
menubars = _gtk_container_focus_sort (GTK_CONTAINER (widget), menubars,
GTK_DIR_TAB_FORWARD, NULL);
if (menubars)
{
GtkMenuShell *menushell = GTK_MENU_SHELL (menubars->data);
if (menushell->children)
{
gtk_signal_emit_by_name (GTK_OBJECT (menushell->children->data),
"activate_item");
retval = TRUE;
}
g_list_free (menubars);
}
}
g_free (accel);
@ -421,34 +503,38 @@ static void
add_to_window (GtkWindow *window,
GtkMenuBar *menubar)
{
GtkMenuBar *old_menubar;
GList *menubars = get_menu_bars (window);
old_menubar = g_object_get_data (G_OBJECT (window),
"gtk-menu-bar");
if (old_menubar)
return; /* ignore this case; app programmer on crack, but
* shouldn't spew stuff, just don't support the accel
* for menubar #2
*/
if (!menubars)
{
g_signal_connect (G_OBJECT (window),
"key_press_event",
G_CALLBACK (window_key_press_handler),
NULL);
}
g_object_set_data (G_OBJECT (window),
"gtk-menu-bar",
menubar);
g_signal_connect (G_OBJECT (window),
"key_press_event",
G_CALLBACK (window_key_press_handler),
menubar);
set_menu_bars (window, g_list_prepend (menubars, menubar));
}
static void
remove_from_window (GtkWindow *window,
GtkMenuBar *menubar)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (window),
G_CALLBACK (window_key_press_handler),
menubar);
GList *menubars = get_menu_bars (window);
menubars = g_object_get_data (G_OBJECT (window),
"gtk-menu-bar-list");
menubars = g_list_remove (menubars, menubar);
if (!menubars)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (window),
G_CALLBACK (window_key_press_handler),
NULL);
}
set_menu_bars (window, menubars);
}
static void
@ -469,6 +555,46 @@ gtk_menu_bar_hierarchy_changed (GtkWidget *widget,
add_to_window (GTK_WINDOW (toplevel), menubar);
}
static void
gtk_menu_bar_cycle_focus (GtkMenuBar *menubar,
GtkDirectionType dir)
{
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menubar));
if (GTK_WIDGET_TOPLEVEL (toplevel))
{
GList *menubars = get_menu_bars (GTK_WINDOW (toplevel));
GList *current;
GtkMenuBar *new;
menubars = _gtk_container_focus_sort (GTK_CONTAINER (toplevel), menubars,
dir, GTK_WIDGET (menubar));
if (menubars)
{
current = g_list_find (menubars, menubar);
if (current && current->next)
new = current->next->data;
else
new = menubars->data;
if (new != menubar)
{
GtkMenuShell *new_menushell = GTK_MENU_SHELL (new);
if (new_menushell->children)
{
g_signal_emit_by_name (menubar, "cancel", 0);
gtk_signal_emit_by_name (GTK_OBJECT (new_menushell->children->data),
"activate_item");
}
}
}
g_list_free (menubars);
}
}
static GtkShadowType
get_shadow_type (GtkMenuBar *menubar)
{

View File

@ -809,14 +809,20 @@ static gint
gtk_menu_item_select_timeout (gpointer data)
{
GtkMenuItem *menu_item;
GtkWidget *parent;
GDK_THREADS_ENTER ();
menu_item = GTK_MENU_ITEM (data);
gtk_menu_item_popup_submenu (data);
if (menu_item->timer_from_keypress && menu_item->submenu)
GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
parent = GTK_WIDGET (menu_item)->parent;
if (parent && GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active)
{
gtk_menu_item_popup_submenu (data);
if (menu_item->timer_from_keypress && menu_item->submenu)
GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
}
GDK_THREADS_LEAVE ();

View File

@ -558,6 +558,9 @@ gtk_menu_shell_key_press (GtkWidget *widget,
if (GTK_IS_WINDOW (toplevel) &&
_gtk_window_activate_key (GTK_WINDOW (toplevel), event))
return TRUE;
if (menu_shell->parent_menu_shell)
return gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent *)event);
return FALSE;
}

View File

@ -69,7 +69,7 @@
#define SCROLLBAR_SPACING(w) (GTK_SCROLLED_WINDOW_GET_CLASS (w)->scrollbar_spacing)
#define DEFAULT_SCROLLBAR_SPACING 3
#define DEFAULT_SCROLLBAR_SPACING 0
enum {
PROP_0,

View File

@ -3109,6 +3109,17 @@ create_menus (void)
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);
menubar = gtk_menu_bar_new ();
gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
gtk_widget_show (menubar);
menu = create_menu (2, 10, TRUE);
menuitem = gtk_menu_item_new_with_label ("Second menu bar");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);
box2 = gtk_vbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);