110 lines
3.4 KiB
Diff
110 lines
3.4 KiB
Diff
diff --git a/gtk/gtkviewport.c b/gtk/gtkviewport.c
|
|
index e564b9af5..24dd9f099 100644
|
|
--- a/gtk/gtkviewport.c
|
|
+++ b/gtk/gtkviewport.c
|
|
@@ -26,6 +26,7 @@
|
|
|
|
#include "config.h"
|
|
#include "gtkviewport.h"
|
|
+#include "gtkwindow.h"
|
|
#include "gtkintl.h"
|
|
#include "gtkmarshalers.h"
|
|
#include "gtkprivate.h"
|
|
@@ -87,6 +88,8 @@ static void gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
|
|
gpointer data);
|
|
static void gtk_viewport_style_set (GtkWidget *widget,
|
|
GtkStyle *previous_style);
|
|
+static void gtk_viewport_set_focus_child (GtkContainer *container,
|
|
+ GtkWidget *child);
|
|
|
|
G_DEFINE_TYPE (GtkViewport, gtk_viewport, GTK_TYPE_BIN)
|
|
|
|
@@ -114,8 +117,9 @@ gtk_viewport_class_init (GtkViewportClass *class)
|
|
widget_class->size_request = gtk_viewport_size_request;
|
|
widget_class->size_allocate = gtk_viewport_size_allocate;
|
|
widget_class->style_set = gtk_viewport_style_set;
|
|
-
|
|
+
|
|
container_class->add = gtk_viewport_add;
|
|
+ container_class->set_focus_child = gtk_viewport_set_focus_child;
|
|
|
|
class->set_scroll_adjustments = gtk_viewport_set_scroll_adjustments;
|
|
|
|
@@ -758,6 +762,76 @@ gtk_viewport_add (GtkContainer *container,
|
|
GTK_CONTAINER_CLASS (gtk_viewport_parent_class)->add (container, child);
|
|
}
|
|
|
|
+static gboolean
|
|
+set_focus_child_cb (gpointer data)
|
|
+{
|
|
+ GtkWidget *widget;
|
|
+ GtkViewport *viewport;
|
|
+ GtkWidget *toplevel;
|
|
+ GtkWidget *focus;
|
|
+ GtkAdjustment *adj;
|
|
+ int x, y;
|
|
+ GtkAllocation widget_alloc;
|
|
+ GtkAllocation focus_alloc;
|
|
+ gdouble value;
|
|
+
|
|
+ widget = (GtkWidget *)data;
|
|
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
+
|
|
+ toplevel = gtk_widget_get_toplevel (widget);
|
|
+ g_return_val_if_fail (GTK_IS_WIDGET (toplevel), FALSE);
|
|
+
|
|
+ focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
|
|
+ if (focus == NULL)
|
|
+ return FALSE;
|
|
+
|
|
+ viewport = GTK_VIEWPORT (widget);
|
|
+
|
|
+ gtk_widget_get_allocation (focus, &focus_alloc);
|
|
+ gtk_widget_get_allocation (widget, &widget_alloc);
|
|
+ gtk_widget_translate_coordinates (focus, widget, 0, 0, &x, &y);
|
|
+
|
|
+ /* Do we need to move vertically? */
|
|
+ if (y + focus_alloc.height >= widget_alloc.height)
|
|
+ {
|
|
+ adj = gtk_viewport_get_vadjustment (viewport);
|
|
+ value = gtk_adjustment_get_value (adj) + (y + focus_alloc.height - widget_alloc.height);
|
|
+ gtk_adjustment_set_value (adj, value);
|
|
+ }
|
|
+ else if (y <= widget_alloc.y)
|
|
+ {
|
|
+ adj = gtk_viewport_get_vadjustment (viewport);
|
|
+ value = gtk_adjustment_get_value (adj) - (widget_alloc.y - y);
|
|
+ gtk_adjustment_set_value (adj, value);
|
|
+ }
|
|
+
|
|
+ /* Do we need to move horizontally? */
|
|
+ if (x + focus_alloc.width >= widget_alloc.width)
|
|
+ {
|
|
+ adj = gtk_viewport_get_hadjustment (viewport);
|
|
+ value = gtk_adjustment_get_value (adj) + (x + focus_alloc.width - widget_alloc.width);
|
|
+ gtk_adjustment_set_value (adj, value);
|
|
+ }
|
|
+ else if (x <= widget_alloc.x)
|
|
+ {
|
|
+ adj = gtk_viewport_get_hadjustment (viewport);
|
|
+ value = gtk_adjustment_get_value (adj) - (widget_alloc.x - x);
|
|
+ gtk_adjustment_set_value (adj, value);
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_viewport_set_focus_child (GtkContainer *container,
|
|
+ GtkWidget *child)
|
|
+{
|
|
+ if (child == NULL)
|
|
+ return;
|
|
+
|
|
+ g_idle_add (set_focus_child_cb, container);
|
|
+}
|
|
+
|
|
static void
|
|
gtk_viewport_size_request (GtkWidget *widget,
|
|
GtkRequisition *requisition)
|