boxPointer: Use the anchor point to fix problems with allocations
Instead of setting the x/y position of the box pointer, which results in a long change of workarounds for limitations of the Clutter layout system, set the anchor point instead, which takes the positioning out of the layout system. The position is computed as a combination of the position computed from the allocation and the box pointer's size, and an offset that we tween when animating showing and hiding the box pointer. https://bugzilla.gnome.org/show_bug.cgi?id=645744
This commit is contained in:
parent
bc48bd5f4a
commit
22c22e0d7a
@ -41,76 +41,76 @@ BoxPointer.prototype = {
|
|||||||
this._border.connect('repaint', Lang.bind(this, this._drawBorder));
|
this._border.connect('repaint', Lang.bind(this, this._drawBorder));
|
||||||
this._container.add_actor(this._border);
|
this._container.add_actor(this._border);
|
||||||
this.bin.raise(this._border);
|
this.bin.raise(this._border);
|
||||||
|
this._xOffset = 0;
|
||||||
|
this._yOffset = 0;
|
||||||
|
this._xPosition = 0;
|
||||||
|
this._yPosition = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function(animate, onComplete) {
|
show: function(animate, onComplete) {
|
||||||
let x = this.actor.x;
|
|
||||||
let y = this.actor.y;
|
|
||||||
let themeNode = this.actor.get_theme_node();
|
let themeNode = this.actor.get_theme_node();
|
||||||
let rise = themeNode.get_length('-arrow-rise');
|
let rise = themeNode.get_length('-arrow-rise');
|
||||||
|
|
||||||
this.actor.opacity = 0;
|
this.opacity = 0;
|
||||||
this.actor.show();
|
this.actor.show();
|
||||||
|
|
||||||
if (animate) {
|
if (animate) {
|
||||||
switch (this._arrowSide) {
|
switch (this._arrowSide) {
|
||||||
case St.Side.TOP:
|
case St.Side.TOP:
|
||||||
this.actor.y -= rise;
|
this.yOffset = -rise;
|
||||||
break;
|
break;
|
||||||
case St.Side.BOTTOM:
|
case St.Side.BOTTOM:
|
||||||
this.actor.y += rise;
|
this.yOffset = rise;
|
||||||
break;
|
break;
|
||||||
case St.Side.LEFT:
|
case St.Side.LEFT:
|
||||||
this.actor.x -= rise;
|
this.xOffset = -rise;
|
||||||
break;
|
break;
|
||||||
case St.Side.RIGHT:
|
case St.Side.RIGHT:
|
||||||
this.actor.x += rise;
|
this.xOffset = rise;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tweener.addTween(this.actor, { opacity: 255,
|
Tweener.addTween(this, { opacity: 255,
|
||||||
x: x,
|
xOffset: 0,
|
||||||
y: y,
|
yOffset: 0,
|
||||||
transition: "linear",
|
transition: "linear",
|
||||||
onComplete: onComplete,
|
onComplete: onComplete,
|
||||||
time: POPUP_ANIMATION_TIME });
|
time: POPUP_ANIMATION_TIME });
|
||||||
},
|
},
|
||||||
|
|
||||||
hide: function(animate, onComplete) {
|
hide: function(animate, onComplete) {
|
||||||
let x = this.actor.x;
|
let xOffset = 0;
|
||||||
let y = this.actor.y;
|
let yOffset = 0;
|
||||||
let originalX = this.actor.x;
|
|
||||||
let originalY = this.actor.y;
|
|
||||||
let themeNode = this.actor.get_theme_node();
|
let themeNode = this.actor.get_theme_node();
|
||||||
let rise = themeNode.get_length('-arrow-rise');
|
let rise = themeNode.get_length('-arrow-rise');
|
||||||
|
|
||||||
if (animate) {
|
if (animate) {
|
||||||
switch (this._arrowSide) {
|
switch (this._arrowSide) {
|
||||||
case St.Side.TOP:
|
case St.Side.TOP:
|
||||||
y += rise;
|
yOffset = rise;
|
||||||
break;
|
break;
|
||||||
case St.Side.BOTTOM:
|
case St.Side.BOTTOM:
|
||||||
y -= rise;
|
yOffset = -rise;
|
||||||
break;
|
break;
|
||||||
case St.Side.LEFT:
|
case St.Side.LEFT:
|
||||||
x += rise;
|
xOffset = rise;
|
||||||
break;
|
break;
|
||||||
case St.Side.RIGHT:
|
case St.Side.RIGHT:
|
||||||
x -= rise;
|
xOffset = -rise;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tweener.addTween(this.actor, { opacity: 0,
|
Tweener.addTween(this, { opacity: 0,
|
||||||
x: x,
|
xOffset: xOffset,
|
||||||
y: y,
|
yOffset: yOffset,
|
||||||
transition: "linear",
|
transition: "linear",
|
||||||
time: POPUP_ANIMATION_TIME,
|
time: POPUP_ANIMATION_TIME,
|
||||||
onComplete: Lang.bind(this, function () {
|
onComplete: Lang.bind(this, function () {
|
||||||
this.actor.hide();
|
this.actor.hide();
|
||||||
this.actor.x = originalX;
|
this.xOffset = 0;
|
||||||
this.actor.y = originalY;
|
this.yOffset = 0;
|
||||||
if (onComplete)
|
if (onComplete)
|
||||||
onComplete();
|
onComplete();
|
||||||
})
|
})
|
||||||
@ -178,17 +178,8 @@ BoxPointer.prototype = {
|
|||||||
}
|
}
|
||||||
this.bin.allocate(childBox, flags);
|
this.bin.allocate(childBox, flags);
|
||||||
|
|
||||||
if (this._sourceActor) {
|
if (this._sourceActor && this._sourceActor.mapped)
|
||||||
Meta.later_add (Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
// This won't cause a loop if _allocate() was
|
|
||||||
// called as a result of repositioning, because in
|
|
||||||
// that case _reposition() will set the same
|
|
||||||
// coordinates again, which Clutter will just
|
|
||||||
// ignore.
|
|
||||||
this._reposition(this._sourceActor, this._gap, this._alignment);
|
this._reposition(this._sourceActor, this._gap, this._alignment);
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_drawBorder: function(area) {
|
_drawBorder: function(area) {
|
||||||
@ -393,9 +384,9 @@ BoxPointer.prototype = {
|
|||||||
parent = parent.get_parent();
|
parent = parent.get_parent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually set the position
|
this._xPosition = Math.floor(x);
|
||||||
this.actor.x = Math.floor(x);
|
this._yPosition = Math.floor(y);
|
||||||
this.actor.y = Math.floor(y);
|
this._shiftActor();
|
||||||
},
|
},
|
||||||
|
|
||||||
// @origin: Coordinate specifying middle of the arrow, along
|
// @origin: Coordinate specifying middle of the arrow, along
|
||||||
@ -406,5 +397,42 @@ BoxPointer.prototype = {
|
|||||||
this._arrowOrigin = origin;
|
this._arrowOrigin = origin;
|
||||||
this._border.queue_repaint();
|
this._border.queue_repaint();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_shiftActor : function() {
|
||||||
|
// Since the position of the BoxPointer depends on the allocated size
|
||||||
|
// of the BoxPointer and the position of the source actor, trying
|
||||||
|
// to position the BoxPoiner via the x/y properties will result in
|
||||||
|
// allocation loops and warnings. Instead we do the positioning via
|
||||||
|
// the anchor point, which is independent of allocation, and leave
|
||||||
|
// x == y == 0.
|
||||||
|
this.actor.set_anchor_point(-(this._xPosition + this._xOffset),
|
||||||
|
-(this._yPosition + this._yOffset));
|
||||||
|
},
|
||||||
|
|
||||||
|
set xOffset(offset) {
|
||||||
|
this._xOffset = offset;
|
||||||
|
this._shiftActor();
|
||||||
|
},
|
||||||
|
|
||||||
|
get xOffset() {
|
||||||
|
return this._xOffset;
|
||||||
|
},
|
||||||
|
|
||||||
|
set yOffset(offset) {
|
||||||
|
this._yOffset = offset;
|
||||||
|
this._shiftActor();
|
||||||
|
},
|
||||||
|
|
||||||
|
get yOffset() {
|
||||||
|
return this._yOffset;
|
||||||
|
},
|
||||||
|
|
||||||
|
set opacity(opacity) {
|
||||||
|
this.actor.opacity = opacity;
|
||||||
|
},
|
||||||
|
|
||||||
|
get opacity() {
|
||||||
|
return this.actor.opacity;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user