163 lines
5.1 KiB
Diff
163 lines
5.1 KiB
Diff
--- gtk+-2.6.4/gtk/gtkscrolledwindow.c 2004-08-09 19:59:52.000000000 +0300
|
|
+++ gtk+-2.6.4/gtk/gtkscrolledwindow.c 2005-04-06 16:19:37.898776872 +0300
|
|
@@ -289,6 +289,13 @@
|
|
DEFAULT_SCROLLBAR_SPACING,
|
|
G_PARAM_READABLE));
|
|
|
|
+ gtk_widget_class_install_style_property (widget_class,
|
|
+ g_param_spec_boolean ("scrollbar_dislocation",
|
|
+ P_("Scrollbar dislocation"),
|
|
+ P_("Flag for having scrollbar at the outer border or container padding instead of at the inner border"),
|
|
+ FALSE,
|
|
+ G_PARAM_READABLE));
|
|
+
|
|
signals[SCROLL_CHILD] =
|
|
g_signal_new ("scroll_child",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
@@ -1062,6 +1069,73 @@
|
|
}
|
|
}
|
|
|
|
+static gdouble
|
|
+gtk_scrolled_window_get_focus_movement (GtkScrolledWindow *scrolled_window)
|
|
+{
|
|
+ GtkWidget *focus_child;
|
|
+ GtkRange *range;
|
|
+ GtkAdjustment *adj;
|
|
+ gdouble value, new_value;
|
|
+ gint x, y;
|
|
+
|
|
+ focus_child = GTK_CONTAINER(scrolled_window)->focus_child;
|
|
+ if (focus_child == NULL)
|
|
+ return 0;
|
|
+
|
|
+ while (GTK_IS_CONTAINER (focus_child) &&
|
|
+ GTK_CONTAINER (focus_child)->focus_child)
|
|
+ {
|
|
+ focus_child = GTK_CONTAINER (focus_child)->focus_child;
|
|
+ }
|
|
+
|
|
+ range = GTK_RANGE (scrolled_window->vscrollbar);
|
|
+ adj = range->adjustment;
|
|
+ value = gtk_adjustment_get_value (adj);
|
|
+
|
|
+ gtk_widget_translate_coordinates (focus_child->parent,
|
|
+ GTK_WIDGET(scrolled_window),
|
|
+ focus_child->allocation.x,
|
|
+ focus_child->allocation.y, &x, &y);
|
|
+
|
|
+ if (y < 0)
|
|
+ {
|
|
+ /* scroll up */
|
|
+ new_value = value + y;
|
|
+ if (new_value < adj->lower)
|
|
+ new_value = adj->lower;
|
|
+ }
|
|
+ else if (y + focus_child->allocation.height > adj->page_size)
|
|
+ {
|
|
+ /* scroll down */
|
|
+ new_value = value + y + focus_child->allocation.height - adj->page_size;
|
|
+ if (new_value > adj->upper - adj->page_size)
|
|
+ new_value = adj->upper - adj->page_size;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ new_value = value;
|
|
+ }
|
|
+
|
|
+ return new_value - value;
|
|
+}
|
|
+
|
|
+static void
|
|
+gtk_scrolled_window_scroll_to_focus (GtkScrolledWindow *scrolled_window)
|
|
+{
|
|
+ GtkAdjustment *adj;
|
|
+ gdouble diff;
|
|
+
|
|
+ diff = gtk_scrolled_window_get_focus_movement (scrolled_window);
|
|
+ if (diff != 0)
|
|
+ {
|
|
+ adj = GTK_RANGE (scrolled_window->vscrollbar)->adjustment;
|
|
+
|
|
+ gtk_adjustment_set_value (adj, gtk_adjustment_get_value (adj) + diff);
|
|
+ gtk_scrolled_window_set_vadjustment (scrolled_window,
|
|
+ GTK_ADJUSTMENT (adj));
|
|
+ }
|
|
+}
|
|
+
|
|
static void
|
|
gtk_scrolled_window_size_allocate (GtkWidget *widget,
|
|
GtkAllocation *allocation)
|
|
@@ -1071,17 +1145,32 @@
|
|
GtkAllocation relative_allocation;
|
|
GtkAllocation child_allocation;
|
|
gint scrollbar_spacing;
|
|
-
|
|
+ gboolean is_focus_visible, dislocate;
|
|
+ gint dislocation;
|
|
+
|
|
g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
|
|
g_return_if_fail (allocation != NULL);
|
|
|
|
scrolled_window = GTK_SCROLLED_WINDOW (widget);
|
|
bin = GTK_BIN (scrolled_window);
|
|
|
|
+ is_focus_visible =
|
|
+ gtk_scrolled_window_get_focus_movement (scrolled_window) == 0;
|
|
+
|
|
scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window);
|
|
|
|
widget->allocation = *allocation;
|
|
|
|
+ /* See how much scrollbar needs be "dislocated" (to get it to the other
|
|
+ * edge of the border). Does not apply to all occasions. */
|
|
+ gtk_widget_style_get (GTK_WIDGET (scrolled_window),
|
|
+ "scrollbar_dislocation", &dislocate,
|
|
+ NULL);
|
|
+ if (dislocate)
|
|
+ dislocation = GTK_CONTAINER (scrolled_window)->border_width;
|
|
+ else
|
|
+ dislocation = 0;
|
|
+
|
|
if (scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
|
|
scrolled_window->hscrollbar_visible = TRUE;
|
|
else if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER)
|
|
@@ -1150,10 +1239,12 @@
|
|
child_allocation.y = (relative_allocation.y +
|
|
relative_allocation.height +
|
|
scrollbar_spacing +
|
|
+ dislocation +
|
|
(scrolled_window->shadow_type == GTK_SHADOW_NONE ?
|
|
0 : widget->style->ythickness));
|
|
else
|
|
- child_allocation.y = GTK_CONTAINER (scrolled_window)->border_width;
|
|
+ child_allocation.y = GTK_CONTAINER (scrolled_window)->border_width -
|
|
+ dislocation;
|
|
|
|
child_allocation.width = relative_allocation.width;
|
|
child_allocation.height = hscrollbar_requisition.height;
|
|
@@ -1189,10 +1280,12 @@
|
|
child_allocation.x = (relative_allocation.x +
|
|
relative_allocation.width +
|
|
scrollbar_spacing +
|
|
+ dislocation +
|
|
(scrolled_window->shadow_type == GTK_SHADOW_NONE ?
|
|
0 : widget->style->xthickness));
|
|
else
|
|
- child_allocation.x = GTK_CONTAINER (scrolled_window)->border_width;
|
|
+ child_allocation.x = GTK_CONTAINER (scrolled_window)->border_width -
|
|
+ dislocation;
|
|
|
|
child_allocation.y = relative_allocation.y;
|
|
child_allocation.width = vscrollbar_requisition.width;
|
|
@@ -1207,6 +1300,9 @@
|
|
}
|
|
|
|
gtk_widget_size_allocate (scrolled_window->vscrollbar, &child_allocation);
|
|
+
|
|
+ if (is_focus_visible)
|
|
+ gtk_scrolled_window_scroll_to_focus (scrolled_window);
|
|
}
|
|
else if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar))
|
|
gtk_widget_hide (scrolled_window->vscrollbar);
|