Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

browser(firefox): support internal drag and drop #2243

Merged
merged 1 commit into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion browser_patches/firefox/BUILD_NUMBER
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1094
1095
82 changes: 80 additions & 2 deletions browser_patches/firefox/patches/bootstrap.diff
Original file line number Diff line number Diff line change
Expand Up @@ -3699,10 +3699,10 @@ index 0000000000000000000000000000000000000000..155d0770ddf704728829272a41a31ce8
+
diff --git a/juggler/content/PageAgent.js b/juggler/content/PageAgent.js
new file mode 100644
index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057fbf0ae582
index 0000000000000000000000000000000000000000..73b6ee4d266ff648acd0a8dfb8909f9b0c76c28d
--- /dev/null
+++ b/juggler/content/PageAgent.js
@@ -0,0 +1,914 @@
@@ -0,0 +1,992 @@
+"use strict";
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const Ci = Components.interfaces;
Expand All @@ -3711,6 +3711,12 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
+
+const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
+const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
+const dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(
+ Ci.nsIDragService
+);
+const obs = Cc["@mozilla.org/observer-service;1"].getService(
+ Ci.nsIObserverService
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: obs -> observerService ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they use obs other places in their code. I firefox style makes it easy to see where this is copy pasted from.

+);
+
+const helper = new Helper();
+
Expand Down Expand Up @@ -3862,6 +3868,7 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
+ this._docShell = docShell;
+ this._initialDPPX = docShell.contentViewer.overrideDPPX;
+ this._customScrollbars = null;
+ this._dataTransfer = null;
+ }
+
+ async _awaitViewportDimensions({width, height}) {
Expand Down Expand Up @@ -4369,6 +4376,12 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
+ }
+
+ async _dispatchKeyEvent({type, keyCode, code, key, repeat, location, text}) {
+ // key events don't fire if we are dragging.
+ if (this._dataTransfer) {
+ if (type === 'keydown' && key === 'Escape')
+ this._cancelDragIfNeeded();
+ return;
+ }
+ const frame = this._frameTree.mainFrame();
+ const tip = frame.textInputProcessor();
+ if (key === 'Meta' && Services.appinfo.OS !== 'Darwin')
Expand Down Expand Up @@ -4415,8 +4428,61 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
+ return {defaultPrevented};
+ }
+
+ _startDragSessionIfNeeded() {
+ const sess = dragService.getCurrentSession();
+ if (sess) return;
+ dragService.startDragSessionForTests(
+ Ci.nsIDragService.DRAGDROP_ACTION_MOVE |
+ Ci.nsIDragService.DRAGDROP_ACTION_COPY |
+ Ci.nsIDragService.DRAGDROP_ACTION_LINK
+ );
+ }
+
+ _simulateDragEvent(type, x, y, modifiers) {
+ const window = this._frameTree.mainFrame().domWindow();
+ const element = window.windowUtils.elementFromPoint(x, y, false, false);
+ const event = window.document.createEvent('DragEvent');
+
+ event.initDragEvent(
+ type,
+ true /* bubble */,
+ true /* cancelable */,
+ window,
+ 0 /* clickCount */,
+ window.mozInnerScreenX + x,
+ window.mozInnerScreenY + y,
+ x,
+ y,
+ modifiers & 2 /* ctrlkey */,
+ modifiers & 1 /* altKey */,
+ modifiers & 4 /* shiftKey */,
+ modifiers & 8 /* metaKey */,
+ 0 /* button */, // firefox always has the button as 0 on drops, regardless of which was pressed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be actual button for dragover events?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, its always 0 for mousemove/dropover events as well.

+ null /* relatedTarget */,
+ this._dataTransfer
+ );
+
+ window.windowUtils.dispatchDOMEventViaPresShellForTesting(element, event);
+ if (type === 'drop')
+ dragService.endDragSession(true);
+ }
+
+ _cancelDragIfNeeded() {
+ this._dataTransfer = null;
+ const sess = dragService.getCurrentSession();
+ if (sess)
+ dragService.endDragSession(false);
+ }
+
+ async _dispatchMouseEvent({type, x, y, button, clickCount, modifiers, buttons}) {
+ this._startDragSessionIfNeeded();
+ const trapDrag = subject => {
+ this._dataTransfer = subject.mozCloneForEvent('drop');
+ }
+
+ const frame = this._frameTree.mainFrame();
+
+ obs.addObserver(trapDrag, 'on-datatransfer-available');
+ frame.domWindow().windowUtils.sendMouseEvent(
+ type,
+ x,
Expand All @@ -4430,6 +4496,8 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
+ undefined /*isDOMEventSynthesized*/,
+ undefined /*isWidgetEventSynthesized*/,
+ buttons);
+ obs.removeObserver(trapDrag, 'on-datatransfer-available');
+
+ if (type === 'mousedown' && button === 2) {
+ frame.domWindow().windowUtils.sendMouseEvent(
+ 'contextmenu',
Expand All @@ -4445,6 +4513,16 @@ index 0000000000000000000000000000000000000000..63754937b3464794227fe894b3d6057f
+ undefined /*isWidgetEventSynthesized*/,
+ buttons);
+ }
+
+ // update drag state
+ if (this._dataTransfer) {
+ if (type === 'mousemove')
+ this._simulateDragEvent('dragover', x, y, modifiers);
+ else if (type === 'mouseup') // firefox will do drops when any mouse button is released
+ this._simulateDragEvent('drop', x, y, modifiers);
+ } else {
+ this._cancelDragIfNeeded();
+ }
+ }
+
+ async _insertText({text}) {
Expand Down