From f38b529c6a7d2cf08df1cb8f730dd54ebdbcfb54 Mon Sep 17 00:00:00 2001 From: Soeren Sandmann Date: Sat, 9 Feb 2002 13:05:02 +0000 Subject: [PATCH] Keyboard navigation for GtkPaned F6: cycle between panes. F8: focus handle Sat Feb 9 13:58:41 2002 Soeren Sandmann * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned F6: cycle between panes. F8: focus handle (#53584) * tests/testgtk.c: Add test cases for GtkPaned keyboard navigation. --- ChangeLog | 9 + ChangeLog.pre-2-0 | 9 + ChangeLog.pre-2-10 | 9 + ChangeLog.pre-2-2 | 9 + ChangeLog.pre-2-4 | 9 + ChangeLog.pre-2-6 | 9 + ChangeLog.pre-2-8 | 9 + gtk/gtkpaned.c | 777 +++++++++++++++++++++++++++++++++++++++++++-- gtk/gtkpaned.h | 19 +- tests/testgtk.c | 366 +++++++++++++++++++++ 10 files changed, 1196 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index afd761312..feeeb5f27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index afd761312..feeeb5f27 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index afd761312..feeeb5f27 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index afd761312..feeeb5f27 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index afd761312..feeeb5f27 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index afd761312..feeeb5f27 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index afd761312..feeeb5f27 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +Sat Feb 9 13:58:41 2002 Soeren Sandmann + + * gtk/gtkpaned.[ch]: Keyboard navigation for GtkPaned + F6: cycle between panes. + F8: focus handle (#53584) + + * tests/testgtk.c: Add test cases for GtkPaned keyboard + navigation. + Sat Feb 9 00:16:31 2002 Owen Taylor * gdk/x11/gdkimage-x11.c (_gdk_x11_copy_to_image): diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c index b0e3385e4..e3b3a4bfa 100644 --- a/gtk/gtkpaned.c +++ b/gtk/gtkpaned.c @@ -26,6 +26,12 @@ #include "gtkintl.h" #include "gtkpaned.h" +#include "gtkbindings.h" +#include "gtksignal.h" +#include "gdk/gdkkeysyms.h" +#include "gtkwindow.h" +#include "gtkmain.h" +#include "gtkmarshalers.h" enum { PROP_0, @@ -33,31 +39,60 @@ enum { PROP_POSITION_SET }; -static void gtk_paned_class_init (GtkPanedClass *klass); -static void gtk_paned_init (GtkPaned *paned); -static void gtk_paned_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_paned_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void gtk_paned_realize (GtkWidget *widget); -static void gtk_paned_unrealize (GtkWidget *widget); -static void gtk_paned_map (GtkWidget *widget); -static void gtk_paned_unmap (GtkWidget *widget); -static gint gtk_paned_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_paned_add (GtkContainer *container, - GtkWidget *widget); -static void gtk_paned_remove (GtkContainer *container, - GtkWidget *widget); -static void gtk_paned_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static GtkType gtk_paned_child_type (GtkContainer *container); +enum { + CYCLE_CHILD_FOCUS, + TOGGLE_HANDLE_FOCUS, + MOVE_HANDLE, + CYCLE_HANDLE_FOCUS, + LAST_SIGNAL, + ACCEPT_POSITION, + CANCEL_POSITION +}; + +static void gtk_paned_class_init (GtkPanedClass *klass); +static void gtk_paned_init (GtkPaned *paned); +static void gtk_paned_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_paned_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gtk_paned_realize (GtkWidget *widget); +static void gtk_paned_unrealize (GtkWidget *widget); +static void gtk_paned_map (GtkWidget *widget); +static void gtk_paned_unmap (GtkWidget *widget); +static gint gtk_paned_expose (GtkWidget *widget, + GdkEventExpose *event); +static gboolean gtk_paned_focus (GtkWidget *widget, + GtkDirectionType direction); +static void gtk_paned_add (GtkContainer *container, + GtkWidget *widget); +static void gtk_paned_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_paned_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void gtk_paned_set_focus_child (GtkContainer *container, + GtkWidget *child); +static void gtk_paned_set_saved_focus (GtkPaned *paned, + GtkWidget *widget); +static void gtk_paned_set_last_child1_focus (GtkPaned *paned, + GtkWidget *widget); +static void gtk_paned_set_last_child2_focus (GtkPaned *paned, + GtkWidget *widget); +static gboolean gtk_paned_cycle_child_focus (GtkPaned *paned, + gboolean reverse); +static gboolean gtk_paned_cycle_handle_focus (GtkPaned *paned, + gboolean reverse); +static gboolean gtk_paned_move_handle (GtkPaned *paned, + GtkScrollType scroll); +static gboolean gtk_paned_accept_position (GtkPaned *paned); +static gboolean gtk_paned_cancel_position (GtkPaned *paned); +static gboolean gtk_paned_toggle_handle_focus (GtkPaned *paned); +static GtkType gtk_paned_child_type (GtkContainer *container); static GtkContainerClass *parent_class = NULL; @@ -87,16 +122,48 @@ gtk_paned_get_type (void) return paned_type; } +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +add_tab_bindings (GtkBindingSet *binding_set, + GdkModifierType modifiers, + gboolean reverse) +{ + gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers, + "cycle_handle_focus", 1, + G_TYPE_BOOLEAN, reverse); + gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers, + "cycle_handle_focus", 1, + G_TYPE_BOOLEAN, reverse); + gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, modifiers, + "cycle_handle_focus", 1, + G_TYPE_BOOLEAN, reverse); +} + +static void +add_move_binding (GtkBindingSet *binding_set, + guint keyval, + GdkModifierType mask, + GtkScrollType scroll) +{ + gtk_binding_entry_add_signal (binding_set, keyval, mask, + "move_handle", 1, + GTK_TYPE_SCROLL_TYPE, scroll); +} + static void gtk_paned_class_init (GtkPanedClass *class) { GObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; + GtkPanedClass *paned_class; + GtkBindingSet *binding_set; object_class = (GObjectClass *) class; widget_class = (GtkWidgetClass *) class; container_class = (GtkContainerClass *) class; + paned_class = (GtkPanedClass *) class; parent_class = gtk_type_class (GTK_TYPE_CONTAINER); @@ -108,12 +175,21 @@ gtk_paned_class_init (GtkPanedClass *class) widget_class->map = gtk_paned_map; widget_class->unmap = gtk_paned_unmap; widget_class->expose_event = gtk_paned_expose; + widget_class->focus = gtk_paned_focus; container_class->add = gtk_paned_add; container_class->remove = gtk_paned_remove; container_class->forall = gtk_paned_forall; container_class->child_type = gtk_paned_child_type; - + container_class->set_focus_child = gtk_paned_set_focus_child; + + paned_class->cycle_child_focus = gtk_paned_cycle_child_focus; + paned_class->toggle_handle_focus = gtk_paned_toggle_handle_focus; + paned_class->move_handle = gtk_paned_move_handle; + paned_class->cycle_handle_focus = gtk_paned_cycle_handle_focus; + paned_class->accept_position = gtk_paned_accept_position; + paned_class->cancel_position = gtk_paned_cancel_position; + g_object_class_install_property (object_class, PROP_POSITION, g_param_spec_int ("position", @@ -139,6 +215,133 @@ gtk_paned_class_init (GtkPanedClass *class) G_MAXINT, 5, G_PARAM_READABLE)); + + signals [CYCLE_HANDLE_FOCUS] = + g_signal_new ("cycle_child_focus", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkPanedClass, cycle_child_focus), + NULL, NULL, + _gtk_marshal_BOOLEAN__BOOLEAN, + G_TYPE_BOOLEAN, 1, + G_TYPE_BOOLEAN); + + signals [TOGGLE_HANDLE_FOCUS] = + g_signal_new ("toggle_handle_focus", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkPanedClass, toggle_handle_focus), + NULL, NULL, + _gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + signals[MOVE_HANDLE] = + g_signal_new ("move_handle", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkPanedClass, move_handle), + NULL, NULL, + _gtk_marshal_BOOLEAN__ENUM, + G_TYPE_BOOLEAN, 1, + GTK_TYPE_SCROLL_TYPE); + + signals [CYCLE_HANDLE_FOCUS] = + g_signal_new ("cycle_handle_focus", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkPanedClass, cycle_handle_focus), + NULL, NULL, + _gtk_marshal_BOOLEAN__BOOLEAN, + G_TYPE_BOOLEAN, 1, + G_TYPE_BOOLEAN); + + signals [ACCEPT_POSITION] = + g_signal_new ("accept_position", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkPanedClass, accept_position), + NULL, NULL, + _gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + signals [CANCEL_POSITION] = + g_signal_new ("cancel_position", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkPanedClass, cancel_position), + NULL, NULL, + _gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + binding_set = gtk_binding_set_by_class (object_class); + + /* F6 and friends */ + gtk_binding_entry_add_signal (binding_set, + GDK_F6, 0, + "cycle_child_focus", 1, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal (binding_set, + GDK_F6, GDK_SHIFT_MASK, + "cycle_child_focus", 1, + G_TYPE_BOOLEAN, TRUE); + + /* F8 and friends */ + gtk_binding_entry_add_signal (binding_set, + GDK_F8, 0, + "toggle_handle_focus", 0); + + add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD); + add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD); + add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD); + add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD); + + /* accept and cancel positions */ + gtk_binding_entry_add_signal (binding_set, + GDK_Escape, 0, + "cancel_position", 0); + + gtk_binding_entry_add_signal (binding_set, + GDK_Return, 0, + "accept_position", 0); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Enter, 0, + "accept_position", 0); + gtk_binding_entry_add_signal (binding_set, + GDK_space, 0, + "accept_position", 0); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Space, 0, + "accept_position", 0); + + /* move handle */ + add_move_binding (binding_set, GDK_Left, 0, GTK_SCROLL_STEP_LEFT); + add_move_binding (binding_set, GDK_KP_Left, 0, GTK_SCROLL_STEP_LEFT); + add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT); + add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT); + + add_move_binding (binding_set, GDK_Right, 0, GTK_SCROLL_STEP_RIGHT); + add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT); + add_move_binding (binding_set, GDK_KP_Right, 0, GTK_SCROLL_STEP_RIGHT); + add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT); + + add_move_binding (binding_set, GDK_Up, 0, GTK_SCROLL_STEP_UP); + add_move_binding (binding_set, GDK_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP); + add_move_binding (binding_set, GDK_KP_Up, 0, GTK_SCROLL_STEP_UP); + add_move_binding (binding_set, GDK_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP); + add_move_binding (binding_set, GDK_Page_Up, 0, GTK_SCROLL_PAGE_UP); + add_move_binding (binding_set, GDK_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP); + + add_move_binding (binding_set, GDK_Down, 0, GTK_SCROLL_STEP_DOWN); + add_move_binding (binding_set, GDK_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN); + add_move_binding (binding_set, GDK_KP_Down, 0, GTK_SCROLL_STEP_DOWN); + add_move_binding (binding_set, GDK_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN); + add_move_binding (binding_set, GDK_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT); + add_move_binding (binding_set, GDK_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT); + + add_move_binding (binding_set, GDK_Home, 0, GTK_SCROLL_START); + add_move_binding (binding_set, GDK_KP_Home, 0, GTK_SCROLL_START); + add_move_binding (binding_set, GDK_End, 0, GTK_SCROLL_END); + add_move_binding (binding_set, GDK_KP_End, 0, GTK_SCROLL_END); } static GtkType @@ -153,7 +356,7 @@ gtk_paned_child_type (GtkContainer *container) static void gtk_paned_init (GtkPaned *paned) { - GTK_WIDGET_SET_FLAGS (paned, GTK_NO_WINDOW); + GTK_WIDGET_SET_FLAGS (paned, GTK_NO_WINDOW | GTK_CAN_FOCUS); paned->child1 = NULL; paned->child2 = NULL; @@ -166,6 +369,12 @@ gtk_paned_init (GtkPaned *paned) paned->position_set = FALSE; paned->last_allocation = -1; paned->in_drag = FALSE; + + paned->saved_focus = NULL; + paned->last_child1_focus = NULL; + paned->last_child2_focus = NULL; + paned->in_recursion = FALSE; + paned->original_position = -1; paned->handle_pos.x = -1; paned->handle_pos.y = -1; @@ -272,6 +481,10 @@ gtk_paned_unrealize (GtkWidget *widget) paned->handle = NULL; } + gtk_paned_set_last_child1_focus (paned, NULL); + gtk_paned_set_last_child2_focus (paned, NULL); + gtk_paned_set_saved_focus (paned, NULL); + if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } @@ -313,12 +526,17 @@ gtk_paned_expose (GtkWidget *widget, if (!gdk_region_empty (region)) { + GtkStateType state; GdkRectangle clip; gdk_region_get_clipbox (region, &clip); + + state = GTK_WIDGET_STATE (widget); + if (gtk_widget_is_focus (widget)) + state = GTK_STATE_SELECTED; gtk_paint_handle (widget->style, widget->window, - GTK_STATE_NORMAL, GTK_SHADOW_NONE, + state, GTK_SHADOW_NONE, &clip, widget, "paned", paned->handle_pos.x, paned->handle_pos.y, paned->handle_pos.width, paned->handle_pos.height, @@ -334,6 +552,24 @@ gtk_paned_expose (GtkWidget *widget, return FALSE; } +static gboolean +gtk_paned_focus (GtkWidget *widget, + GtkDirectionType direction) + +{ + gboolean retval; + + /* This is a hack, but how can this be done without + * excessive cut-and-paste from gtkcontainer.c? + */ + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); + retval = (* GTK_WIDGET_CLASS (parent_class)->focus) (widget, direction); + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); + + return retval; +} + void gtk_paned_add1 (GtkPaned *paned, GtkWidget *widget) @@ -562,3 +798,488 @@ gtk_paned_compute_position (GtkPaned *paned, paned->last_allocation = allocation; } + +static void +gtk_paned_set_saved_focus (GtkPaned *paned, GtkWidget *widget) +{ + if (paned->saved_focus) + g_object_remove_weak_pointer (G_OBJECT (paned->saved_focus), + (gpointer *)&(paned->saved_focus)); + + paned->saved_focus = widget; + + if (paned->saved_focus) + g_object_add_weak_pointer (G_OBJECT (paned->saved_focus), + (gpointer *)&(paned->saved_focus)); +} + +static void +gtk_paned_set_last_child1_focus (GtkPaned *paned, GtkWidget *widget) +{ + if (paned->last_child1_focus) + g_object_remove_weak_pointer (G_OBJECT (paned->last_child1_focus), + (gpointer *)&(paned->last_child1_focus)); + + paned->last_child1_focus = widget; + + if (paned->last_child1_focus) + g_object_add_weak_pointer (G_OBJECT (paned->last_child1_focus), + (gpointer *)&(paned->last_child1_focus)); +} + +static void +gtk_paned_set_last_child2_focus (GtkPaned *paned, GtkWidget *widget) +{ + if (paned->last_child2_focus) + g_object_remove_weak_pointer (G_OBJECT (paned->last_child2_focus), + (gpointer *)&(paned->last_child2_focus)); + + paned->last_child2_focus = widget; + + if (paned->last_child2_focus) + g_object_add_weak_pointer (G_OBJECT (paned->last_child2_focus), + (gpointer *)&(paned->last_child2_focus)); +} + +static GtkWidget * +paned_get_focus_widget (GtkPaned *paned) +{ + GtkWidget *toplevel; + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); + if (GTK_WIDGET_TOPLEVEL (toplevel)) + return GTK_WINDOW (toplevel)->focus_widget; + + return NULL; +} + +static void +gtk_paned_set_focus_child (GtkContainer *container, + GtkWidget *focus_child) +{ + GtkPaned *paned; + + g_return_if_fail (GTK_IS_PANED (container)); + + paned = GTK_PANED (container); + + if (focus_child == NULL) + { + GtkWidget *last_focus; + GtkWidget *w; + + last_focus = paned_get_focus_widget (paned); + + if (last_focus) + { + /* If there is one or more paned widgets between us and the + * focus widget, we want the topmost of those as last_focus + */ + for (w = last_focus; w != GTK_WIDGET (paned); w = w->parent) + if (GTK_IS_PANED (w)) + last_focus = w; + + if (container->focus_child == paned->child1) + gtk_paned_set_last_child1_focus (paned, last_focus); + else if (container->focus_child == paned->child2) + gtk_paned_set_last_child2_focus (paned, last_focus); + } + } + + if (parent_class->set_focus_child) + (* parent_class->set_focus_child) (container, focus_child); +} + +static void +gtk_paned_get_cycle_chain (GtkPaned *paned, + GtkDirectionType direction, + GList **widgets) +{ + GtkContainer *container = GTK_CONTAINER (paned); + GtkWidget *ancestor = NULL; + GList *temp_list = NULL; + GList *list; + + if (paned->in_recursion) + return; + + g_assert (widgets != NULL); + + if (paned->last_child1_focus && + !gtk_widget_is_ancestor (paned->last_child1_focus, GTK_WIDGET (paned))) + { + gtk_paned_set_last_child1_focus (paned, NULL); + } + + if (paned->last_child2_focus && + !gtk_widget_is_ancestor (paned->last_child2_focus, GTK_WIDGET (paned))) + { + gtk_paned_set_last_child2_focus (paned, NULL); + } + + if (GTK_WIDGET (paned)->parent) + ancestor = gtk_widget_get_ancestor (GTK_WIDGET (paned)->parent, GTK_TYPE_PANED); + + /* The idea here is that temp_list is a list of widgets we want to cycle + * to. The list is prioritized so that the first element is our first + * choice, the next our second, and so on. + * + * We can't just use g_list_reverse(), because we want to try + * paned->last_child?_focus before paned->child?, both when we + * are going forward and backward. + */ + if (direction == GTK_DIR_TAB_FORWARD) + { + if (container->focus_child == paned->child1) + { + temp_list = g_list_append (temp_list, paned->last_child2_focus); + temp_list = g_list_append (temp_list, paned->child2); + temp_list = g_list_append (temp_list, ancestor); + } + else if (container->focus_child == paned->child2) + { + temp_list = g_list_append (temp_list, ancestor); + temp_list = g_list_append (temp_list, paned->last_child1_focus); + temp_list = g_list_append (temp_list, paned->child1); + } + else + { + temp_list = g_list_append (temp_list, paned->last_child1_focus); + temp_list = g_list_append (temp_list, paned->child1); + temp_list = g_list_append (temp_list, paned->last_child2_focus); + temp_list = g_list_append (temp_list, paned->child2); + temp_list = g_list_append (temp_list, ancestor); + } + } + else + { + if (container->focus_child == paned->child1) + { + temp_list = g_list_append (temp_list, ancestor); + temp_list = g_list_append (temp_list, paned->last_child2_focus); + temp_list = g_list_append (temp_list, paned->child2); + } + else if (container->focus_child == paned->child2) + { + temp_list = g_list_append (temp_list, paned->last_child1_focus); + temp_list = g_list_append (temp_list, paned->child1); + temp_list = g_list_append (temp_list, ancestor); + } + else + { + temp_list = g_list_append (temp_list, paned->last_child2_focus); + temp_list = g_list_append (temp_list, paned->child2); + temp_list = g_list_append (temp_list, paned->last_child1_focus); + temp_list = g_list_append (temp_list, paned->child1); + temp_list = g_list_append (temp_list, ancestor); + } + } + + /* Walk through the list and expand all the paned widgets. */ + for (list = temp_list; list != NULL; list = list->next) + { + GtkWidget *widget = list->data; + + if (widget) + { + if (GTK_IS_PANED (widget)) + { + paned->in_recursion = TRUE; + gtk_paned_get_cycle_chain (GTK_PANED (widget), direction, widgets); + paned->in_recursion = FALSE; + } + else + { + *widgets = g_list_append (*widgets, widget); + } + } + } + + g_list_free (temp_list); +} + +static gboolean +gtk_paned_cycle_child_focus (GtkPaned *paned, + gboolean reversed) +{ + GList *cycle_chain = NULL; + GList *list; + + GtkDirectionType direction = reversed? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; + + /* ignore f6 if the handle is focused */ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + return TRUE; + + /* we can't just let the event propagate up the hierarchy, + * because the paned will want to cycle focus _unless_ an + * ancestor paned handles the event + */ + gtk_paned_get_cycle_chain (paned, direction, &cycle_chain); + + for (list = cycle_chain; list != NULL; list = list->next) + if (gtk_widget_child_focus (GTK_WIDGET (list->data), direction)) + break; + + g_list_free (cycle_chain); + + return TRUE; +} + +static void +get_child_panes (GtkWidget *widget, + GList **panes) +{ + if (GTK_IS_PANED (widget)) + { + GtkPaned *paned = GTK_PANED (widget); + + get_child_panes (paned->child1, panes); + *panes = g_list_prepend (*panes, widget); + get_child_panes (paned->child2, panes); + } + else if (GTK_IS_CONTAINER (widget)) + { + gtk_container_foreach (GTK_CONTAINER (widget), + (GtkCallback)get_child_panes, panes); + } +} + +static GList * +get_all_panes (GtkPaned *paned) +{ + GtkPaned *topmost = NULL; + GList *result = NULL; + GtkWidget *w; + + for (w = GTK_WIDGET (paned); w != NULL; w = w->parent) + { + if (GTK_IS_PANED (w)) + topmost = GTK_PANED (w); + } + + g_assert (topmost); + + get_child_panes (GTK_WIDGET (topmost), &result); + + return g_list_reverse (result); +} + +static void +gtk_paned_find_neighbours (GtkPaned *paned, + GtkPaned **next, + GtkPaned **prev) +{ + GList *all_panes = get_all_panes (paned); + GList *this_link; + + g_assert (all_panes); + + this_link = g_list_find (all_panes, paned); + + g_assert (this_link); + + if (this_link->next) + *next = this_link->next->data; + else + *next = all_panes->data; + + if (this_link->prev) + *prev = this_link->prev->data; + else + *prev = g_list_last (all_panes)->data; + + if (*next == paned) + *next = NULL; + + if (*prev == paned) + *prev = NULL; + + g_list_free (all_panes); +} + +static gboolean +gtk_paned_move_handle (GtkPaned *paned, + GtkScrollType scroll) +{ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + { + gint old_position; + gint new_position; + + enum { + SINGLE_STEP_SIZE = 1, + PAGE_STEP_SIZE = 75, + }; + + old_position = gtk_paned_get_position (paned); + + switch (scroll) + { + case GTK_SCROLL_STEP_LEFT: + case GTK_SCROLL_STEP_UP: + case GTK_SCROLL_STEP_BACKWARD: + new_position = old_position - SINGLE_STEP_SIZE; + break; + + case GTK_SCROLL_STEP_RIGHT: + case GTK_SCROLL_STEP_DOWN: + case GTK_SCROLL_STEP_FORWARD: + new_position = old_position + SINGLE_STEP_SIZE; + break; + + case GTK_SCROLL_PAGE_LEFT: + case GTK_SCROLL_PAGE_UP: + case GTK_SCROLL_PAGE_BACKWARD: + new_position = old_position - PAGE_STEP_SIZE; + break; + + case GTK_SCROLL_PAGE_RIGHT: + case GTK_SCROLL_PAGE_DOWN: + case GTK_SCROLL_PAGE_FORWARD: + new_position = old_position + PAGE_STEP_SIZE; + break; + + case GTK_SCROLL_START: + new_position = paned->min_position; + break; + + case GTK_SCROLL_END: + new_position = paned->max_position; + break; + + default: + new_position = old_position; + break; + } + + new_position = CLAMP (new_position, paned->min_position, paned->max_position); + + if (old_position != new_position) + gtk_paned_set_position (paned, new_position); + + return TRUE; + } + + return FALSE; +} + +static void +gtk_paned_restore_focus (GtkPaned *paned) +{ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + { + if (paned->saved_focus && GTK_WIDGET_SENSITIVE (paned->saved_focus)) + { + gtk_widget_grab_focus (paned->saved_focus); + } + else + { + /* the saved focus is somehow not available for focusing, + * try + * 1) tabbing into the paned widget + * if that didn't work, + * 2) unset focus for the window if there is one + */ + + if (!gtk_widget_child_focus (GTK_WIDGET (paned), GTK_DIR_TAB_FORWARD)) + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); + + if (GTK_IS_WINDOW (toplevel)) + gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); + } + } + + gtk_paned_set_saved_focus (paned, NULL); + } +} + +static gboolean +gtk_paned_accept_position (GtkPaned *paned) +{ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + { + paned->original_position = -1; + gtk_paned_restore_focus (paned); + + return TRUE; + } + + return FALSE; +} + + +static gboolean +gtk_paned_cancel_position (GtkPaned *paned) +{ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + { + if (paned->original_position != -1) + { + gtk_paned_set_position (paned, paned->original_position); + paned->original_position = -1; + } + + gtk_paned_restore_focus (paned); + return TRUE; + } + + return FALSE; +} + +static gboolean +gtk_paned_cycle_handle_focus (GtkPaned *paned, + gboolean reversed) +{ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + { + GtkPaned *next, *prev; + GtkPaned *focus = NULL; + + gtk_paned_find_neighbours (paned, &next, &prev); + + if (reversed && prev) + focus = prev; + else if (!reversed && next) + focus = next; + + if (focus) + { + gtk_paned_set_saved_focus (focus, paned->saved_focus); + gtk_paned_set_saved_focus (paned, NULL); + gtk_widget_grab_focus (GTK_WIDGET (focus)); + + if (!gtk_widget_is_focus (GTK_WIDGET (paned))) + { + paned->original_position = -1; + focus->original_position = gtk_paned_get_position (focus); + } + } + + return TRUE; + } + + return FALSE; +} + +static gboolean +gtk_paned_toggle_handle_focus (GtkPaned *paned) +{ + if (gtk_widget_is_focus (GTK_WIDGET (paned))) + { + gtk_paned_accept_position (paned); + } + else + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); + + if (GTK_IS_WINDOW (toplevel)) + gtk_paned_set_saved_focus (paned, GTK_WINDOW (toplevel)->focus_widget); + + gtk_widget_grab_focus (GTK_WIDGET (paned)); + paned->original_position = gtk_paned_get_position (paned); + } + + return TRUE; +} diff --git a/gtk/gtkpaned.h b/gtk/gtkpaned.h index 7606be2a7..115dd12a6 100644 --- a/gtk/gtkpaned.h +++ b/gtk/gtkpaned.h @@ -72,11 +72,28 @@ struct _GtkPaned guint child2_shrink : 1; guint child2_resize : 1; guint orientation : 1; -}; + guint in_recursion : 1; + GtkWidget *last_child1_focus; + GtkWidget *last_child2_focus; + GtkWidget *saved_focus; + + gint original_position; +}; + struct _GtkPanedClass { GtkContainerClass parent_class; + + gboolean (* cycle_child_focus) (GtkPaned *paned, + gboolean reverse); + gboolean (* toggle_handle_focus) (GtkPaned *paned); + gboolean (* move_handle) (GtkPaned *paned, + GtkScrollType scroll); + gboolean (* cycle_handle_focus) (GtkPaned *paned, + gboolean reverse); + gboolean (* accept_position) (GtkPaned *paned); + gboolean (* cancel_position) (GtkPaned *paned); }; diff --git a/tests/testgtk.c b/tests/testgtk.c index fbd4af4c6..f2b23a81e 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -7902,6 +7902,371 @@ create_panes (void) gtk_widget_destroy (window); } +/* + * Paned keyboard navigation + */ + +static GtkWidget* +paned_keyboard_window1 (void) +{ + GtkWidget *window1; + GtkWidget *hpaned1; + GtkWidget *frame1; + GtkWidget *vbox1; + GtkWidget *button7; + GtkWidget *button8; + GtkWidget *button9; + GtkWidget *vpaned1; + GtkWidget *frame2; + GtkWidget *frame5; + GtkWidget *hbox1; + GtkWidget *button5; + GtkWidget *button6; + GtkWidget *frame3; + GtkWidget *frame4; + GtkWidget *table1; + GtkWidget *button1; + GtkWidget *button2; + GtkWidget *button3; + GtkWidget *button4; + + window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation"); + + hpaned1 = gtk_hpaned_new (); + gtk_container_add (GTK_CONTAINER (window1), hpaned1); + + frame1 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (frame1), vbox1); + + button7 = gtk_button_new_with_label ("button7"); + gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0); + + button8 = gtk_button_new_with_label ("button8"); + gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0); + + button9 = gtk_button_new_with_label ("button9"); + gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0); + + vpaned1 = gtk_vpaned_new (); + gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE); + + frame2 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN); + + frame5 = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (frame2), frame5); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (frame5), hbox1); + + button5 = gtk_button_new_with_label ("button5"); + gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0); + + button6 = gtk_button_new_with_label ("button6"); + gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0); + + frame3 = gtk_frame_new (NULL); + gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN); + + frame4 = gtk_frame_new ("Buttons"); + gtk_container_add (GTK_CONTAINER (frame3), frame4); + gtk_container_set_border_width (GTK_CONTAINER (frame4), 15); + + table1 = gtk_table_new (2, 2, FALSE); + gtk_container_add (GTK_CONTAINER (frame4), table1); + gtk_container_set_border_width (GTK_CONTAINER (table1), 11); + + button1 = gtk_button_new_with_label ("button1"); + gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + button2 = gtk_button_new_with_label ("button2"); + gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + button3 = gtk_button_new_with_label ("button3"); + gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + button4 = gtk_button_new_with_label ("button4"); + gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + return window1; +} + +static GtkWidget* +paned_keyboard_window2 (void) +{ + GtkWidget *window2; + GtkWidget *hpaned2; + GtkWidget *frame6; + GtkWidget *button13; + GtkWidget *hbox2; + GtkWidget *vpaned2; + GtkWidget *frame7; + GtkWidget *button12; + GtkWidget *frame8; + GtkWidget *button11; + GtkWidget *button10; + + window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane"); + + hpaned2 = gtk_hpaned_new (); + gtk_container_add (GTK_CONTAINER (window2), hpaned2); + + frame6 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN); + + button13 = gtk_button_new_with_label ("button13"); + gtk_container_add (GTK_CONTAINER (frame6), button13); + + hbox2 = gtk_hbox_new (FALSE, 0); + gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE); + + vpaned2 = gtk_vpaned_new (); + gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0); + + frame7 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN); + + button12 = gtk_button_new_with_label ("button12"); + gtk_container_add (GTK_CONTAINER (frame7), button12); + + frame8 = gtk_frame_new (NULL); + gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN); + + button11 = gtk_button_new_with_label ("button11"); + gtk_container_add (GTK_CONTAINER (frame8), button11); + + button10 = gtk_button_new_with_label ("button10"); + gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0); + + return window2; +} + +static GtkWidget* +paned_keyboard_window3 (void) +{ + GtkWidget *window3; + GtkWidget *vbox2; + GtkWidget *label1; + GtkWidget *hpaned3; + GtkWidget *frame9; + GtkWidget *button14; + GtkWidget *hpaned4; + GtkWidget *frame10; + GtkWidget *button15; + GtkWidget *hpaned5; + GtkWidget *frame11; + GtkWidget *button16; + GtkWidget *frame12; + GtkWidget *button17; + + window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (window3), "window3", window3); + gtk_window_set_title (GTK_WINDOW (window3), "Nested panes"); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window3), vbox2); + + label1 = gtk_label_new ("Three panes nested inside each other"); + gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0); + + hpaned3 = gtk_hpaned_new (); + gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0); + + frame9 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN); + + button14 = gtk_button_new_with_label ("button14"); + gtk_container_add (GTK_CONTAINER (frame9), button14); + + hpaned4 = gtk_hpaned_new (); + gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE); + + frame10 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN); + + button15 = gtk_button_new_with_label ("button15"); + gtk_container_add (GTK_CONTAINER (frame10), button15); + + hpaned5 = gtk_hpaned_new (); + gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE); + + frame11 = gtk_frame_new (NULL); + gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN); + + button16 = gtk_button_new_with_label ("button16"); + gtk_container_add (GTK_CONTAINER (frame11), button16); + + frame12 = gtk_frame_new (NULL); + gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE); + gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN); + + button17 = gtk_button_new_with_label ("button17"); + gtk_container_add (GTK_CONTAINER (frame12), button17); + + return window3; +} + +static GtkWidget* +paned_keyboard_window4 (void) +{ + GtkWidget *window4; + GtkWidget *vbox3; + GtkWidget *label2; + GtkWidget *hpaned6; + GtkWidget *vpaned3; + GtkWidget *button19; + GtkWidget *button18; + GtkWidget *hbox3; + GtkWidget *vpaned4; + GtkWidget *button21; + GtkWidget *button20; + GtkWidget *vpaned5; + GtkWidget *button23; + GtkWidget *button22; + GtkWidget *vpaned6; + GtkWidget *button25; + GtkWidget *button24; + + window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (window4), "window4", window4); + gtk_window_set_title (GTK_WINDOW (window4), "window4"); + + vbox3 = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window4), vbox3); + + label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n - vpaned\n - vpaned\n - vpaned\n"); + gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT); + + hpaned6 = gtk_hpaned_new (); + gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0); + + vpaned3 = gtk_vpaned_new (); + gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE); + + button19 = gtk_button_new_with_label ("button19"); + gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE); + + button18 = gtk_button_new_with_label ("button18"); + gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE); + + hbox3 = gtk_hbox_new (FALSE, 0); + gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE); + + vpaned4 = gtk_vpaned_new (); + gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0); + + button21 = gtk_button_new_with_label ("button21"); + gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE); + + button20 = gtk_button_new_with_label ("button20"); + gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE); + + vpaned5 = gtk_vpaned_new (); + gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0); + + button23 = gtk_button_new_with_label ("button23"); + gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE); + + button22 = gtk_button_new_with_label ("button22"); + gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE); + + vpaned6 = gtk_vpaned_new (); + gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0); + + button25 = gtk_button_new_with_label ("button25"); + gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE); + + button24 = gtk_button_new_with_label ("button24"); + gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE); + + return window4; +} + +static void +create_paned_keyboard_navigation (void) +{ + static GtkWidget *window1 = NULL; + static GtkWidget *window2 = NULL; + static GtkWidget *window3 = NULL; + static GtkWidget *window4 = NULL; + + if (!window1) + { + window1 = paned_keyboard_window1 (); + gtk_signal_connect (GTK_OBJECT (window1), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &window1); + } + + if (!window2) + { + window2 = paned_keyboard_window2 (); + gtk_signal_connect (GTK_OBJECT (window2), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &window2); + } + + if (!window3) + { + window3 = paned_keyboard_window3 (); + gtk_signal_connect (GTK_OBJECT (window3), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &window3); + } + + if (!window4) + { + window4 = paned_keyboard_window4 (); + gtk_signal_connect (GTK_OBJECT (window4), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &window4); + } + + if (GTK_WIDGET_VISIBLE (window1)) + gtk_widget_destroy (GTK_WIDGET (window1)); + else + gtk_widget_show_all (GTK_WIDGET (window1)); + + if (GTK_WIDGET_VISIBLE (window2)) + gtk_widget_destroy (GTK_WIDGET (window2)); + else + gtk_widget_show_all (GTK_WIDGET (window2)); + + if (GTK_WIDGET_VISIBLE (window3)) + gtk_widget_destroy (GTK_WIDGET (window3)); + else + gtk_widget_show_all (GTK_WIDGET (window3)); + + if (GTK_WIDGET_VISIBLE (window4)) + gtk_widget_destroy (GTK_WIDGET (window4)); + else + gtk_widget_show_all (GTK_WIDGET (window4)); +} + + /* * Shaped Windows */ @@ -10966,6 +11331,7 @@ struct { { "modal window", create_modal_window, TRUE }, { "notebook", create_notebook }, { "panes", create_panes }, + { "paned keyboard", create_paned_keyboard_navigation }, { "pixmap", create_pixmap }, { "preview color", create_color_preview, TRUE }, { "preview gray", create_gray_preview, TRUE }, -- 2.43.2