Fix interaction of borders/background and scrolling

StBoxLayout: Make consistent that the area scrolled and clipped
to is the content area (excluding borders and padding.) Translate
back appropriately when chaining up so that the parent background
is drawn at the right place and picking on the box (if it's reactive)
picks at the right place on the screen.

clip-to-allocation is removed from StScrollView since it's just
not right - if the child has any non-moving elements, like headers or
borders, it will need to set a narrower clip. And even if the entire
child scrolls, we want to clip to an arrow that excludes the scrollbars.

https://bugzilla.gnome.org/show_bug.cgi?id=595997
This commit is contained in:
Owen W. Taylor 2009-09-21 19:11:09 -04:00
parent 76443e91cd
commit 4057cfaa17
3 changed files with 106 additions and 41 deletions

View File

@ -924,15 +924,12 @@ static void
st_box_layout_paint (ClutterActor *actor) st_box_layout_paint (ClutterActor *actor)
{ {
StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv; StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv;
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
GList *l; GList *l;
gdouble x, y; gdouble x, y;
ClutterActorBox child_b; ClutterActorBox child_box;
ClutterActorBox box_b; ClutterActorBox allocation_box;
ClutterActorBox content_box;
CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->paint (actor);
if (priv->children == NULL)
return;
if (priv->hadjustment) if (priv->hadjustment)
x = st_adjustment_get_value (priv->hadjustment); x = st_adjustment_get_value (priv->hadjustment);
@ -944,11 +941,40 @@ st_box_layout_paint (ClutterActor *actor)
else else
y = 0; y = 0;
clutter_actor_get_allocation_box (actor, &box_b); /* If we are translated, then we need to translate back before chaining
box_b.x2 = (box_b.x2 - box_b.x1) + x; * up or the background and borders will be drawn in the wrong place */
box_b.x1 = x; if (x != 0 || y != 0)
box_b.y2 = (box_b.y2 - box_b.y1) + y; {
box_b.y1 = y; cogl_push_matrix ();
cogl_translate ((int)x, (int)y, 0);
}
CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->paint (actor);
if (x != 0 || y != 0)
{
cogl_pop_matrix ();
}
if (priv->children == NULL)
return;
clutter_actor_get_allocation_box (actor, &allocation_box);
st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);
content_box.x1 += x;
content_box.y1 += y;
content_box.x2 += x;
content_box.y2 += y;
/* The content area forms the viewport into the scrolled contents, while
* the borders and background stay in place; after drawing the borders and
* background, we clip to the content area */
if (priv->hadjustment || priv->vadjustment)
cogl_clip_push ((int)content_box.x1,
(int)content_box.y1,
(int)content_box.x2 - (int)content_box.x1,
(int)content_box.y2 - (int)content_box.y1);
for (l = priv->children; l; l = g_list_next (l)) for (l = priv->children; l; l = g_list_next (l))
{ {
@ -957,16 +983,19 @@ st_box_layout_paint (ClutterActor *actor)
if (!CLUTTER_ACTOR_IS_VISIBLE (child)) if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue; continue;
clutter_actor_get_allocation_box (child, &child_b); clutter_actor_get_allocation_box (child, &child_box);
if ((child_b.x1 < box_b.x2) && if ((child_box.x1 < content_box.x2) &&
(child_b.x2 > box_b.x1) && (child_box.x2 > content_box.x1) &&
(child_b.y1 < box_b.y2) && (child_box.y1 < content_box.y2) &&
(child_b.y2 > box_b.y1)) (child_box.y2 > content_box.y1))
{ {
clutter_actor_paint (child); clutter_actor_paint (child);
} }
} }
if (priv->hadjustment || priv->vadjustment)
cogl_clip_pop ();
} }
static void static void
@ -974,15 +1003,12 @@ st_box_layout_pick (ClutterActor *actor,
const ClutterColor *color) const ClutterColor *color)
{ {
StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv; StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv;
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
GList *l; GList *l;
gdouble x, y; gdouble x, y;
ClutterActorBox child_b; ClutterActorBox child_box;
ClutterActorBox box_b; ClutterActorBox allocation_box;
ClutterActorBox content_box;
CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor, color);
if (priv->children == NULL)
return;
if (priv->hadjustment) if (priv->hadjustment)
x = st_adjustment_get_value (priv->hadjustment); x = st_adjustment_get_value (priv->hadjustment);
@ -994,11 +1020,35 @@ st_box_layout_pick (ClutterActor *actor,
else else
y = 0; y = 0;
clutter_actor_get_allocation_box (actor, &box_b); if (x != 0 || y != 0)
box_b.x2 = (box_b.x2 - box_b.x1) + x; {
box_b.x1 = x; cogl_push_matrix ();
box_b.y2 = (box_b.y2 - box_b.y1) + y; cogl_translate ((int)x, (int)y, 0);
box_b.y1 = y; }
CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor, color);
if (x != 0 || y != 0)
{
cogl_pop_matrix ();
}
if (priv->children == NULL)
return;
clutter_actor_get_allocation_box (actor, &allocation_box);
st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);
content_box.x1 += x;
content_box.y1 += y;
content_box.x2 += x;
content_box.y2 += y;
if (priv->hadjustment || priv->vadjustment)
cogl_clip_push ((int)content_box.x1,
(int)content_box.y1,
(int)content_box.x2 - (int)content_box.x1,
(int)content_box.y2 - (int)content_box.y1);
for (l = priv->children; l; l = g_list_next (l)) for (l = priv->children; l; l = g_list_next (l))
{ {
@ -1007,16 +1057,19 @@ st_box_layout_pick (ClutterActor *actor,
if (!CLUTTER_ACTOR_IS_VISIBLE (child)) if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue; continue;
clutter_actor_get_allocation_box (child, &child_b); clutter_actor_get_allocation_box (child, &child_box);
if ((child_b.x1 < box_b.x2) if ((child_box.x1 < content_box.x2) &&
&& (child_b.x2 > box_b.x1) (child_box.x2 > content_box.x1) &&
&& (child_b.y1 < box_b.y2) (child_box.y1 < content_box.y2) &&
&& (child_b.y2 > box_b.y1)) (child_box.y2 > content_box.y1))
{ {
clutter_actor_paint (child); clutter_actor_paint (child);
} }
} }
if (priv->hadjustment || priv->vadjustment)
cogl_clip_pop ();
} }
static void static void

View File

@ -590,8 +590,7 @@ st_scroll_view_init (StScrollView *self)
/* mouse scroll is enabled by default, so we also need to be reactive */ /* mouse scroll is enabled by default, so we also need to be reactive */
priv->mouse_scroll = TRUE; priv->mouse_scroll = TRUE;
g_object_set (G_OBJECT (self), "reactive", TRUE, "clip-to-allocation", TRUE, g_object_set (G_OBJECT (self), "reactive", TRUE, NULL);
NULL);
} }
static void static void

View File

@ -8,11 +8,17 @@ const UI = imports.testcommon.ui;
UI.init(); UI.init();
let stage = Clutter.Stage.get_default(); let stage = Clutter.Stage.get_default();
let v = new St.ScrollView({}); let vbox = new St.BoxLayout({ vertical: true,
stage.add_actor(v); width: stage.width,
height: stage.height,
style: "padding: 10px;" });
stage.add_actor(vbox);
let v = new St.ScrollView();
vbox.add(v, { expand: true });
let b = new St.BoxLayout({ vertical: true, let b = new St.BoxLayout({ vertical: true,
width: stage.width, style: "border: 2px solid #880000; border-radius: 10px; padding: 0px 5px;" });
height: stage.height });
v.add_actor(b); v.add_actor(b);
let cc_a = "a".charCodeAt(0); let cc_a = "a".charCodeAt(0);
@ -20,9 +26,16 @@ let s = "";
for (let i = 0; i < 26 * 3; i++) { for (let i = 0; i < 26 * 3; i++) {
s += String.fromCharCode(cc_a + i % 26); s += String.fromCharCode(cc_a + i % 26);
let t = new St.Label({ "text": s}); let t = new St.Label({ text: s,
reactive: true });
let line = i + 1;
t.connect('button-press-event',
function() {
log("Click on line " + line);
});
b.add(t); b.add(t);
} }
stage.show(); stage.show();
Clutter.main(); Clutter.main();
stage.destroy();