boxpointer: Flip side if we would end outside the monitor

This flips the BoxPointer if it ends outside the monitor and we have
enough space to fit it inside, on the opposite side of the source
actor.

https://bugzilla.gnome.org/show_bug.cgi?id=678164
This commit is contained in:
Rui Matos 2012-06-14 19:43:15 +02:00
parent 02428019fa
commit 8d017ceaf1

View File

@ -18,7 +18,10 @@ const POPUP_ANIMATION_TIME = 0.15;
* *
* An actor which displays a triangle "arrow" pointing to a given * An actor which displays a triangle "arrow" pointing to a given
* side. The .bin property is a container in which content can be * side. The .bin property is a container in which content can be
* placed. The arrow position may be controlled via setArrowOrigin(). * placed. The arrow position may be controlled via
* setArrowOrigin(). The arrow side might be temporarily flipped
* depending on the box size and source position to keep the box
* totally inside the monitor if possible.
* *
*/ */
const BoxPointer = new Lang.Class({ const BoxPointer = new Lang.Class({
@ -26,6 +29,7 @@ const BoxPointer = new Lang.Class({
_init: function(arrowSide, binProperties) { _init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
this._userArrowSide = arrowSide;
this._arrowOrigin = 0; this._arrowOrigin = 0;
this.actor = new St.Bin({ x_fill: true, this.actor = new St.Bin({ x_fill: true,
y_fill: true }); y_fill: true });
@ -199,8 +203,27 @@ const BoxPointer = new Lang.Class({
} }
this.bin.allocate(childBox, flags); this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(this._sourceActor, this._arrowAlignment); this._reposition(this._sourceActor, this._arrowAlignment);
if (this._shouldFlip()) {
switch (this._arrowSide) {
case St.Side.TOP:
this._arrowSide = St.Side.BOTTOM;
break;
case St.Side.BOTTOM:
this._arrowSide = St.Side.TOP;
break;
case St.Side.LEFT:
this._arrowSide = St.Side.RIGHT;
break;
case St.Side.RIGHT:
this._arrowSide = St.Side.LEFT;
break;
}
this._reposition(this._sourceActor, this._arrowAlignment);
}
}
}, },
_drawBorder: function(area) { _drawBorder: function(area) {
@ -327,6 +350,8 @@ const BoxPointer = new Lang.Class({
}, },
setPosition: function(sourceActor, alignment) { setPosition: function(sourceActor, alignment) {
this._arrowSide = this._userArrowSide;
// We need to show it now to force an allocation, // We need to show it now to force an allocation,
// so that we can query the correct size. // so that we can query the correct size.
this.actor.show(); this.actor.show();
@ -343,11 +368,7 @@ const BoxPointer = new Lang.Class({
if (!this._sourceActor) if (!this._sourceActor)
return; return;
// We need to show it now to force an allocation, this.setPosition(this._sourceActor, this._arrowAlignment);
// so that we can query the correct size.
this.actor.show();
this._reposition(this._sourceActor, this._arrowAlignment);
}, },
_reposition: function(sourceActor, alignment) { _reposition: function(sourceActor, alignment) {
@ -446,6 +467,39 @@ const BoxPointer = new Lang.Class({
-(this._yPosition + this._yOffset)); -(this._yPosition + this._yOffset));
}, },
_shouldFlip: function() {
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
let boxWidth = boxAllocation.x2 - boxAllocation.x1;
let boxHeight = boxAllocation.y2 - boxAllocation.y1;
let monitor = Main.layoutManager.findMonitorForActor(this.actor);
switch (this._arrowSide) {
case St.Side.TOP:
if (boxAllocation.y2 > monitor.y + monitor.height &&
boxHeight < sourceAllocation.y1 - monitor.y)
return true;
break;
case St.Side.BOTTOM:
if (boxAllocation.y1 < monitor.y &&
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
return true;
break;
case St.Side.LEFT:
if (boxAllocation.x2 > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - monitor.x)
return true;
break;
case St.Side.RIGHT:
if (boxAllocation.x1 < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return true;
break;
}
return false;
},
set xOffset(offset) { set xOffset(offset) {
this._xOffset = offset; this._xOffset = offset;
this._shiftActor(); this._shiftActor();