diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkclist.c gtk+-1.2.10/gtk/gtkclist.c *** gtk+-1.2.10.orig/gtk/gtkclist.c Wed Feb 28 19:14:09 2001 --- gtk+-1.2.10/gtk/gtkclist.c Tue May 15 12:46:46 2001 *************** *** 683,689 **** widget_class->expose_event = gtk_clist_expose; widget_class->size_request = gtk_clist_size_request; widget_class->size_allocate = gtk_clist_size_allocate; ! widget_class->key_press_event = gtk_clist_key_press; widget_class->focus_in_event = gtk_clist_focus_in; widget_class->focus_out_event = gtk_clist_focus_out; widget_class->draw_focus = gtk_clist_draw_focus; --- 683,689 ---- widget_class->expose_event = gtk_clist_expose; widget_class->size_request = gtk_clist_size_request; widget_class->size_allocate = gtk_clist_size_allocate; ! widget_class->focus_in_event = gtk_clist_focus_in; widget_class->focus_out_event = gtk_clist_focus_out; widget_class->draw_focus = gtk_clist_draw_focus; *************** *** 4439,4445 **** * gtk_clist_draw * gtk_clist_expose * gtk_clist_style_set - * gtk_clist_key_press * gtk_clist_button_press * gtk_clist_button_release * gtk_clist_motion --- 4439,4444 ---- *************** *** 4910,4943 **** } static gint - gtk_clist_key_press (GtkWidget *widget, - GdkEventKey *event) - { - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - if (GTK_WIDGET_CLASS (parent_class)->key_press_event && - GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event)) - return TRUE; - - switch (event->keyval) - { - case GDK_Tab: - case GDK_ISO_Left_Tab: - if (event->state & GDK_SHIFT_MASK) - return gtk_container_focus (GTK_CONTAINER (widget), - GTK_DIR_TAB_BACKWARD); - else - return gtk_container_focus (GTK_CONTAINER (widget), - GTK_DIR_TAB_FORWARD); - default: - break; - } - return FALSE; - } - - static gint gtk_clist_button_press (GtkWidget *widget, GdkEventButton *event) { --- 4909,4914 ---- *************** *** 6583,6592 **** g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_CLIST (container), FALSE); if (!GTK_WIDGET_IS_SENSITIVE (container)) return FALSE; ! clist = GTK_CLIST (container); focus_child = container->focus_child; old_row = clist->focus_row; --- 6554,6568 ---- g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_CLIST (container), FALSE); + clist = GTK_CLIST (container); + if (!GTK_WIDGET_IS_SENSITIVE (container)) return FALSE; ! if ((GTK_WIDGET_HAS_FOCUS (container) && ! GTK_CLIST_CHILD_HAS_FOCUS (clist))) ! return FALSE; ! focus_child = container->focus_child; old_row = clist->focus_row; diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkcontainer.c gtk+-1.2.10/gtk/gtkcontainer.c *** gtk+-1.2.10.orig/gtk/gtkcontainer.c Sun Sep 26 19:46:57 1999 --- gtk+-1.2.10/gtk/gtkcontainer.c Tue May 15 12:46:46 2001 *************** *** 82,94 **** static void gtk_container_real_set_focus_child (GtkContainer *container, GtkWidget *widget); static gint gtk_container_focus_tab (GtkContainer *container, ! GList *children, GtkDirectionType direction); static gint gtk_container_focus_up_down (GtkContainer *container, ! GList *children, GtkDirectionType direction); static gint gtk_container_focus_left_right (GtkContainer *container, ! GList *children, GtkDirectionType direction); static gint gtk_container_focus_move (GtkContainer *container, GList *children, --- 82,94 ---- static void gtk_container_real_set_focus_child (GtkContainer *container, GtkWidget *widget); static gint gtk_container_focus_tab (GtkContainer *container, ! GList **children, GtkDirectionType direction); static gint gtk_container_focus_up_down (GtkContainer *container, ! GList **children, GtkDirectionType direction); static gint gtk_container_focus_left_right (GtkContainer *container, ! GList **children, GtkDirectionType direction); static gint gtk_container_focus_move (GtkContainer *container, GList *children, *************** *** 1191,1196 **** --- 1191,1198 ---- g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE); + + return_val = FALSE; gtk_signal_emit (GTK_OBJECT (container), container_signals[FOCUS], *************** *** 1397,1402 **** --- 1399,1407 ---- !GTK_WIDGET_IS_SENSITIVE (container)) return FALSE; + if (GTK_WIDGET_HAS_FOCUS (container)) + return FALSE; + return_val = FALSE; if (GTK_WIDGET_CAN_FOCUS (container)) *************** *** 1440,1454 **** { case GTK_DIR_TAB_FORWARD: case GTK_DIR_TAB_BACKWARD: ! return_val = gtk_container_focus_tab (container, children, direction); break; case GTK_DIR_UP: case GTK_DIR_DOWN: ! return_val = gtk_container_focus_up_down (container, children, direction); break; case GTK_DIR_LEFT: case GTK_DIR_RIGHT: ! return_val = gtk_container_focus_left_right (container, children, direction); break; } --- 1445,1459 ---- { case GTK_DIR_TAB_FORWARD: case GTK_DIR_TAB_BACKWARD: ! return_val = gtk_container_focus_tab (container, &children, direction); break; case GTK_DIR_UP: case GTK_DIR_DOWN: ! return_val = gtk_container_focus_up_down (container, &children, direction); break; case GTK_DIR_LEFT: case GTK_DIR_RIGHT: ! return_val = gtk_container_focus_left_right (container, &children, direction); break; } *************** *** 1461,1467 **** static gint gtk_container_focus_tab (GtkContainer *container, ! GList *children, GtkDirectionType direction) { GtkWidget *child; --- 1466,1472 ---- static gint gtk_container_focus_tab (GtkContainer *container, ! GList **children, GtkDirectionType direction) { GtkWidget *child; *************** *** 1470,1482 **** guint length; guint i, j; ! length = g_list_length (children); /* sort the children in the y direction */ for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (children, j); child = tmp_list->data; while (j > 0) --- 1475,1487 ---- guint length; guint i, j; ! length = g_list_length (*children); /* sort the children in the y direction */ for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (*children, j); child = tmp_list->data; while (j > 0) *************** *** 1501,1507 **** for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (children, j); child = tmp_list->data; while (j > 0) --- 1506,1512 ---- for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (*children, j); child = tmp_list->data; while (j > 0) *************** *** 1525,1538 **** * of the children. */ if (direction == GTK_DIR_TAB_BACKWARD) ! children = g_list_reverse (children); ! return gtk_container_focus_move (container, children, direction); } static gint gtk_container_focus_up_down (GtkContainer *container, ! GList *children, GtkDirectionType direction) { GtkWidget *child; --- 1530,1543 ---- * of the children. */ if (direction == GTK_DIR_TAB_BACKWARD) ! *children = g_list_reverse (*children); ! return gtk_container_focus_move (container, *children, direction); } static gint gtk_container_focus_up_down (GtkContainer *container, ! GList **children, GtkDirectionType direction) { GtkWidget *child; *************** *** 1559,1571 **** focus_x = 0; } ! length = g_list_length (children); /* sort the children in the y direction */ for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (children, j); child = tmp_list->data; while (j > 0) --- 1564,1576 ---- focus_x = 0; } ! length = g_list_length (*children); /* sort the children in the y direction */ for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (*children, j); child = tmp_list->data; while (j > 0) *************** *** 1591,1597 **** for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (children, j); child = tmp_list->data; dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x; --- 1596,1602 ---- for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (*children, j); child = tmp_list->data; dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x; *************** *** 1621,1627 **** (direction == GTK_DIR_UP)) focus_x += focus_width; ! tmp_list = children; while (tmp_list) { child = tmp_list->data; --- 1626,1632 ---- (direction == GTK_DIR_UP)) focus_x += focus_width; ! tmp_list = *children; while (tmp_list) { child = tmp_list->data; *************** *** 1629,1648 **** dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x; if (((direction == GTK_DIR_DOWN) && (dist1 < 0)) || ((direction == GTK_DIR_UP) && (dist1 > 0))) ! tmp_list->data = NULL; ! tmp_list = tmp_list->next; } if (direction == GTK_DIR_UP) ! children = g_list_reverse (children); ! return gtk_container_focus_move (container, children, direction); } static gint gtk_container_focus_left_right (GtkContainer *container, ! GList *children, GtkDirectionType direction) { GtkWidget *child; --- 1634,1661 ---- dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x; if (((direction == GTK_DIR_DOWN) && (dist1 < 0)) || ((direction == GTK_DIR_UP) && (dist1 > 0))) ! { ! GList *tmp_list2; ! ! tmp_list2 = tmp_list; ! tmp_list = tmp_list->next; ! *children = g_list_remove_link (*children, tmp_list2); ! g_list_free_1 (tmp_list2); ! } ! else ! tmp_list = tmp_list->next; } if (direction == GTK_DIR_UP) ! *children = g_list_reverse (*children); ! return gtk_container_focus_move (container, *children, direction); } static gint gtk_container_focus_left_right (GtkContainer *container, ! GList **children, GtkDirectionType direction) { GtkWidget *child; *************** *** 1669,1681 **** focus_y = 0; } ! length = g_list_length (children); /* sort the children in the x direction */ for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (children, j); child = tmp_list->data; while (j > 0) --- 1682,1694 ---- focus_y = 0; } ! length = g_list_length (*children); /* sort the children in the x direction */ for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (*children, j); child = tmp_list->data; while (j > 0) *************** *** 1701,1707 **** for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (children, j); child = tmp_list->data; dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y; --- 1714,1720 ---- for (i = 1; i < length; i++) { j = i; ! tmp_list = g_list_nth (*children, j); child = tmp_list->data; dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y; *************** *** 1731,1737 **** (direction == GTK_DIR_LEFT)) focus_y += focus_height; ! tmp_list = children; while (tmp_list) { child = tmp_list->data; --- 1744,1750 ---- (direction == GTK_DIR_LEFT)) focus_y += focus_height; ! tmp_list = *children; while (tmp_list) { child = tmp_list->data; *************** *** 1739,1753 **** dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y; if (((direction == GTK_DIR_RIGHT) && (dist1 < 0)) || ((direction == GTK_DIR_LEFT) && (dist1 > 0))) ! tmp_list->data = NULL; ! tmp_list = tmp_list->next; } if (direction == GTK_DIR_LEFT) ! children = g_list_reverse (children); ! return gtk_container_focus_move (container, children, direction); } static gint --- 1752,1774 ---- dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y; if (((direction == GTK_DIR_RIGHT) && (dist1 < 0)) || ((direction == GTK_DIR_LEFT) && (dist1 > 0))) ! { ! GList *tmp_list2; ! ! tmp_list2 = tmp_list; ! tmp_list = tmp_list->next; ! *children = g_list_remove_link (*children, tmp_list2); ! g_list_free_1 (tmp_list2); ! } ! else ! tmp_list = tmp_list->next; } if (direction == GTK_DIR_LEFT) ! *children = g_list_reverse (*children); ! return gtk_container_focus_move (container, *children, direction); } static gint *************** *** 1766,1783 **** child = children->data; children = children->next; - if (!child) - continue; - if (focus_child) { if (focus_child == child) { focus_child = NULL; ! if (GTK_WIDGET_DRAWABLE (child) && ! GTK_IS_CONTAINER (child) && ! !GTK_WIDGET_HAS_FOCUS (child)) if (gtk_container_focus (GTK_CONTAINER (child), direction)) return TRUE; } --- 1787,1799 ---- child = children->data; children = children->next; if (focus_child) { if (focus_child == child) { focus_child = NULL; ! if (GTK_WIDGET_DRAWABLE (child) && GTK_IS_CONTAINER (child)) if (gtk_container_focus (GTK_CONTAINER (child), direction)) return TRUE; } diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkentry.c gtk+-1.2.10/gtk/gtkentry.c *** gtk+-1.2.10.orig/gtk/gtkentry.c Tue May 15 12:47:19 2001 --- gtk+-1.2.10/gtk/gtkentry.c Tue May 15 12:46:46 2001 *************** *** 1207,1214 **** } break; case GDK_Return: ! return_val = TRUE; ! gtk_widget_activate (widget); break; /* The next two keys should not be inserted literally. Any others ??? */ case GDK_Tab: --- 1207,1213 ---- } break; case GDK_Return: ! return_val = gtk_widget_activate (widget); break; /* The next two keys should not be inserted literally. Any others ??? */ case GDK_Tab: diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkhbbox.c gtk+-1.2.10/gtk/gtkhbbox.c *** gtk+-1.2.10.orig/gtk/gtkhbbox.c Wed Feb 24 02:34:45 1999 --- gtk+-1.2.10/gtk/gtkhbbox.c Tue May 15 12:46:46 2001 *************** *** 24,38 **** * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "gtkhbbox.h" static void gtk_hbutton_box_class_init (GtkHButtonBoxClass *klass); static void gtk_hbutton_box_init (GtkHButtonBox *box); ! static void gtk_hbutton_box_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_hbutton_box_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); static gint default_spacing = 30; static gint default_layout_style = GTK_BUTTONBOX_EDGE; --- 24,42 ---- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ + #include #include "gtkhbbox.h" + #include "gtkwindow.h" static void gtk_hbutton_box_class_init (GtkHButtonBoxClass *klass); static void gtk_hbutton_box_init (GtkHButtonBox *box); ! static void gtk_hbutton_box_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_hbutton_box_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); ! static gint gtk_hbutton_box_focus (GtkContainer *container, ! GtkDirectionType direction); static gint default_spacing = 30; static gint default_layout_style = GTK_BUTTONBOX_EDGE; *************** *** 66,76 **** gtk_hbutton_box_class_init (GtkHButtonBoxClass *class) { GtkWidgetClass *widget_class; ! widget_class = (GtkWidgetClass*) class; widget_class->size_request = gtk_hbutton_box_size_request; widget_class->size_allocate = gtk_hbutton_box_size_allocate; } static void --- 70,84 ---- gtk_hbutton_box_class_init (GtkHButtonBoxClass *class) { GtkWidgetClass *widget_class; + GtkContainerClass *container_class; ! widget_class = (GtkWidgetClass *) class; ! container_class = (GtkContainerClass *) class; widget_class->size_request = gtk_hbutton_box_size_request; widget_class->size_allocate = gtk_hbutton_box_size_allocate; + + container_class->focus = gtk_hbutton_box_focus; } static void *************** *** 280,282 **** --- 288,570 ---- } } + /* Utility function to give focus to a widget, or to do gtk_container_focus() if + * it is a container. + */ + static gint + grab_focus (GtkHButtonBox *hbbox, GtkWidget *widget, GtkDirectionType direction) + { + if (!widget) + return FALSE; + + if (!(GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget))) + return FALSE; + + if (GTK_IS_CONTAINER (widget)) + return gtk_container_focus (GTK_CONTAINER (widget), direction); + else if (GTK_WIDGET_CAN_FOCUS (widget)) + { + gtk_widget_grab_focus (widget); + return TRUE; + } + else + return FALSE; + } + + /* Starts trying to focus the box's widgets in sequence */ + static gint + try_focus (GtkHButtonBox *hbbox, GList *child, GtkDirectionType direction, + gboolean forwards, GtkPackType pack) + { + while (child) + { + GtkBoxChild *box_child; + GtkWidget *widget; + + box_child = child->data; + widget = box_child->widget; + + if (forwards) + child = child->next; + else + child = child->prev; + + if (box_child->pack != pack) + continue; + + if (grab_focus (hbbox, widget, direction)) + return TRUE; + } + + return FALSE; + } + + /* Returns the node that contains the specified child widget */ + static GList * + find_child (GtkHButtonBox *hbbox, GtkWidget *widget) + { + GList *children; + + for (children = GTK_BOX (hbbox)->children; children; children = children->next) + { + GtkBoxChild *child; + + child = children->data; + if (child->widget == widget) + return children; + } + + return NULL; + } + + /* Changes the focus in Tab or left/right directions */ + static gint + focus_along_children (GtkHButtonBox *hbbox, GtkDirectionType direction) + { + GtkContainer *container; + GtkBox *box; + + container = GTK_CONTAINER (hbbox); + box = GTK_BOX (hbbox); + + if (container->focus_child && GTK_WIDGET_IS_SENSITIVE (container->focus_child)) + { + GtkWidget *widget; + GList *child; + GtkBoxChild *box_child; + + widget = container->focus_child; + gtk_container_set_focus_child (container, NULL); + + g_assert (GTK_WIDGET_DRAWABLE (widget)); + + child = find_child (hbbox, widget); + g_assert (child != NULL); + + box_child = child->data; + + if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_RIGHT) + { + if (box_child->pack == GTK_PACK_START) + return (try_focus (hbbox, GTK_IS_CONTAINER (widget) ? child : child->next, + direction, TRUE, GTK_PACK_START) + || try_focus (hbbox, g_list_last (child), direction, FALSE, GTK_PACK_END)); + else if (box_child->pack == GTK_PACK_END) + return try_focus (hbbox, GTK_IS_CONTAINER (widget) ? child : child->prev, + direction, FALSE, GTK_PACK_END); + else + g_assert_not_reached (); + } + else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_LEFT) + { + if (box_child->pack == GTK_PACK_START) + return try_focus (hbbox, GTK_IS_CONTAINER (widget) ? child : child->prev, + direction, FALSE, GTK_PACK_START); + else if (box_child->pack == GTK_PACK_END) + return (try_focus (hbbox, GTK_IS_CONTAINER (widget) ? child : child->next, + direction, TRUE, GTK_PACK_END) + || try_focus (hbbox, g_list_last (child), direction, FALSE, GTK_PACK_START)); + } + else + g_assert_not_reached (); + } + else + { + if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_RIGHT) + return (try_focus (hbbox, box->children, direction, TRUE, GTK_PACK_START) + || try_focus (hbbox, g_list_last (box->children), direction, FALSE, GTK_PACK_END)); + else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_LEFT) + return (try_focus (hbbox, box->children, direction, TRUE, GTK_PACK_END) + || try_focus (hbbox, g_list_last (box->children), direction, FALSE, GTK_PACK_START)); + else + { + g_assert_not_reached (); + return FALSE; + } + } + + return FALSE; + } + + /* Finds a focusable child that is the most overlapping to the specified coordinates */ + static GtkWidget * + find_most_overlapping_focusable_child (GtkHButtonBox *hbbox, int x1, int x2) + { + GList *children; + GtkWidget *overlap; + gint bx1; + int max_overlap; + + overlap = NULL; + max_overlap = 0; + + gdk_window_get_origin (GTK_WIDGET (hbbox)->window, &bx1, NULL); + + for (children = GTK_BOX (hbbox)->children; children; children = children->next) + { + GtkBoxChild *box_child; + GtkWidget *widget; + int wx1, wx2; + int o; + + box_child = children->data; + widget = box_child->widget; + + if (!(GTK_WIDGET_DRAWABLE (widget) + && GTK_WIDGET_IS_SENSITIVE (widget) + && (GTK_IS_CONTAINER (widget) || GTK_WIDGET_CAN_FOCUS (widget)))) + continue; + + wx1 = bx1 + widget->allocation.x; + wx2 = wx1 + widget->allocation.width; + + if (x1 >= wx2 || x2 <= wx1) + continue; + + o = MIN (x2, wx2) - MAX (x1, wx1); + + g_assert (o >= 0); + + if (!overlap || o > max_overlap) + { + overlap = widget; + max_overlap = o; + } + } + + return overlap; + } + + /* Changes the focus in up/down directions */ + static gint + focus_outside (GtkHButtonBox *hbbox, GtkDirectionType direction) + { + GtkContainer *container; + GtkWidget *toplevel; + + container = GTK_CONTAINER (hbbox); + + if (container->focus_child) + { + if (GTK_IS_CONTAINER (container->focus_child)) + { + GtkWidget *focus_child; + + focus_child = container->focus_child; + gtk_container_set_focus_child (container, NULL); + + if (gtk_container_focus (GTK_CONTAINER (focus_child), direction)) + return TRUE; + } + else + return FALSE; /* pass focus on to something outside the HButtonBox */ + } + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (hbbox)); + + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *focus_widget; + GtkWidget *widget; + + focus_widget = GTK_WINDOW (toplevel)->focus_widget; + + if (focus_widget) + { + int x1, x2; + gint fx; + + x1 = focus_widget->allocation.x; + x2 = focus_widget->allocation.x + focus_widget->allocation.width; + + gdk_window_get_origin (focus_widget->parent->window, &fx, NULL); + + x1 += fx; + x2 += fx; + + widget = find_most_overlapping_focusable_child (hbbox, x1, x2); + } + else + { + gint tx; + + gdk_window_get_origin (toplevel->window, &tx, NULL); + widget = find_most_overlapping_focusable_child (hbbox, + tx, + tx + toplevel->allocation.width); + } + + return grab_focus (hbbox, widget, direction); + } + else + return FALSE; + } + + /* Focus handler for horizontal boxes */ + static gint + gtk_hbutton_box_focus (GtkContainer *container, GtkDirectionType direction) + { + GtkHButtonBox *hbbox; + + g_return_val_if_fail (container != NULL, FALSE); + g_return_val_if_fail (GTK_IS_HBUTTON_BOX (container), FALSE); + + hbbox = GTK_HBUTTON_BOX (container); + + switch (direction) + { + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_RIGHT: + case GTK_DIR_TAB_BACKWARD: + case GTK_DIR_LEFT: + return focus_along_children (hbbox, direction); + + case GTK_DIR_UP: + case GTK_DIR_DOWN: + return focus_outside (hbbox, direction); + + default: + g_assert_not_reached (); + return FALSE; + } + } diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkhbox.c gtk+-1.2.10/gtk/gtkhbox.c *** gtk+-1.2.10.orig/gtk/gtkhbox.c Wed Feb 24 02:34:47 1999 --- gtk+-1.2.10/gtk/gtkhbox.c Tue May 15 12:46:46 2001 *************** *** 21,38 **** * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with ! * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "gtkhbox.h" ! static void gtk_hbox_class_init (GtkHBoxClass *klass); ! static void gtk_hbox_init (GtkHBox *box); ! static void gtk_hbox_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_hbox_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); GtkType --- 21,42 ---- * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with ! * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ + #include #include "gtkhbox.h" + #include "gtkwindow.h" ! static void gtk_hbox_class_init (GtkHBoxClass *klass); ! static void gtk_hbox_init (GtkHBox *box); ! static void gtk_hbox_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_hbox_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); ! static gint gtk_hbox_focus (GtkContainer *container, ! GtkDirectionType direction); GtkType *************** *** 64,74 **** gtk_hbox_class_init (GtkHBoxClass *class) { GtkWidgetClass *widget_class; ! widget_class = (GtkWidgetClass*) class; widget_class->size_request = gtk_hbox_size_request; widget_class->size_allocate = gtk_hbox_size_allocate; } static void --- 68,82 ---- gtk_hbox_class_init (GtkHBoxClass *class) { GtkWidgetClass *widget_class; + GtkContainerClass *container_class; ! widget_class = (GtkWidgetClass *) class; ! container_class = (GtkContainerClass *) class; widget_class->size_request = gtk_hbox_size_request; widget_class->size_allocate = gtk_hbox_size_allocate; + + container_class->focus = gtk_hbox_focus; } static void *************** *** 325,329 **** --- 333,616 ---- x -= (child_width + box->spacing); } } + } + } + + /* Utility function to give focus to a widget, or to do gtk_container_focus() if + * it is a container. + */ + static gint + grab_focus (GtkHBox *hbox, GtkWidget *widget, GtkDirectionType direction) + { + if (!widget) + return FALSE; + + if (!(GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget))) + return FALSE; + + if (GTK_IS_CONTAINER (widget)) + return gtk_container_focus (GTK_CONTAINER (widget), direction); + else if (GTK_WIDGET_CAN_FOCUS (widget)) + { + gtk_widget_grab_focus (widget); + return TRUE; + } + else + return FALSE; + } + + /* Starts trying to focus the box's widgets in sequence */ + static gint + try_focus (GtkHBox *hbox, GList *child, GtkDirectionType direction, + gboolean forwards, GtkPackType pack) + { + while (child) + { + GtkBoxChild *box_child; + GtkWidget *widget; + + box_child = child->data; + widget = box_child->widget; + + if (forwards) + child = child->next; + else + child = child->prev; + + if (box_child->pack != pack) + continue; + + if (grab_focus (hbox, widget, direction)) + return TRUE; + } + + return FALSE; + } + + /* Returns the node that contains the specified child widget */ + static GList * + find_child (GtkHBox *hbox, GtkWidget *widget) + { + GList *children; + + for (children = GTK_BOX (hbox)->children; children; children = children->next) + { + GtkBoxChild *child; + + child = children->data; + if (child->widget == widget) + return children; + } + + return NULL; + } + + /* Changes the focus in Tab or left/right directions */ + static gint + focus_along_children (GtkHBox *hbox, GtkDirectionType direction) + { + GtkContainer *container; + GtkBox *box; + + container = GTK_CONTAINER (hbox); + box = GTK_BOX (hbox); + + if (container->focus_child) + { + GtkWidget *widget; + GList *child; + GtkBoxChild *box_child; + + widget = container->focus_child; + gtk_container_set_focus_child (container, NULL); + + g_assert (GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget)); + + child = find_child (hbox, widget); + g_assert (child != NULL); + + box_child = child->data; + + if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_RIGHT) + { + if (box_child->pack == GTK_PACK_START) + return (try_focus (hbox, GTK_IS_CONTAINER (widget) ? child : child->next, + direction, TRUE, GTK_PACK_START) + || try_focus (hbox, g_list_last (child), direction, FALSE, GTK_PACK_END)); + else if (box_child->pack == GTK_PACK_END) + return try_focus (hbox, GTK_IS_CONTAINER (widget) ? child : child->prev, + direction, FALSE, GTK_PACK_END); + else + g_assert_not_reached (); + } + else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_LEFT) + { + if (box_child->pack == GTK_PACK_START) + return try_focus (hbox, GTK_IS_CONTAINER (widget) ? child : child->prev, + direction, FALSE, GTK_PACK_START); + else if (box_child->pack == GTK_PACK_END) + return (try_focus (hbox, GTK_IS_CONTAINER (widget) ? child : child->next, + direction, TRUE, GTK_PACK_END) + || try_focus (hbox, g_list_last (child), direction, FALSE, GTK_PACK_START)); + } + else + g_assert_not_reached (); + } + else + { + if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_RIGHT) + return (try_focus (hbox, box->children, direction, TRUE, GTK_PACK_START) + || try_focus (hbox, g_list_last (box->children), direction, FALSE, GTK_PACK_END)); + else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_LEFT) + return (try_focus (hbox, box->children, direction, TRUE, GTK_PACK_END) + || try_focus (hbox, g_list_last (box->children), direction, FALSE, GTK_PACK_START)); + else + { + g_assert_not_reached (); + return FALSE; + } + } + + return FALSE; + } + + /* Finds a focusable child that is the most overlapping to the specified coordinates */ + static GtkWidget * + find_most_overlapping_focusable_child (GtkHBox *hbox, int x1, int x2) + { + GList *children; + GtkWidget *overlap; + gint bx1; + int max_overlap; + + overlap = NULL; + max_overlap = 0; + + gdk_window_get_origin (GTK_WIDGET (hbox)->window, &bx1, NULL); + + for (children = GTK_BOX (hbox)->children; children; children = children->next) + { + GtkBoxChild *box_child; + GtkWidget *widget; + int wx1, wx2; + int o; + + box_child = children->data; + widget = box_child->widget; + + if (!(GTK_WIDGET_DRAWABLE (widget) + && GTK_WIDGET_IS_SENSITIVE (widget) + && (GTK_IS_CONTAINER (widget) || GTK_WIDGET_CAN_FOCUS (widget)))) + continue; + + wx1 = bx1 + widget->allocation.x; + wx2 = wx1 + widget->allocation.width; + + if (x1 >= wx2 || x2 <= wx1) + continue; + + o = MIN (x2, wx2) - MAX (x1, wx1); + + g_assert (o >= 0); + + if (!overlap || o > max_overlap) + { + overlap = widget; + max_overlap = o; + } + } + + return overlap; + } + + /* Changes the focus in up/down directions */ + static gint + focus_outside (GtkHBox *hbox, GtkDirectionType direction) + { + GtkContainer *container; + GtkWidget *toplevel; + + container = GTK_CONTAINER (hbox); + + if (container->focus_child) + { + if (GTK_IS_CONTAINER (container->focus_child)) + { + GtkWidget *focus_child; + + focus_child = container->focus_child; + gtk_container_set_focus_child (container, NULL); + + if (gtk_container_focus (GTK_CONTAINER (focus_child), direction)) + return TRUE; + } + else + return FALSE; /* pass focus on to something outside the HBox */ + } + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (hbox)); + + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *focus_widget; + GtkWidget *widget; + + focus_widget = GTK_WINDOW (toplevel)->focus_widget; + + if (focus_widget) + { + int x1, x2; + gint fx; + + x1 = focus_widget->allocation.x; + x2 = focus_widget->allocation.x + focus_widget->allocation.width; + + gdk_window_get_origin (focus_widget->parent->window, &fx, NULL); + + x1 += fx; + x2 += fx; + + widget = find_most_overlapping_focusable_child (hbox, x1, x2); + } + else + { + gint tx; + + gdk_window_get_origin (toplevel->window, &tx, NULL); + widget = find_most_overlapping_focusable_child (hbox, tx, tx + toplevel->allocation.width); + } + + return grab_focus (hbox, widget, direction); + } + else + return FALSE; + } + + /* Focus handler for horizontal boxes */ + static gint + gtk_hbox_focus (GtkContainer *container, GtkDirectionType direction) + { + GtkHBox *hbox; + + g_return_val_if_fail (container != NULL, FALSE); + g_return_val_if_fail (GTK_IS_HBOX (container), FALSE); + + hbox = GTK_HBOX (container); + + switch (direction) + { + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_RIGHT: + case GTK_DIR_TAB_BACKWARD: + case GTK_DIR_LEFT: + return focus_along_children (hbox, direction); + + case GTK_DIR_UP: + case GTK_DIR_DOWN: + return focus_outside (hbox, direction); + + default: + g_assert_not_reached (); + return FALSE; } } diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtknotebook.c gtk+-1.2.10/gtk/gtknotebook.c *** gtk+-1.2.10.orig/gtk/gtknotebook.c Tue Jan 30 18:27:26 2001 --- gtk+-1.2.10/gtk/gtknotebook.c Tue May 15 12:46:46 2001 *************** *** 196,202 **** static void gtk_notebook_switch_page (GtkNotebook *notebook, GtkNotebookPage *page, gint page_num); ! static gint gtk_notebook_page_select (GtkNotebook *notebook); static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook, GList *new_child); static void gtk_notebook_menu_switch_page (GtkWidget *widget, --- 196,203 ---- static void gtk_notebook_switch_page (GtkNotebook *notebook, GtkNotebookPage *page, gint page_num); ! static gboolean gtk_notebook_page_select (GtkNotebook *notebook, ! gboolean unset_focus_child); static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook, GList *new_child); static void gtk_notebook_menu_switch_page (GtkWidget *widget, *************** *** 1049,1055 **** } } else if (event->button == 2) ! gtk_notebook_page_select (GTK_NOTEBOOK (widget)); else if (event->button == 3) gtk_notebook_switch_focus_tab (notebook, gtk_notebook_search_page (notebook, --- 1050,1056 ---- } } else if (event->button == 2) ! gtk_notebook_page_select (GTK_NOTEBOOK (widget), FALSE); else if (event->button == 3) gtk_notebook_switch_focus_tab (notebook, gtk_notebook_search_page (notebook, *************** *** 1077,1083 **** } } else if (event->button == 2) ! gtk_notebook_page_select (GTK_NOTEBOOK (widget)); else if (event->button == 3) gtk_notebook_switch_focus_tab (notebook, gtk_notebook_search_page (notebook, NULL, --- 1078,1084 ---- } } else if (event->button == 2) ! gtk_notebook_page_select (GTK_NOTEBOOK (widget), FALSE); else if (event->button == 3) gtk_notebook_switch_focus_tab (notebook, gtk_notebook_search_page (notebook, NULL, *************** *** 1285,1291 **** GdkEventKey *event) { GtkNotebook *notebook; - GtkDirectionType direction = 0; GList *list; g_return_val_if_fail (widget != NULL, FALSE); --- 1286,1291 ---- *************** *** 1299,1363 **** switch (event->keyval) { - case GDK_Up: - switch (notebook->tab_pos) - { - case GTK_POS_BOTTOM: - gtk_notebook_page_select (GTK_NOTEBOOK (widget)); - return TRUE; - case GTK_POS_TOP: - return FALSE; - default: - direction = GTK_DIR_UP; - break; - } - break; - case GDK_Left: - switch (notebook->tab_pos) - { - case GTK_POS_RIGHT: - gtk_notebook_page_select (GTK_NOTEBOOK (widget)); - return TRUE; - case GTK_POS_LEFT: - return FALSE; - default: - direction = GTK_DIR_LEFT; - break; - } - break; - case GDK_Down: - switch (notebook->tab_pos) - { - case GTK_POS_TOP: - gtk_notebook_page_select (GTK_NOTEBOOK (widget)); - return TRUE; - case GTK_POS_BOTTOM: - return FALSE; - default: - direction = GTK_DIR_DOWN; - break; - } - break; - case GDK_Right: - switch (notebook->tab_pos) - { - case GTK_POS_LEFT: - gtk_notebook_page_select (GTK_NOTEBOOK (widget)); - return TRUE; - case GTK_POS_RIGHT: - return FALSE; - default: - direction = GTK_DIR_RIGHT; - break; - } - break; - case GDK_Tab: - case GDK_ISO_Left_Tab: - if (event->state & GDK_SHIFT_MASK) - direction = GTK_DIR_TAB_BACKWARD; - else - direction = GTK_DIR_TAB_FORWARD; - break; case GDK_Home: list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE); if (list) --- 1299,1304 ---- *************** *** 1370,1381 **** return TRUE; case GDK_Return: case GDK_space: ! gtk_notebook_page_select (GTK_NOTEBOOK (widget)); return TRUE; default: ! return FALSE; } ! return gtk_container_focus (GTK_CONTAINER (widget), direction); } static gint --- 1311,1322 ---- return TRUE; case GDK_Return: case GDK_space: ! gtk_notebook_page_select (GTK_NOTEBOOK (widget), FALSE); return TRUE; default: ! break; } ! return FALSE; } static gint *************** *** 1623,1643 **** gtk_notebook_focus (GtkContainer *container, GtkDirectionType direction) { GtkNotebook *notebook; GtkNotebookPage *page = NULL; GtkNotebookPage *old_page = NULL; ! g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE); notebook = GTK_NOTEBOOK (container); if (!GTK_WIDGET_DRAWABLE (notebook) || !GTK_WIDGET_IS_SENSITIVE (container) || !notebook->children || !notebook->cur_page) return FALSE; ! if (!notebook->show_tabs) { if (GTK_WIDGET_DRAWABLE (notebook->cur_page->child) && --- 1564,1618 ---- gtk_notebook_focus (GtkContainer *container, GtkDirectionType direction) { + GtkWidget *old_focus_child; GtkNotebook *notebook; GtkNotebookPage *page = NULL; GtkNotebookPage *old_page = NULL; ! g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE); notebook = GTK_NOTEBOOK (container); + + old_focus_child = container->focus_child; if (!GTK_WIDGET_DRAWABLE (notebook) || !GTK_WIDGET_IS_SENSITIVE (container) || !notebook->children || !notebook->cur_page) return FALSE; ! ! if (GTK_WIDGET_HAS_FOCUS (container)) ! switch (direction) ! { ! case GTK_DIR_UP: ! if (notebook->tab_pos == GTK_POS_BOTTOM) ! return gtk_notebook_page_select (notebook, TRUE); ! else if (notebook->tab_pos == GTK_POS_TOP) ! return FALSE; ! break; ! case GTK_DIR_LEFT: ! if (notebook->tab_pos == GTK_POS_RIGHT) ! return gtk_notebook_page_select (notebook, TRUE); ! else if (notebook->tab_pos == GTK_POS_LEFT) ! return FALSE; ! break; ! case GTK_DIR_DOWN: ! if (notebook->tab_pos == GTK_POS_TOP) ! return gtk_notebook_page_select (notebook, TRUE); ! else if (notebook->tab_pos == GTK_POS_BOTTOM) ! return FALSE; ! break; ! case GTK_DIR_RIGHT: ! if (notebook->tab_pos == GTK_POS_LEFT) ! return gtk_notebook_page_select (notebook, TRUE); ! else if (notebook->tab_pos == GTK_POS_RIGHT) ! return FALSE; ! break; ! default: ! break; ! } ! if (!notebook->show_tabs) { if (GTK_WIDGET_DRAWABLE (notebook->cur_page->child) && *************** *** 1645,1657 **** { if (GTK_IS_CONTAINER (notebook->cur_page->child)) { ! if (gtk_container_focus ! (GTK_CONTAINER (notebook->cur_page->child), direction)) return TRUE; } else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child)) { ! if (!container->focus_child) { gtk_widget_grab_focus (notebook->cur_page->child); return TRUE; --- 1620,1632 ---- { if (GTK_IS_CONTAINER (notebook->cur_page->child)) { ! gtk_container_set_focus_child (container, NULL); ! if (gtk_container_focus (GTK_CONTAINER (notebook->cur_page->child), direction)) return TRUE; } else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child)) { ! if (!old_focus_child) { gtk_widget_grab_focus (notebook->cur_page->child); return TRUE; *************** *** 1659,1678 **** } } return FALSE; ! } if (notebook->focus_tab) old_page = notebook->focus_tab->data; ! if (container->focus_child && old_page && ! container->focus_child == old_page->child && notebook->child_has_focus) { ! if (GTK_WIDGET_DRAWABLE (container->focus_child)) { ! if (GTK_IS_CONTAINER (container->focus_child) && ! !GTK_WIDGET_HAS_FOCUS (container->focus_child)) { ! if (gtk_container_focus (GTK_CONTAINER (container->focus_child), direction)) return TRUE; } --- 1634,1653 ---- } } return FALSE; ! } if (notebook->focus_tab) old_page = notebook->focus_tab->data; ! if (old_focus_child && old_page && ! old_focus_child == old_page->child && notebook->child_has_focus) { ! if (GTK_WIDGET_DRAWABLE (old_focus_child)) { ! if (GTK_IS_CONTAINER (old_focus_child)) { ! gtk_container_set_focus_child (container, NULL); ! if (gtk_container_focus (GTK_CONTAINER (old_focus_child), direction)) return TRUE; } *************** *** 1706,1727 **** if (notebook->focus_tab) { ! if (!GTK_WIDGET_HAS_FOCUS (container)) ! gtk_widget_grab_focus (GTK_WIDGET (container)); page = notebook->focus_tab->data; if (GTK_WIDGET_MAPPED (page->tab_label)) ! gtk_notebook_focus_changed (notebook, old_page); else { gtk_notebook_pages_allocate (notebook, &(GTK_WIDGET (notebook)->allocation)); gtk_notebook_expose_tabs (notebook); } return TRUE; } gtk_notebook_focus_changed (notebook, old_page); return FALSE; } --- 1681,1706 ---- if (notebook->focus_tab) { ! gtk_widget_grab_focus (GTK_WIDGET (container)); page = notebook->focus_tab->data; if (GTK_WIDGET_MAPPED (page->tab_label)) ! { ! gtk_notebook_focus_changed (notebook, old_page); ! return TRUE; ! } else { gtk_notebook_pages_allocate (notebook, &(GTK_WIDGET (notebook)->allocation)); gtk_notebook_expose_tabs (notebook); } + return TRUE; } gtk_notebook_focus_changed (notebook, old_page); + return FALSE; } *************** *** 3337,3344 **** page_num); } ! static gint ! gtk_notebook_page_select (GtkNotebook *notebook) { GtkNotebookPage *page; --- 3316,3324 ---- page_num); } ! static gboolean ! gtk_notebook_page_select (GtkNotebook *notebook, ! gboolean reset_focus_child) { GtkNotebookPage *page; *************** *** 3355,3360 **** --- 3335,3345 ---- { if (GTK_IS_CONTAINER (page->child)) { + if (reset_focus_child) + { + /* maintain ::focus movement propagation invariants here */ + gtk_container_set_focus_child (GTK_CONTAINER (notebook), NULL); + } if (gtk_container_focus (GTK_CONTAINER (page->child), GTK_DIR_TAB_FORWARD)) return TRUE; diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkplug.c gtk+-1.2.10/gtk/gtkplug.c *** gtk+-1.2.10.orig/gtk/gtkplug.c Thu Mar 15 13:41:40 2001 --- gtk+-1.2.10/gtk/gtkplug.c Tue May 15 12:46:46 2001 *************** *** 229,236 **** } return_val = FALSE; ! if (window->focus_widget) ! return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event); #if 0 if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state)) --- 229,240 ---- } return_val = FALSE; ! if (window->focus_widget && ! window->focus_widget != widget && ! GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! { ! return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event); ! } #if 0 if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state)) *************** *** 244,252 **** case GDK_space: if (window->focus_widget) { ! gtk_widget_activate (window->focus_widget); ! return_val = TRUE; } break; case GDK_Return: case GDK_KP_Enter: --- 248,257 ---- case GDK_space: if (window->focus_widget) { ! if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! return_val = gtk_widget_activate (window->focus_widget); } + break; case GDK_Return: case GDK_KP_Enter: *************** *** 254,266 **** (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))) { ! gtk_widget_activate (window->default_widget); ! return_val = TRUE; } else if (window->focus_widget) { ! gtk_widget_activate (window->focus_widget); ! return_val = TRUE; } break; case GDK_Up: --- 259,269 ---- (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))) { ! return_val = gtk_widget_activate (window->default_widget); } else if (window->focus_widget) { ! return_val = gtk_widget_activate (window->focus_widget); } break; case GDK_Up: diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkvbbox.c gtk+-1.2.10/gtk/gtkvbbox.c *** gtk+-1.2.10.orig/gtk/gtkvbbox.c Wed Feb 24 02:36:53 1999 --- gtk+-1.2.10/gtk/gtkvbbox.c Tue May 15 12:46:46 2001 *************** *** 24,38 **** * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "gtkvbbox.h" static void gtk_vbutton_box_class_init (GtkVButtonBoxClass *klass); static void gtk_vbutton_box_init (GtkVButtonBox *box); ! static void gtk_vbutton_box_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_vbutton_box_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); static gint default_spacing = 10; static GtkButtonBoxStyle default_layout_style = GTK_BUTTONBOX_EDGE; --- 24,42 ---- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ + #include #include "gtkvbbox.h" + #include "gtkwindow.h" static void gtk_vbutton_box_class_init (GtkVButtonBoxClass *klass); static void gtk_vbutton_box_init (GtkVButtonBox *box); ! static void gtk_vbutton_box_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_vbutton_box_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); ! static gint gtk_vbutton_box_focus (GtkContainer *container, ! GtkDirectionType direction); static gint default_spacing = 10; static GtkButtonBoxStyle default_layout_style = GTK_BUTTONBOX_EDGE; *************** *** 66,76 **** gtk_vbutton_box_class_init (GtkVButtonBoxClass *class) { GtkWidgetClass *widget_class; ! widget_class = (GtkWidgetClass*) class; widget_class->size_request = gtk_vbutton_box_size_request; widget_class->size_allocate = gtk_vbutton_box_size_allocate; } static void --- 70,84 ---- gtk_vbutton_box_class_init (GtkVButtonBoxClass *class) { GtkWidgetClass *widget_class; + GtkContainerClass *container_class; ! widget_class = (GtkWidgetClass *) class; ! container_class = (GtkContainerClass *) class; widget_class->size_request = gtk_vbutton_box_size_request; widget_class->size_allocate = gtk_vbutton_box_size_allocate; + + container_class->focus = gtk_vbutton_box_focus; } static void *************** *** 283,286 **** } } ! --- 291,573 ---- } } ! /* Utility function to give focus to a widget, or to do gtk_container_focus() if ! * it is a container. ! */ ! static gint ! grab_focus (GtkVButtonBox *vbbox, GtkWidget *widget, GtkDirectionType direction) ! { ! if (!widget) ! return FALSE; ! ! if (!(GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget))) ! return FALSE; ! ! if (GTK_IS_CONTAINER (widget)) ! return gtk_container_focus (GTK_CONTAINER (widget), direction); ! else if (GTK_WIDGET_CAN_FOCUS (widget)) ! { ! gtk_widget_grab_focus (widget); ! return TRUE; ! } ! else ! return FALSE; ! } ! ! /* Starts trying to focus the box's widgets in sequence */ ! static gint ! try_focus (GtkVButtonBox *vbbox, GList *child, GtkDirectionType direction, ! gboolean forwards, GtkPackType pack) ! { ! while (child) ! { ! GtkBoxChild *box_child; ! GtkWidget *widget; ! ! box_child = child->data; ! widget = box_child->widget; ! ! if (forwards) ! child = child->next; ! else ! child = child->prev; ! ! if (box_child->pack != pack) ! continue; ! ! if (grab_focus (vbbox, widget, direction)) ! return TRUE; ! } ! ! return FALSE; ! } ! ! /* Returns the node that contains the specified child widget */ ! static GList * ! find_child (GtkVButtonBox *vbbox, GtkWidget *widget) ! { ! GList *children; ! ! for (children = GTK_BOX (vbbox)->children; children; children = children->next) ! { ! GtkBoxChild *child; ! ! child = children->data; ! if (child->widget == widget) ! return children; ! } ! ! return NULL; ! } ! ! /* Changes the focus in Tab or up/down directions */ ! static gint ! focus_along_children (GtkVButtonBox *vbbox, GtkDirectionType direction) ! { ! GtkContainer *container; ! GtkBox *box; ! ! container = GTK_CONTAINER (vbbox); ! box = GTK_BOX (vbbox); ! ! if (container->focus_child) ! { ! GtkWidget *widget; ! GList *child; ! GtkBoxChild *box_child; ! ! widget = container->focus_child; ! gtk_container_set_focus_child (container, NULL); ! ! g_assert (GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget)); ! ! child = find_child (vbbox, widget); ! g_assert (child != NULL); ! ! box_child = child->data; ! ! if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_DOWN) ! { ! if (box_child->pack == GTK_PACK_START) ! return (try_focus (vbbox, GTK_IS_CONTAINER (widget) ? child : child->next, ! direction, TRUE, GTK_PACK_START) ! || try_focus (vbbox, g_list_last (child), direction, FALSE, GTK_PACK_END)); ! else if (box_child->pack == GTK_PACK_END) ! return try_focus (vbbox, GTK_IS_CONTAINER (widget) ? child : child->prev, ! direction, FALSE, GTK_PACK_END); ! else ! g_assert_not_reached (); ! } ! else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_UP) ! { ! if (box_child->pack == GTK_PACK_START) ! return try_focus (vbbox, GTK_IS_CONTAINER (widget) ? child : child->prev, ! direction, FALSE, GTK_PACK_START); ! else if (box_child->pack == GTK_PACK_END) ! return (try_focus (vbbox, GTK_IS_CONTAINER (widget) ? child : child->next, ! direction, TRUE, GTK_PACK_END) ! || try_focus (vbbox, g_list_last (child), direction, FALSE, GTK_PACK_START)); ! } ! else ! g_assert_not_reached (); ! } ! else ! { ! if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_DOWN) ! return (try_focus (vbbox, box->children, direction, TRUE, GTK_PACK_START) ! || try_focus (vbbox, g_list_last (box->children), direction, FALSE, GTK_PACK_END)); ! else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_UP) ! return (try_focus (vbbox, box->children, direction, TRUE, GTK_PACK_END) ! || try_focus (vbbox, g_list_last (box->children), direction, FALSE, GTK_PACK_START)); ! else ! { ! g_assert_not_reached (); ! return FALSE; ! } ! } ! ! return FALSE; ! } ! ! /* Finds a focusable child that is the most overlapping to the specified coordinates */ ! static GtkWidget * ! find_most_overlapping_focusable_child (GtkVButtonBox *vbbox, int y1, int y2) ! { ! GList *children; ! GtkWidget *overlap; ! gint by1; ! int max_overlap; ! ! overlap = NULL; ! max_overlap = 0; ! ! gdk_window_get_origin (GTK_WIDGET (vbbox)->window, NULL, &by1); ! ! for (children = GTK_BOX (vbbox)->children; children; children = children->next) ! { ! GtkBoxChild *box_child; ! GtkWidget *widget; ! int wy1, wy2; ! int o; ! ! box_child = children->data; ! widget = box_child->widget; ! ! if (!(GTK_WIDGET_DRAWABLE (widget) ! && GTK_WIDGET_IS_SENSITIVE (widget) ! && (GTK_IS_CONTAINER (widget) || GTK_WIDGET_CAN_FOCUS (widget)))) ! continue; ! ! wy1 = by1 + widget->allocation.y; ! wy2 = wy1 + widget->allocation.height; ! ! if (y1 >= wy2 || y2 <= wy1) ! continue; ! ! o = MIN (y2, wy2) - MAX (y1, wy1); ! ! g_assert (o >= 0); ! ! if (!overlap || o > max_overlap) ! { ! overlap = widget; ! max_overlap = o; ! } ! } ! ! return overlap; ! } ! ! /* Changes the focus in left/right directions */ ! static gint ! focus_outside (GtkVButtonBox *vbbox, GtkDirectionType direction) ! { ! GtkContainer *container; ! GtkWidget *toplevel; ! ! container = GTK_CONTAINER (vbbox); ! ! if (container->focus_child) ! { ! if (GTK_IS_CONTAINER (container->focus_child)) ! { ! GtkWidget *focus_child; ! ! focus_child = container->focus_child; ! gtk_container_set_focus_child (container, NULL); ! ! if (gtk_container_focus (GTK_CONTAINER (focus_child), direction)) ! return TRUE; ! } ! else ! return FALSE; /* pass focus on to something outside the VButtonBox */ ! } ! ! toplevel = gtk_widget_get_toplevel (GTK_WIDGET (vbbox)); ! ! if (GTK_IS_WINDOW (toplevel)) ! { ! GtkWidget *focus_widget; ! GtkWidget *widget; ! ! focus_widget = GTK_WINDOW (toplevel)->focus_widget; ! ! if (focus_widget) ! { ! int y1, y2; ! gint fy; ! ! y1 = focus_widget->allocation.y; ! y2 = focus_widget->allocation.y + focus_widget->allocation.height; ! ! gdk_window_get_origin (focus_widget->parent->window, NULL, &fy); ! ! y1 += fy; ! y2 += fy; ! ! widget = find_most_overlapping_focusable_child (vbbox, y1, y2); ! } ! else ! { ! gint ty; ! ! gdk_window_get_origin (toplevel->window, NULL, &ty); ! widget = find_most_overlapping_focusable_child (vbbox, ! ty, ! ty + toplevel->allocation.height); ! } ! ! return grab_focus (vbbox, widget, direction); ! } ! else ! return FALSE; ! } ! ! /* Focus handler for vertical boxes */ ! static gint ! gtk_vbutton_box_focus (GtkContainer *container, GtkDirectionType direction) ! { ! GtkVButtonBox *vbbox; ! ! g_return_val_if_fail (container != NULL, FALSE); ! g_return_val_if_fail (GTK_IS_VBUTTON_BOX (container), FALSE); ! ! vbbox = GTK_VBUTTON_BOX (container); ! ! switch (direction) ! { ! case GTK_DIR_TAB_FORWARD: ! case GTK_DIR_DOWN: ! case GTK_DIR_TAB_BACKWARD: ! case GTK_DIR_UP: ! return focus_along_children (vbbox, direction); ! ! case GTK_DIR_RIGHT: ! case GTK_DIR_LEFT: ! return focus_outside (vbbox, direction); ! ! default: ! g_assert_not_reached (); ! return FALSE; ! } ! } diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkvbox.c gtk+-1.2.10/gtk/gtkvbox.c *** gtk+-1.2.10.orig/gtk/gtkvbox.c Wed Feb 24 02:36:55 1999 --- gtk+-1.2.10/gtk/gtkvbox.c Tue May 15 12:46:46 2001 *************** *** 21,38 **** * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with ! * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "gtkvbox.h" ! static void gtk_vbox_class_init (GtkVBoxClass *klass); ! static void gtk_vbox_init (GtkVBox *box); ! static void gtk_vbox_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_vbox_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); GtkType --- 21,42 ---- * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with ! * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ + #include #include "gtkvbox.h" + #include "gtkwindow.h" ! static void gtk_vbox_class_init (GtkVBoxClass *klass); ! static void gtk_vbox_init (GtkVBox *box); ! static void gtk_vbox_size_request (GtkWidget *widget, ! GtkRequisition *requisition); ! static void gtk_vbox_size_allocate (GtkWidget *widget, ! GtkAllocation *allocation); ! static gint gtk_vbox_focus (GtkContainer *container, ! GtkDirectionType direction); GtkType *************** *** 64,74 **** gtk_vbox_class_init (GtkVBoxClass *class) { GtkWidgetClass *widget_class; ! widget_class = (GtkWidgetClass*) class; widget_class->size_request = gtk_vbox_size_request; widget_class->size_allocate = gtk_vbox_size_allocate; } static void --- 68,82 ---- gtk_vbox_class_init (GtkVBoxClass *class) { GtkWidgetClass *widget_class; + GtkContainerClass *container_class; ! widget_class = (GtkWidgetClass *) class; ! container_class = (GtkContainerClass *) class; widget_class->size_request = gtk_vbox_size_request; widget_class->size_allocate = gtk_vbox_size_allocate; + + container_class->focus = gtk_vbox_focus; } static void *************** *** 323,327 **** --- 331,614 ---- y -= (child_height + box->spacing); } } + } + } + + /* Utility function to give focus to a widget, or to do gtk_container_focus() if + * it is a container. + */ + static gint + grab_focus (GtkVBox *vbox, GtkWidget *widget, GtkDirectionType direction) + { + if (!widget) + return FALSE; + + if (!(GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget))) + return FALSE; + + if (GTK_IS_CONTAINER (widget)) + return gtk_container_focus (GTK_CONTAINER (widget), direction); + else if (GTK_WIDGET_CAN_FOCUS (widget)) + { + gtk_widget_grab_focus (widget); + return TRUE; + } + else + return FALSE; + } + + /* Starts trying to focus the box's widgets in sequence */ + static gint + try_focus (GtkVBox *vbox, GList *child, GtkDirectionType direction, + gboolean forwards, GtkPackType pack) + { + while (child) + { + GtkBoxChild *box_child; + GtkWidget *widget; + + box_child = child->data; + widget = box_child->widget; + + if (forwards) + child = child->next; + else + child = child->prev; + + if (box_child->pack != pack) + continue; + + if (grab_focus (vbox, widget, direction)) + return TRUE; + } + + return FALSE; + } + + /* Returns the node that contains the specified child widget */ + static GList * + find_child (GtkVBox *vbox, GtkWidget *widget) + { + GList *children; + + for (children = GTK_BOX (vbox)->children; children; children = children->next) + { + GtkBoxChild *child; + + child = children->data; + if (child->widget == widget) + return children; + } + + return NULL; + } + + /* Changes the focus in Tab or up/down directions */ + static gint + focus_along_children (GtkVBox *vbox, GtkDirectionType direction) + { + GtkContainer *container; + GtkBox *box; + + container = GTK_CONTAINER (vbox); + box = GTK_BOX (vbox); + + if (container->focus_child) + { + GtkWidget *widget; + GList *child; + GtkBoxChild *box_child; + + widget = container->focus_child; + gtk_container_set_focus_child (container, NULL); + + g_assert (GTK_WIDGET_DRAWABLE (widget) && GTK_WIDGET_IS_SENSITIVE (widget)); + + child = find_child (vbox, widget); + g_assert (child != NULL); + + box_child = child->data; + + if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_DOWN) + { + if (box_child->pack == GTK_PACK_START) + return (try_focus (vbox, GTK_IS_CONTAINER (widget) ? child : child->next, + direction, TRUE, GTK_PACK_START) + || try_focus (vbox, g_list_last (child), direction, FALSE, GTK_PACK_END)); + else if (box_child->pack == GTK_PACK_END) + return try_focus (vbox, GTK_IS_CONTAINER (widget) ? child : child->prev, + direction, FALSE, GTK_PACK_END); + else + g_assert_not_reached (); + } + else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_UP) + { + if (box_child->pack == GTK_PACK_START) + return try_focus (vbox, GTK_IS_CONTAINER (widget) ? child : child->prev, + direction, FALSE, GTK_PACK_START); + else if (box_child->pack == GTK_PACK_END) + return (try_focus (vbox, GTK_IS_CONTAINER (widget) ? child : child->next, + direction, TRUE, GTK_PACK_END) + || try_focus (vbox, g_list_last (child), direction, FALSE, GTK_PACK_START)); + } + else + g_assert_not_reached (); + } + else + { + if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_DOWN) + return (try_focus (vbox, box->children, direction, TRUE, GTK_PACK_START) + || try_focus (vbox, g_list_last (box->children), direction, FALSE, GTK_PACK_END)); + else if (direction == GTK_DIR_TAB_BACKWARD || direction == GTK_DIR_UP) + return (try_focus (vbox, box->children, direction, TRUE, GTK_PACK_END) + || try_focus (vbox, g_list_last (box->children), direction, FALSE, GTK_PACK_START)); + else + { + g_assert_not_reached (); + return FALSE; + } + } + + return FALSE; + } + + /* Finds a focusable child that is the most overlapping to the specified coordinates */ + static GtkWidget * + find_most_overlapping_focusable_child (GtkVBox *vbox, int y1, int y2) + { + GList *children; + GtkWidget *overlap; + gint by1; + int max_overlap; + + overlap = NULL; + max_overlap = 0; + + gdk_window_get_origin (GTK_WIDGET (vbox)->window, NULL, &by1); + + for (children = GTK_BOX (vbox)->children; children; children = children->next) + { + GtkBoxChild *box_child; + GtkWidget *widget; + int wy1, wy2; + int o; + + box_child = children->data; + widget = box_child->widget; + + if (!(GTK_WIDGET_DRAWABLE (widget) + && GTK_WIDGET_IS_SENSITIVE (widget) + && (GTK_IS_CONTAINER (widget) || GTK_WIDGET_CAN_FOCUS (widget)))) + continue; + + wy1 = by1 + widget->allocation.y; + wy2 = wy1 + widget->allocation.height; + + if (y1 >= wy2 || y2 <= wy1) + continue; + + o = MIN (y2, wy2) - MAX (y1, wy1); + + g_assert (o >= 0); + + if (!overlap || o > max_overlap) + { + overlap = widget; + max_overlap = o; + } + } + + return overlap; + } + + /* Changes the focus in left/right directions */ + static gint + focus_outside (GtkVBox *vbox, GtkDirectionType direction) + { + GtkContainer *container; + GtkWidget *toplevel; + + container = GTK_CONTAINER (vbox); + + if (container->focus_child) + { + if (GTK_IS_CONTAINER (container->focus_child)) + { + GtkWidget *focus_child; + + focus_child = container->focus_child; + gtk_container_set_focus_child (container, NULL); + + if (gtk_container_focus (GTK_CONTAINER (focus_child), direction)) + return TRUE; + } + else + return FALSE; /* pass focus on to something outside the VBox */ + } + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (vbox)); + + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *focus_widget; + GtkWidget *widget; + + focus_widget = GTK_WINDOW (toplevel)->focus_widget; + + if (focus_widget) + { + int y1, y2; + gint fy; + + y1 = focus_widget->allocation.y; + y2 = focus_widget->allocation.y + focus_widget->allocation.height; + + gdk_window_get_origin (focus_widget->parent->window, NULL, &fy); + + y1 += fy; + y2 += fy; + + widget = find_most_overlapping_focusable_child (vbox, y1, y2); + } + else + { + gint ty; + + gdk_window_get_origin (toplevel->window, NULL, &ty); + widget = find_most_overlapping_focusable_child (vbox, ty, ty + toplevel->allocation.height); + } + + return grab_focus (vbox, widget, direction); + } + else + return FALSE; + } + + /* Focus handler for vertical boxes */ + static gint + gtk_vbox_focus (GtkContainer *container, GtkDirectionType direction) + { + GtkVBox *vbox; + + g_return_val_if_fail (container != NULL, FALSE); + g_return_val_if_fail (GTK_IS_VBOX (container), FALSE); + + vbox = GTK_VBOX (container); + + switch (direction) + { + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_DOWN: + case GTK_DIR_TAB_BACKWARD: + case GTK_DIR_UP: + return focus_along_children (vbox, direction); + + case GTK_DIR_RIGHT: + case GTK_DIR_LEFT: + return focus_outside (vbox, direction); + + default: + g_assert_not_reached (); + return FALSE; } } diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkwidget.c gtk+-1.2.10/gtk/gtkwidget.c *** gtk+-1.2.10.orig/gtk/gtkwidget.c Thu Mar 1 04:35:50 2001 --- gtk+-1.2.10/gtk/gtkwidget.c Tue May 15 12:46:46 2001 *************** *** 3113,3119 **** { widget = GTK_WINDOW (toplevel)->focus_widget; ! if (widget == focus_widget) { /* We call gtk_window_set_focus() here so that the * toplevel window can request the focus if necessary. --- 3113,3121 ---- { widget = GTK_WINDOW (toplevel)->focus_widget; ! if (widget == focus_widget && ! GTK_CONTAINER (toplevel)->focus_child && ! GTK_CONTAINER (focus_widget->parent)->focus_child == focus_widget) { /* We call gtk_window_set_focus() here so that the * toplevel window can request the focus if necessary. diff -Nrc -x *~ gtk+-1.2.10.orig/gtk/gtkwindow.c gtk+-1.2.10/gtk/gtkwindow.c *** gtk+-1.2.10.orig/gtk/gtkwindow.c Fri Mar 9 18:39:16 2001 --- gtk+-1.2.10/gtk/gtkwindow.c Tue May 15 12:47:00 2001 *************** *** 117,122 **** --- 117,124 ---- static gint gtk_window_client_event (GtkWidget *widget, GdkEventClient *event); static void gtk_window_check_resize (GtkContainer *container); + static gint gtk_window_focus (GtkContainer *container, + GtkDirectionType direction); static void gtk_window_real_set_focus (GtkWindow *window, GtkWidget *focus); *************** *** 251,256 **** --- 253,259 ---- widget_class->expose_event = gtk_window_expose; container_class->check_resize = gtk_window_check_resize; + container_class->focus = gtk_window_focus; klass->set_focus = gtk_window_real_set_focus; } *************** *** 533,539 **** if (window->focus_widget) { if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! gtk_widget_activate (window->focus_widget); return TRUE; } --- 536,543 ---- if (window->focus_widget) { if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! return gtk_widget_activate (window->focus_widget); ! return TRUE; } *************** *** 547,556 **** g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget)) ! { ! gtk_widget_activate (window->default_widget); ! return TRUE; ! } return FALSE; } --- 551,557 ---- g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget)) ! return gtk_widget_activate (window->default_widget); return FALSE; } *************** *** 985,991 **** break; case EnterNotify: case LeaveNotify: ! if (xev->xcrossing.detail != NotifyInferior && xev->xcrossing.focus && !window->window_has_focus) { window->window_has_pointer_focus = (xev->xany.type == EnterNotify) ? TRUE : FALSE; --- 986,993 ---- break; case EnterNotify: case LeaveNotify: ! if (gdk_window_get_parent (GTK_WIDGET (window)->window) == GDK_ROOT_PARENT () && ! xev->xcrossing.detail != NotifyInferior && xev->xcrossing.focus && !window->window_has_focus) { window->window_has_pointer_focus = (xev->xany.type == EnterNotify) ? TRUE : FALSE; *************** *** 1264,1271 **** if (window->focus_widget) { if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! gtk_widget_activate (window->focus_widget); ! handled = TRUE; } break; case GDK_Return: --- 1266,1272 ---- if (window->focus_widget) { if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! handled = gtk_widget_activate (window->focus_widget); } break; case GDK_Return: *************** *** 1273,1286 **** if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) && (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))) { ! gtk_widget_activate (window->default_widget); ! handled = TRUE; } else if (window->focus_widget) { if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! gtk_widget_activate (window->focus_widget); ! handled = TRUE; } break; case GDK_Up: --- 1274,1285 ---- if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) && (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))) { ! handled = gtk_widget_activate (window->default_widget); } else if (window->focus_widget) { if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget)) ! handled = gtk_widget_activate (window->focus_widget); } break; case GDK_Up: *************** *** 1522,1527 **** --- 1521,1580 ---- if (GTK_WIDGET_VISIBLE (container)) gtk_window_move_resize (window); + } + + static gint + gtk_window_focus (GtkContainer *container, + GtkDirectionType direction) + { + GtkBin *bin = GTK_BIN (container); + GtkWindow *window = GTK_WINDOW (container); + GtkWidget *old_focus_child = container->focus_child; + GtkWidget *parent; + + /* We need a special implementation here to deal properly with wrapping + * around in the tab chain without the danger of going into an + * infinite loop. + */ + if (old_focus_child) + { + if (GTK_IS_CONTAINER (old_focus_child) && + GTK_WIDGET_DRAWABLE (old_focus_child) && + GTK_WIDGET_IS_SENSITIVE (old_focus_child) && + gtk_container_focus (GTK_CONTAINER (old_focus_child), direction)) + return TRUE; + } + + if (window->focus_widget) + { + /* Wrapped off the end, clear the focus setting for the toplpevel */ + parent = window->focus_widget->parent; + while (parent) + { + gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL); + parent = GTK_WIDGET (parent)->parent; + } + + gtk_window_set_focus (GTK_WINDOW (container), NULL); + } + + /* Now try to focus the first widget in the window */ + if (bin->child && GTK_WIDGET_DRAWABLE (bin->child) && + GTK_WIDGET_IS_SENSITIVE (bin->child)) + { + if (GTK_IS_CONTAINER (bin->child)) + { + if (gtk_container_focus (GTK_CONTAINER (bin->child), direction)) + return TRUE; + } + else if (GTK_WIDGET_CAN_FOCUS (bin->child)) + { + gtk_widget_grab_focus (bin->child); + return TRUE; + } + } + + return FALSE; } static void