[gnome-shell] boxpointer: Avoid malformed boxpointer arrow



commit 00f15c10754fc327802fdec9318b8a07491df7b4
Author: Debarshi Ray <debarshir gnome org>
Date:   Sat Sep 1 16:42:50 2012 +0200

    boxpointer: Avoid malformed boxpointer arrow
    
    If the arrow's origin is so close to the edge that the arrow will not
    be isosceles, we try to compensate as follows:
      - We skip the rounded corner and settle for a right angled arrow as
        as shown below.
        |\_____
        |
        |
      - If the arrow was going to be acute angled, we move the position of
        the box to maintain the arrow's accuracy.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=680077

 js/ui/boxpointer.js |  179 ++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 129 insertions(+), 50 deletions(-)
---
diff --git a/js/ui/boxpointer.js b/js/ui/boxpointer.js
index 17c1801..5749a65 100644
--- a/js/ui/boxpointer.js
+++ b/js/ui/boxpointer.js
@@ -274,14 +274,51 @@ const BoxPointer = new Lang.Class({
         let [x1, y1] = [halfBorder, halfBorder];
         let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
 
+        let skipTopLeft = false;
+        let skipTopRight = false;
+        let skipBottomLeft = false;
+        let skipBottomRight = false;
+
+        switch (this._arrowSide) {
+        case St.Side.TOP:
+            if (this._arrowOrigin == x1)
+                skipTopLeft = true;
+            else if (this._arrowOrigin == x2)
+                skipTopRight = true;
+            break;
+
+        case St.Side.RIGHT:
+            if (this._arrowOrigin == y1)
+                skipTopRight = true;
+            else if (this._arrowOrigin == y2)
+                skipBottomRight = true;
+            break;
+
+        case St.Side.BOTTOM:
+            if (this._arrowOrigin == x1)
+                skipBottomLeft = true;
+            else if (this._arrowOrigin == x2)
+                skipBottomRight = true;
+            break;
+
+        case St.Side.LEFT:
+            if (this._arrowOrigin == y1)
+                skipTopLeft = true;
+            else if (this._arrowOrigin == y2)
+                skipBottomLeft = true;
+            break;
+        }
+
         cr.moveTo(x1 + borderRadius, y1);
         if (this._arrowSide == St.Side.TOP) {
-            if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
-                cr.lineTo(this._arrowOrigin, y1 - rise);
-                cr.lineTo(Math.max(x1 + borderRadius, this._arrowOrigin) + halfBase, y1);
-            } else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
-                cr.lineTo(Math.min(x2 - borderRadius, this._arrowOrigin) - halfBase, y1);
-                cr.lineTo(this._arrowOrigin, y1 - rise);
+            if (skipTopLeft) {
+                cr.moveTo(x1, y2 - borderRadius);
+                cr.lineTo(x1, y1 - rise);
+                cr.lineTo(x1 + halfBase, y1);
+            } else if (skipTopRight) {
+                cr.lineTo(x2 - halfBase, y1);
+                cr.lineTo(x2, y1 - rise);
+                cr.lineTo(x2, y1 + borderRadius);
             } else {
                 cr.lineTo(this._arrowOrigin - halfBase, y1);
                 cr.lineTo(this._arrowOrigin, y1 - rise);
@@ -289,19 +326,21 @@ const BoxPointer = new Lang.Class({
             }
         }
 
-        cr.lineTo(x2 - borderRadius, y1);
-
-        // top-right corner
-        cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
-               3*Math.PI/2, Math.PI*2);
+        if (!skipTopRight) {
+            // top-right corner
+            cr.lineTo(x2 - borderRadius, y1);
+            cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
+                   3*Math.PI/2, Math.PI*2);
+        }
 
         if (this._arrowSide == St.Side.RIGHT) {
-            if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
-                cr.lineTo(x2 + rise, this._arrowOrigin);
-                cr.lineTo(x2, Math.max(y1 + borderRadius, this._arrowOrigin) + halfBase);
-            } else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
-                cr.lineTo(x2, Math.min(y2 - borderRadius, this._arrowOrigin) - halfBase);
-                cr.lineTo(x2 + rise, this._arrowOrigin);
+            if (skipTopRight) {
+                cr.lineTo(x2 + rise, y1);
+                cr.lineTo(x2 + rise, y1 + halfBase);
+            } else if (skipBottomRight) {
+                cr.lineTo(x2, y2 - halfBase);
+                cr.lineTo(x2 + rise, y2);
+                cr.lineTo(x2 - borderRadius, y2);
             } else {
                 cr.lineTo(x2, this._arrowOrigin - halfBase);
                 cr.lineTo(x2 + rise, this._arrowOrigin);
@@ -309,19 +348,21 @@ const BoxPointer = new Lang.Class({
             }
         }
 
-        cr.lineTo(x2, y2 - borderRadius);
-
-        // bottom-right corner
-        cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
-               0, Math.PI/2);
+        if (!skipBottomRight) {
+            // bottom-right corner
+            cr.lineTo(x2, y2 - borderRadius);
+            cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
+                   0, Math.PI/2);
+        }
 
         if (this._arrowSide == St.Side.BOTTOM) {
-            if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
-                cr.lineTo(Math.max(x1 + borderRadius, this._arrowOrigin) + halfBase, y2);
-                cr.lineTo(this._arrowOrigin, y2 + rise);
-            } else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
-                cr.lineTo(this._arrowOrigin, y2 + rise);
-                cr.lineTo(Math.min(x2 - borderRadius, this._arrowOrigin) - halfBase, y2);
+            if (skipBottomLeft) {
+                cr.lineTo(x1 + halfBase, y2);
+                cr.lineTo(x1, y2 + rise);
+                cr.lineTo(x1, y2 - borderRadius);
+            } else if (skipBottomRight) {
+                cr.lineTo(x2, y2 + rise);
+                cr.lineTo(x2 - halfBase, y2);
             } else {
                 cr.lineTo(this._arrowOrigin + halfBase, y2);
                 cr.lineTo(this._arrowOrigin, y2 + rise);
@@ -329,19 +370,21 @@ const BoxPointer = new Lang.Class({
             }
         }
 
-        cr.lineTo(x1 + borderRadius, y2);
-
-        // bottom-left corner
-        cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
-               Math.PI/2, Math.PI);
+        if (!skipBottomLeft) {
+            // bottom-left corner
+            cr.lineTo(x1 + borderRadius, y2);
+            cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
+                   Math.PI/2, Math.PI);
+        }
 
         if (this._arrowSide == St.Side.LEFT) {
-            if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
-                cr.lineTo(x1, Math.max(y1 + borderRadius, this._arrowOrigin) + halfBase);
-                cr.lineTo(x1 - rise, this._arrowOrigin);
-            } else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
-                cr.lineTo(x1 - rise, this._arrowOrigin);
-                cr.lineTo(x1, Math.min(y2 - borderRadius, this._arrowOrigin) - halfBase);
+            if (skipTopLeft) {
+                cr.lineTo(x1, y1 + halfBase);
+                cr.lineTo(x1 - rise, y1);
+                cr.lineTo(x1 + borderRadius, y1);
+            } else if (skipBottomLeft) {
+                cr.lineTo(x1 - rise, y2)
+                cr.lineTo(x1 - rise, y2 - halfBase);
             } else {
                 cr.lineTo(x1, this._arrowOrigin + halfBase);
                 cr.lineTo(x1 - rise, this._arrowOrigin);
@@ -349,11 +392,12 @@ const BoxPointer = new Lang.Class({
             }
         }
 
-        cr.lineTo(x1, y1 + borderRadius);
-
-        // top-left corner
-        cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
-               Math.PI, 3*Math.PI/2);
+        if (!skipTopLeft) {
+            // top-left corner
+            cr.lineTo(x1, y1 + borderRadius);
+            cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
+                   Math.PI, 3*Math.PI/2);
+        }
 
         Clutter.cairo_set_source_color(cr, backgroundColor);
         cr.fillPreserve();
@@ -406,9 +450,8 @@ const BoxPointer = new Lang.Class({
         let arrowBase = themeNode.get_length('-arrow-base');
         let borderRadius = themeNode.get_length('-arrow-border-radius');
         let margin = (4 * borderRadius + borderWidth + arrowBase);
-        let halfMargin = margin / 2;
 
-        let themeNode = this.actor.get_theme_node();
+        let halfMargin = margin / 2;
         let gap = themeNode.get_length('-boxpointer-gap');
         let padding = themeNode.get_length('-arrow-rise');
 
@@ -429,8 +472,23 @@ const BoxPointer = new Lang.Class({
             break;
         }
 
-        // Now align and position the pointing axis, making sure
-        // it fits on screen
+        // Now align and position the pointing axis, making sure it fits on
+        // screen. If the arrowOrigin is so close to the edge that the arrow
+        // will not be isosceles, we try to compensate as follows:
+        //   - We skip the rounded corner and settle for a right angled arrow
+        //     as shown below. See _drawBorder for further details.
+        //     |\_____
+        //     |
+        //     |
+        //   - If the arrow was going to be acute angled, we move the position
+        //     of the box to maintain the arrow's accuracy.
+
+        let arrowOrigin;
+        let halfBase = Math.floor(arrowBase/2);
+        let halfBorder = borderWidth / 2;
+        let [x1, y1] = [halfBorder, halfBorder];
+        let [x2, y2] = [natWidth - halfBorder, natHeight - halfBorder];
+
         switch (this._arrowSide) {
         case St.Side.TOP:
         case St.Side.BOTTOM:
@@ -438,7 +496,17 @@ const BoxPointer = new Lang.Class({
 
             resX = Math.max(resX, monitor.x + padding);
             resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
-            this.setArrowOrigin(sourceCenterX - resX);
+
+            arrowOrigin = sourceCenterX - resX;
+            if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
+                if (arrowOrigin > x1)
+                    resX += (arrowOrigin - x1);
+                arrowOrigin = x1;
+            } else if (arrowOrigin >= (x2 - (borderRadius + halfBase))) {
+                if (arrowOrigin < x2)
+                    resX -= (x2 - arrowOrigin);
+                arrowOrigin = x2;
+            }
             break;
 
         case St.Side.LEFT:
@@ -448,10 +516,21 @@ const BoxPointer = new Lang.Class({
             resY = Math.max(resY, monitor.y + padding);
             resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
 
-            this.setArrowOrigin(sourceCenterY - resY);
+            arrowOrigin = sourceCenterY - resY;
+            if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
+                if (arrowOrigin > y1)
+                    resY += (arrowOrigin - y1);
+                arrowOrigin = y1;
+            } else if (arrowOrigin >= (y2 - (borderRadius + halfBase))) {
+                if (arrowOrigin < y2)
+                    resX -= (y2 - arrowOrigin);
+                arrowOrigin = y2;
+            }
             break;
         }
 
+        this.setArrowOrigin(arrowOrigin);
+
         let parent = this.actor.get_parent();
         let success, x, y;
         while (!success) {



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