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 draft
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Wed, 13 Apr 2016 13:16:00 +0200
changeset 353059 d008cc34cef5143c981f9aff1a80dd52cac1f9c8
parent 352730 fae9c42677310d5dbe380e6e70efff2d46a99cc5
child 518814 729177d92904fe81f27a81094838b20afc348156
push id15871
push userchevobbe.nicolas@gmail.com
push dateTue, 19 Apr 2016 06:07:02 +0000
reviewersjdescottes
bugs1232806
milestone48.0a1
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