Skip to content

Commit 5a883a5

Browse files
browser(firefox): support internal drag and drop (#2243)
1 parent a38ac3f commit 5a883a5

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

browser_patches/firefox/BUILD_NUMBER

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1094
1+
1095

browser_patches/firefox/patches/bootstrap.diff

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3699,10 +3699,10 @@ index 0000000000000000000000000000000000000000..155d0770ddf704728829272a41a31ce8
36993699
+
37003700
diff --git a/juggler/content/PageAgent.js b/juggler/content/PageAgent.js
37013701
new file mode 100644
3702-
index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057fbf0ae582
3702+
index 0000000000000000000000000000000000000000..73b6ee4d266ff648acd0a8dfb8909f9b0c76c28d
37033703
--- /dev/null
37043704
+++ b/juggler/content/PageAgent.js
3705-
@@ -0,0 +1,914 @@
3705+
@@ -0,0 +1,992 @@
37063706
+"use strict";
37073707
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
37083708
+const Ci = Components.interfaces;
@@ -3711,6 +3711,12 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
37113711
+
37123712
+const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
37133713
+const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
3714+
+const dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(
3715+
+ Ci.nsIDragService
3716+
+);
3717+
+const obs = Cc["@mozilla.org/observer-service;1"].getService(
3718+
+ Ci.nsIObserverService
3719+
+);
37143720
+
37153721
+const helper = new Helper();
37163722
+
@@ -3862,6 +3868,7 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
38623868
+ this._docShell = docShell;
38633869
+ this._initialDPPX = docShell.contentViewer.overrideDPPX;
38643870
+ this._customScrollbars = null;
3871+
+ this._dataTransfer = null;
38653872
+ }
38663873
+
38673874
+ async _awaitViewportDimensions({width, height}) {
@@ -4369,6 +4376,12 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
43694376
+ }
43704377
+
43714378
+ async _dispatchKeyEvent({type, keyCode, code, key, repeat, location, text}) {
4379+
+ // key events don't fire if we are dragging.
4380+
+ if (this._dataTransfer) {
4381+
+ if (type === 'keydown' && key === 'Escape')
4382+
+ this._cancelDragIfNeeded();
4383+
+ return;
4384+
+ }
43724385
+ const frame = this._frameTree.mainFrame();
43734386
+ const tip = frame.textInputProcessor();
43744387
+ if (key === 'Meta' && Services.appinfo.OS !== 'Darwin')
@@ -4415,8 +4428,61 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
44154428
+ return {defaultPrevented};
44164429
+ }
44174430
+
4431+
+ _startDragSessionIfNeeded() {
4432+
+ const sess = dragService.getCurrentSession();
4433+
+ if (sess) return;
4434+
+ dragService.startDragSessionForTests(
4435+
+ Ci.nsIDragService.DRAGDROP_ACTION_MOVE |
4436+
+ Ci.nsIDragService.DRAGDROP_ACTION_COPY |
4437+
+ Ci.nsIDragService.DRAGDROP_ACTION_LINK
4438+
+ );
4439+
+ }
4440+
+
4441+
+ _simulateDragEvent(type, x, y, modifiers) {
4442+
+ const window = this._frameTree.mainFrame().domWindow();
4443+
+ const element = window.windowUtils.elementFromPoint(x, y, false, false);
4444+
+ const event = window.document.createEvent('DragEvent');
4445+
+
4446+
+ event.initDragEvent(
4447+
+ type,
4448+
+ true /* bubble */,
4449+
+ true /* cancelable */,
4450+
+ window,
4451+
+ 0 /* clickCount */,
4452+
+ window.mozInnerScreenX + x,
4453+
+ window.mozInnerScreenY + y,
4454+
+ x,
4455+
+ y,
4456+
+ modifiers & 2 /* ctrlkey */,
4457+
+ modifiers & 1 /* altKey */,
4458+
+ modifiers & 4 /* shiftKey */,
4459+
+ modifiers & 8 /* metaKey */,
4460+
+ 0 /* button */, // firefox always has the button as 0 on drops, regardless of which was pressed
4461+
+ null /* relatedTarget */,
4462+
+ this._dataTransfer
4463+
+ );
4464+
+
4465+
+ window.windowUtils.dispatchDOMEventViaPresShellForTesting(element, event);
4466+
+ if (type === 'drop')
4467+
+ dragService.endDragSession(true);
4468+
+ }
4469+
+
4470+
+ _cancelDragIfNeeded() {
4471+
+ this._dataTransfer = null;
4472+
+ const sess = dragService.getCurrentSession();
4473+
+ if (sess)
4474+
+ dragService.endDragSession(false);
4475+
+ }
4476+
+
44184477
+ async _dispatchMouseEvent({type, x, y, button, clickCount, modifiers, buttons}) {
4478+
+ this._startDragSessionIfNeeded();
4479+
+ const trapDrag = subject => {
4480+
+ this._dataTransfer = subject.mozCloneForEvent('drop');
4481+
+ }
4482+
+
44194483
+ const frame = this._frameTree.mainFrame();
4484+
+
4485+
+ obs.addObserver(trapDrag, 'on-datatransfer-available');
44204486
+ frame.domWindow().windowUtils.sendMouseEvent(
44214487
+ type,
44224488
+ x,
@@ -4430,6 +4496,8 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
44304496
+ undefined /*isDOMEventSynthesized*/,
44314497
+ undefined /*isWidgetEventSynthesized*/,
44324498
+ buttons);
4499+
+ obs.removeObserver(trapDrag, 'on-datatransfer-available');
4500+
+
44334501
+ if (type === 'mousedown' && button === 2) {
44344502
+ frame.domWindow().windowUtils.sendMouseEvent(
44354503
+ 'contextmenu',
@@ -4445,6 +4513,16 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
44454513
+ undefined /*isWidgetEventSynthesized*/,
44464514
+ buttons);
44474515
+ }
4516+
+
4517+
+ // update drag state
4518+
+ if (this._dataTransfer) {
4519+
+ if (type === 'mousemove')
4520+
+ this._simulateDragEvent('dragover', x, y, modifiers);
4521+
+ else if (type === 'mouseup') // firefox will do drops when any mouse button is released
4522+
+ this._simulateDragEvent('drop', x, y, modifiers);
4523+
+ } else {
4524+
+ this._cancelDragIfNeeded();
4525+
+ }
44484526
+ }
44494527
+
44504528
+ async _insertText({text}) {

0 commit comments

Comments
 (0)