Bug 1232806 - Change mouse events' target to window in the markup view to keep track of the dragging even when the cursor is outside the window. r=jdescottes
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Wed, 13 Apr 2016 13:16:00 +0200
changeset 293761 e2f5cd553b44f73fa85c8427aed560f9a47f0ce9
parent 293760 72da827dde30b4c3cff2b6785a785b3a4284daa9
child 293762 9774863180f92d75e7851f138bed71fe9828122a
push id30193
push usercbook@mozilla.com
push dateWed, 20 Apr 2016 09:47:15 +0000
treeherdermozilla-central@973dfa158221 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1232806
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1232806 - Change mouse events' target to window in the markup view to keep track of the dragging even when the cursor is outside the window. r=jdescottes Add some tests in the `mousemove` handler to keep the dragged node inside the markup panel. MozReview-Commit-ID: LSlzTeJyc9D
devtools/client/inspector/markup/markup.js
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -125,17 +125,17 @@ function MarkupView(inspector, frame, co
   this._onToolboxPickerHover = this._onToolboxPickerHover.bind(this);
   this._onCollapseAttributesPrefChange =
     this._onCollapseAttributesPrefChange.bind(this);
 
   // Listening to various events.
   this._elt.addEventListener("click", this._onMouseClick, false);
   this._elt.addEventListener("mousemove", this._onMouseMove, false);
   this._elt.addEventListener("mouseleave", this._onMouseLeave, false);
-  this.doc.body.addEventListener("mouseup", this._onMouseUp);
+  this.win.addEventListener("mouseup", this._onMouseUp);
   this.win.addEventListener("keydown", this._onKeyDown, false);
   this.win.addEventListener("copy", this._onCopy);
   this._frame.addEventListener("focus", this._onFocus, false);
   this.walker.on("mutations", this._mutationObserver);
   this.walker.on("display-change", this._onDisplayChange);
   this._inspector.selection.on("new-node-front", this._onNewSelection);
   this._inspector.toolbox.on("picker-node-hovered", this._onToolboxPickerHover);
 
@@ -1616,17 +1616,17 @@ MarkupView.prototype = {
     this.undo = null;
 
     this.popup.destroy();
     this.popup = null;
 
     this._elt.removeEventListener("click", this._onMouseClick, false);
     this._elt.removeEventListener("mousemove", this._onMouseMove, false);
     this._elt.removeEventListener("mouseleave", this._onMouseLeave, false);
-    this.doc.body.removeEventListener("mouseup", this._onMouseUp);
+    this.win.removeEventListener("mouseup", this._onMouseUp);
     this.win.removeEventListener("keydown", this._onKeyDown, false);
     this.win.removeEventListener("copy", this._onCopy);
     this._frame.removeEventListener("focus", this._onFocus, false);
     this.walker.off("mutations", this._mutationObserver);
     this.walker.off("display-change", this._onDisplayChange);
     this._inspector.selection.off("new-node-front", this._onNewSelection);
     this._inspector.toolbox.off("picker-node-hovered",
                                 this._onToolboxPickerHover);
@@ -1788,18 +1788,18 @@ MarkupContainer.prototype = {
 
     this._onMouseDown = this._onMouseDown.bind(this);
     this._onToggle = this._onToggle.bind(this);
     this._onMouseUp = this._onMouseUp.bind(this);
     this._onMouseMove = this._onMouseMove.bind(this);
 
     // Binding event listeners
     this.elt.addEventListener("mousedown", this._onMouseDown, false);
-    this.markup.doc.body.addEventListener("mouseup", this._onMouseUp, true);
-    this.markup.doc.body.addEventListener("mousemove", this._onMouseMove, true);
+    this.win.addEventListener("mouseup", this._onMouseUp, true);
+    this.win.addEventListener("mousemove", this._onMouseMove, true);
     this.elt.addEventListener("dblclick", this._onToggle, false);
     if (this.expander) {
       this.expander.addEventListener("click", this._onToggle, false);
     }
 
     // Marking the node as shown or hidden
     this.isDisplayed = this.node.isDisplayed;
   },
@@ -2052,21 +2052,30 @@ MarkupContainer.prototype = {
       // indicator.
       let position = this.elt.nextElementSibling ||
                      this.markup.getContainer(this.node.parentNode())
                                 .closeTagLine;
       this.markup.indicateDragTarget(position);
     }
 
     if (this.isDragging) {
-      let diff = event.pageY - this._dragStartY;
+      let x = 0;
+      let y = event.pageY - this.win.scrollY;
+
+      // Ensure we keep the dragged element within the markup view.
+      if (y < 0) {
+        y = 0;
+      } else if (y >= this.markup.doc.body.offsetHeight - this.win.scrollY) {
+        y = this.markup.doc.body.offsetHeight - this.win.scrollY - 1;
+      }
+
+      let diff = y - this._dragStartY + this.win.scrollY;
       this.elt.style.top = diff + "px";
 
-      let el = this.markup.doc.elementFromPoint(event.pageX - this.win.scrollX,
-                                                event.pageY - this.win.scrollY);
+      let el = this.markup.doc.elementFromPoint(x, y);
       this.markup.indicateDropTarget(el);
     }
   },
 
   cancelDragging: function() {
     if (!this.isDragging) {
       return;
     }
@@ -2185,19 +2194,20 @@ MarkupContainer.prototype = {
   /**
    * Get rid of event listeners and references, when the container is no longer
    * needed
    */
   destroy: function() {
     // Remove event listeners
     this.elt.removeEventListener("mousedown", this._onMouseDown, false);
     this.elt.removeEventListener("dblclick", this._onToggle, false);
-    this.markup.doc.body.removeEventListener("mouseup", this._onMouseUp, true);
-    this.markup.doc.body.removeEventListener("mousemove",
-      this._onMouseMove, true);
+    if (this.win) {
+      this.win.removeEventListener("mouseup", this._onMouseUp, true);
+      this.win.removeEventListener("mousemove", this._onMouseMove, true);
+    }
 
     this.win = null;
 
     if (this.expander) {
       this.expander.removeEventListener("click", this._onToggle, false);
     }
 
     // Recursively destroy children containers