Bug 1295010 - Don't move the eyedropper to the out of browser window by keyboard navigation. r=pbro
authorRuturaj Vartak <ruturaj@gmail.com>
Sat, 03 Sep 2016 00:07:00 +0200
changeset 312853 a6b6a93eb41a05e310a11f0172f01ba9b21d3eac
parent 312852 99c542fa43a72ee863c813b5624048d1b443549b
child 312854 541c9086c0f27fba60beecc9bc94543103895c86
push id20467
push userryanvm@gmail.com
push dateWed, 07 Sep 2016 01:54:15 +0000
treeherderfx-team@a6b6a93eb41a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1295010
milestone51.0a1
Bug 1295010 - Don't move the eyedropper to the out of browser window by keyboard navigation. r=pbro MozReview-Commit-ID: vBwmSxVNXK
devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-events.js
devtools/client/inspector/test/head.js
devtools/server/actors/highlighters/eye-dropper.js
--- a/devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-events.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-events.js
@@ -2,48 +2,117 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 // Test the eyedropper mouse and keyboard handling.
 
 const HIGHLIGHTER_TYPE = "EyeDropper";
 const ID = "eye-dropper-";
+const TEST_URI = `
+<style>
+  html{width:100%;height:100%;}
+</style>
+<body>eye-dropper test</body>`;
 
 const MOVE_EVENTS_DATA = [
   {type: "mouse", x: 200, y: 100, expected: {x: 200, y: 100}},
   {type: "mouse", x: 100, y: 200, expected: {x: 100, y: 200}},
   {type: "keyboard", key: "VK_LEFT", expected: {x: 99, y: 200}},
   {type: "keyboard", key: "VK_LEFT", shift: true, expected: {x: 89, y: 200}},
   {type: "keyboard", key: "VK_RIGHT", expected: {x: 90, y: 200}},
   {type: "keyboard", key: "VK_RIGHT", shift: true, expected: {x: 100, y: 200}},
   {type: "keyboard", key: "VK_DOWN", expected: {x: 100, y: 201}},
   {type: "keyboard", key: "VK_DOWN", shift: true, expected: {x: 100, y: 211}},
   {type: "keyboard", key: "VK_UP", expected: {x: 100, y: 210}},
   {type: "keyboard", key: "VK_UP", shift: true, expected: {x: 100, y: 200}},
+  // Mouse initialization for left and top snapping
+  {type: "mouse", x: 7, y: 7, expected: {x: 7, y: 7}},
+  // Left Snapping
+  {type: "keyboard", key: "VK_LEFT", shift: true, expected: {x: 0, y: 7},
+   desc: "Left Snapping to x=0"},
+  // Top Snapping
+  {type: "keyboard", key: "VK_UP", shift: true, expected: {x: 0, y: 0},
+   desc: "Top Snapping to y=0"},
+  // Mouse initialization for right snapping
+  {
+    type: "mouse",
+    x: (width, height) => width - 5,
+    y: 0,
+    expected: {
+      x: (width, height) => width - 5,
+      y: 0
+    }
+  },
+  // Right snapping
+  {
+    type: "keyboard",
+    key: "VK_RIGHT",
+    shift: true,
+    expected: {
+      x: (width, height) => width,
+      y: 0
+    },
+    desc: "Right snapping to x=max window width available"
+  },
+  // Mouse initialization for bottom snapping
+  {
+    type: "mouse",
+    x: 0,
+    y: (width, height) => height - 5,
+    expected: {
+      x: 0,
+      y: (width, height) => height - 5
+    }
+  },
+  // Bottom snapping
+  {
+    type: "keyboard",
+    key: "VK_DOWN",
+    shift: true,
+    expected: {
+      x: 0,
+      y: (width, height) => height
+    },
+    desc: "Bottom snapping to y=max window height available"
+  },
 ];
 
 add_task(function* () {
-  let helper = yield openInspectorForURL("data:text/html;charset=utf-8,eye-dropper test")
-               .then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
+  let helper = yield openInspectorForURL("data:text/html;charset=utf-8,"
+    + encodeURIComponent(TEST_URI)
+  ).then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
   helper.prefix = ID;
 
   yield helper.show("html");
   yield respondsToMoveEvents(helper);
   yield respondsToReturnAndEscape(helper);
 
   helper.finalize();
 });
 
 function* respondsToMoveEvents(helper) {
   info("Checking that the eyedropper responds to events from the mouse and keyboard");
-  let {mouse} = helper;
+  let {mouse, testActor} = helper;
+  let {width, height} = yield testActor.getBoundingClientRect("html");
 
-  for (let {type, x, y, key, shift, expected} of MOVE_EVENTS_DATA) {
-    info(`Simulating a ${type} event to move to ${expected.x} ${expected.y}`);
+  for (let {type, x, y, key, shift, expected, desc} of MOVE_EVENTS_DATA) {
+    x = typeof x === "function" ? x(width, height) : x;
+    y = typeof y === "function" ? y(width, height) : y;
+    expected.x = typeof expected.x === "function" ?
+      expected.x(width, height) : expected.x;
+    expected.y = typeof expected.y === "function" ?
+      expected.y(width, height) : expected.y;
+
+    if (typeof desc === "undefined") {
+      info(`Simulating a ${type} event to move to ${expected.x} ${expected.y}`);
+    } else {
+      info(`Simulating ${type} event: ${desc}`);
+    }
+
     if (type === "mouse") {
       yield mouse.move(x, y);
     } else if (type === "keyboard") {
       let options = shift ? {shiftKey: true} : {};
       yield EventUtils.synthesizeKey(key, options);
     }
     yield checkPosition(expected, helper);
   }
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -526,17 +526,19 @@ const getHighlighterHelperFor = (type) =
 
       reflow: function* () {
         yield testActor.reflow();
       },
 
       finalize: function* () {
         highlightedNode = null;
         yield highlighter.finalize();
-      }
+      },
+
+      testActor: testActor
     };
   }
 );
 
 // The expand all operation of the markup-view calls itself recursively and
 // there's not one event we can wait for to know when it's done so use this
 // helper function to wait until all recursive children updates are done.
 function* waitForMultipleChildrenUpdates(inspector) {
--- a/devtools/server/actors/highlighters/eye-dropper.js
+++ b/devtools/server/actors/highlighters/eye-dropper.js
@@ -424,18 +424,20 @@ EyeDropper.prototype = {
     if (e.shiftKey) {
       modifier = 10;
     }
 
     offsetY *= modifier;
     offsetX *= modifier;
 
     if (offsetX !== 0 || offsetY !== 0) {
-      this.magnifiedArea.x += offsetX;
-      this.magnifiedArea.y += offsetY;
+      this.magnifiedArea.x = cap(this.magnifiedArea.x + offsetX,
+                                 0, this.win.innerWidth * this.pageZoom);
+      this.magnifiedArea.y = cap(this.magnifiedArea.y + offsetY, 0,
+                                 this.win.innerHeight * this.pageZoom);
 
       this.draw();
 
       this.moveTo(this.magnifiedArea.x / this.pageZoom,
                   this.magnifiedArea.y / this.pageZoom);
 
       e.preventDefault();
     }
@@ -521,8 +523,12 @@ function toColorString(rgb, format) {
  * Produce a hex-formatted color string from rgb values.
  * @param {array} rgb Rgb values of color to stringify.
  * @return {string} Hex formatted string for color, e.g. "#FFEE00".
  */
 function hexString([r, g, b]) {
   let val = (1 << 24) + (r << 16) + (g << 8) + (b << 0);
   return "#" + val.toString(16).substr(-6).toUpperCase();
 }
+
+function cap(value, min, max) {
+  return Math.max(min, Math.min(value, max));
+}