[gnome-shell] boxpointer: Flip side if we would end outside the monitor



commit 8d017ceaf1dffd3c35c15fea3dba810c6e36744a
Author: Rui Matos <tiagomatos gmail com>
Date:   Thu Jun 14 19:43:15 2012 +0200

    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

 js/ui/boxpointer.js |   68 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 61 insertions(+), 7 deletions(-)
---
diff --git a/js/ui/boxpointer.js b/js/ui/boxpointer.js
index 0535651..d09c8bf 100644
--- a/js/ui/boxpointer.js
+++ b/js/ui/boxpointer.js
@@ -18,7 +18,10 @@ const POPUP_ANIMATION_TIME = 0.15;
  *
  * An actor which displays a triangle "arrow" pointing to a given
  * 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({
@@ -26,6 +29,7 @@ const BoxPointer = new Lang.Class({
 
     _init: function(arrowSide, binProperties) {
         this._arrowSide = arrowSide;
+        this._userArrowSide = arrowSide;
         this._arrowOrigin = 0;
         this.actor = new St.Bin({ x_fill: true,
                                   y_fill: true });
@@ -199,8 +203,27 @@ const BoxPointer = new Lang.Class({
         }
         this.bin.allocate(childBox, flags);
 
-        if (this._sourceActor && this._sourceActor.mapped)
+        if (this._sourceActor && this._sourceActor.mapped) {
             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) {
@@ -327,6 +350,8 @@ const BoxPointer = new Lang.Class({
     },
 
     setPosition: function(sourceActor, alignment) {
+        this._arrowSide = this._userArrowSide;
+
         // We need to show it now to force an allocation,
         // so that we can query the correct size.
         this.actor.show();
@@ -343,11 +368,7 @@ const BoxPointer = new Lang.Class({
         if (!this._sourceActor)
             return;
 
-        // We need to show it now to force an allocation,
-        // so that we can query the correct size.
-        this.actor.show();
-
-        this._reposition(this._sourceActor, this._arrowAlignment);
+        this.setPosition(this._sourceActor, this._arrowAlignment);
     },
 
     _reposition: function(sourceActor, alignment) {
@@ -446,6 +467,39 @@ const BoxPointer = new Lang.Class({
                                     -(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) {
         this._xOffset = offset;
         this._shiftActor();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]