1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * Provide support for drag-and-drop operations in shaped windows. The
8 * standard API doesn't work because no "dragover" events are generated
9 * if the mouse moves outside the window region.
13 /** @suppress {duplicate} */
14 var remoting
= remoting
|| {};
18 * @param {Element} element The element to register for drag and drop.
19 * @param {function(number, number):void} dragUpdate Callback to receive the
20 * X and Y deltas as the element is dragged.
21 * @param {function():void=} opt_dragStart Initiation callback.
22 * @param {function():void=} opt_dragEnd Completion callback.
24 remoting
.DragAndDrop = function(element
, dragUpdate
,
25 opt_dragStart
, opt_dragEnd
) {
27 this.element_
= element
;
30 this.dragUpdate_
= dragUpdate
;
33 this.dragStart_
= opt_dragStart
;
36 this.dragEnd_
= opt_dragEnd
;
38 /** @private {number} */
39 this.previousDeltaX_
= 0;
41 /** @private {number} */
42 this.previousDeltaY_
= 0;
44 /** @type {boolean} */
45 this.seenNonZeroDelta_
= false;
47 /** @private {function(Event):void} */
48 this.callOnMouseUp_
= this.onMouseUp_
.bind(this);
50 /** @private {function(Event):void} */
51 this.callOnMouseMove_
= this.onMouseMove_
.bind(this);
53 element
.addEventListener('mousedown', this.onMouseDown_
.bind(this), false);
57 * @param {Event} event
59 remoting
.DragAndDrop
.prototype.onMouseDown_ = function(event
) {
60 if (event
.button
!= 0) {
63 this.previousDeltaX_
= 0;
64 this.previousDeltaY_
= 0;
65 this.seenNonZeroDelta_
= false;
66 this.element_
.addEventListener('mousemove', this.callOnMouseMove_
, false);
67 this.element_
.addEventListener('mouseup', this.callOnMouseUp_
, false);
68 this.element_
.requestPointerLock();
69 if (this.dragStart_
) {
75 * TODO(jamiewalch): Remove the workarounds in this method once the pointer-lock
76 * API is fixed (crbug.com/419562).
78 * @param {Event} event
80 remoting
.DragAndDrop
.prototype.onMouseMove_ = function(event
) {
81 // Ignore the first non-zero delta. A click event will generate a bogus
82 // mousemove event, even if the mouse doesn't move.
83 if (!this.seenNonZeroDelta_
&&
84 (event
.movementX
!= 0 || event
.movementY
!= 0)) {
85 this.seenNonZeroDelta_
= true;
89 * The mouse lock API is buggy when used with shaped windows, and occasionally
90 * generates single, large deltas that must be filtered out.
92 * @param {number} previous
93 * @param {number} current
96 var adjustDelta = function(previous
, current
) {
97 var THRESHOLD
= 100; // Based on observed values.
98 if (Math
.abs(previous
< THRESHOLD
) && Math
.abs(current
) >= THRESHOLD
) {
103 this.previousDeltaX_
= adjustDelta(this.previousDeltaX_
, event
.movementX
);
104 this.previousDeltaY_
= adjustDelta(this.previousDeltaY_
, event
.movementY
);
105 if (this.previousDeltaX_
!= 0 || this.previousDeltaY_
!= 0) {
106 this.dragUpdate_(this.previousDeltaX_
, this.previousDeltaY_
);
111 * @param {Event} event
113 remoting
.DragAndDrop
.prototype.onMouseUp_ = function(event
) {
114 this.element_
.removeEventListener('mousemove', this.callOnMouseMove_
, false);
115 this.element_
.removeEventListener('mouseup', this.callOnMouseUp_
, false);
116 document
.exitPointerLock();