Xamarin Public Jenkins (auto-signing) 4edc784e8b Imported Upstream version 6.6.0.129
Former-commit-id: 5252f8cfe37b84003acc4bfe0fa11691f0daf9fd
2019-10-17 09:04:47 +00:00

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)