Bug 1241885 - Implement support for -moz-window-dragging in GTK and remove toolkit toolbar-drag binding. r=dao,bzbarsky,stransky
☠☠ backed out by 0771389994bb ☠ ☠
authorTim Nguyen <ntim.bugs@gmail.com>
Fri, 18 Jan 2019 16:51:08 +0000
changeset 454459 176be7000d331cd31aa97a6d8a35bdf0777b520f
parent 454458 255d5e9dc5ca7e1bbd00852c0c7fc24836f1f757
child 454460 dd82c0dd27dffc6fd32e0cba59d74c70e3f96ecb
push id35397
push useropoprus@mozilla.com
push dateSat, 19 Jan 2019 03:35:41 +0000
treeherdermozilla-central@57dc8bbbc38f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, bzbarsky, stransky
bugs1241885
milestone66.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 1241885 - Implement support for -moz-window-dragging in GTK and remove toolkit toolbar-drag binding. r=dao,bzbarsky,stransky The restriction preventing fullscreen windows from being dragged is removed. Differential Revision: https://phabricator.services.mozilla.com/D15075
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
browser/base/content/test/static/browser_all_files_referenced.js
browser/themes/linux/browser.css
browser/themes/linux/places/organizer.css
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/webidl/Window.webidl
toolkit/content/jar.mn
toolkit/content/tests/chrome/chrome.ini
toolkit/content/tests/chrome/test_bug585946.xul
toolkit/content/widgets/toolbar.xml
toolkit/modules/WindowDraggingUtils.jsm
toolkit/modules/moz.build
toolkit/themes/linux/global/global.css
tools/lint/eslint/modules.json
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
widget/nsBaseWidget.h
widget/nsIWidget.h
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1537,22 +1537,16 @@ var gBrowserInit = {
     });
 
     window.addEventListener("mousemove", MousePosTracker);
     window.addEventListener("dragover", MousePosTracker);
 
     gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
     gNavToolbox.addEventListener("customizationending", CustomizationHandler);
 
-    if (AppConstants.platform == "linux") {
-      let { WindowDraggingElement } =
-        ChromeUtils.import("resource://gre/modules/WindowDraggingUtils.jsm", {});
-      new WindowDraggingElement(document.getElementById("titlebar"));
-    }
-
     SessionStore.promiseInitialized.then(() => {
       // Bail out if the window has been closed in the meantime.
       if (window.closed) {
         return;
       }
 
       // Enable the Restore Last Session command if needed
       RestoreLastSessionObserver.init();
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1250,17 +1250,17 @@
           gBrowser._endRemoveTab(tab);
         }
       ]]></handler>
 
       <handler event="dblclick"><![CDATA[
         // When the tabbar has an unified appearance with the titlebar
         // and menubar, a double-click in it should have the same behavior
         // as double-clicking the titlebar
-        if (TabsInTitlebar.enabled || this.parentNode._dragBindingAlive)
+        if (TabsInTitlebar.enabled)
           return;
 
         if (event.button != 0 ||
             event.originalTarget.localName != "scrollbox")
           return;
 
         if (!this._blockDblClick)
           BrowserOpenTab();
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -153,19 +153,16 @@ var whitelist = [
   // Bug 1356043
   {file: "resource://gre/modules/PerfMeasurement.jsm"},
   // Bug 1356045
   {file: "chrome://global/content/test-ipc.xul"},
   // Bug 1378173 (warning: still used by devtools)
   {file: "resource://gre/modules/Promise.jsm"},
   // Still used by WebIDE, which is going away but not entirely gone.
   {file: "resource://gre/modules/ZipUtils.jsm"},
-  // Bug 1463225 (on Mac and Windows this is only used by a test)
-  {file: "chrome://global/content/bindings/toolbar.xml",
-   platforms: ["macosx", "win"]},
   // Bug 1483277 (temporarily unreferenced)
   {file: AppConstants.BROWSER_CHROME_URL == "chrome://browser/content/browser.xul" ?
     "chrome://browser/content/browser.xhtml" : "chrome://browser/content/browser.xul" },
   // Bug 1494170
   // (The references to these files are dynamically generated, so the test can't
   // find the references)
   {file: "chrome://devtools/skin/images/aboutdebugging-firefox-aurora.svg",
    isFromDevTools: true},
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -475,22 +475,22 @@ notification[value="translation"] menuli
 }
 
 #TabsToolbar:not(:-moz-lwtheme) {
   -moz-appearance: menubar;
   color: -moz-menubartext;
 }
 
 #nav-bar {
-  -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
+  -moz-window-dragging: drag;
 }
 
 @media (-moz-menubar-drag) {
   #TabsToolbar {
-    -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
+    -moz-window-dragging: drag;
   }
 }
 
 .keyboard-focused-tab > .tab-stack > .tab-content,
 .tabbrowser-tab:focus:not([aria-activedescendant]) > .tab-stack > .tab-content {
   outline: 1px dotted;
   outline-offset: -6px;
 }
--- a/browser/themes/linux/places/organizer.css
+++ b/browser/themes/linux/places/organizer.css
@@ -5,17 +5,17 @@
 
 /* Toolbar */
 #placesToolbar {
   -moz-appearance: menubar;
 }
 
 @media (-moz-menubar-drag) {
   #placesToolbar {
-    -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
+    -moz-window-dragging: drag;
   }
 }
 
 #placesToolbar > toolbarbutton {
   color: -moz-menubartext;
 }
 
 #placesToolbar > toolbarbutton:hover {
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -6612,34 +6612,16 @@ void nsGlobalWindowInner::GetAttentionWi
                                                      ErrorResult& aError) {
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
 
   if (widget) {
     aError = widget->GetAttention(aCycleCount);
   }
 }
 
-void nsGlobalWindowInner::BeginWindowMove(Event& aMouseDownEvent,
-                                          ErrorResult& aError) {
-  nsCOMPtr<nsIWidget> widget = GetMainWidget();
-
-  if (!widget) {
-    return;
-  }
-
-  WidgetMouseEvent* mouseEvent =
-      aMouseDownEvent.WidgetEventPtr()->AsMouseEvent();
-  if (!mouseEvent || mouseEvent->mClass != eMouseEventClass) {
-    aError.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aError = widget->BeginMoveDrag(mouseEvent);
-}
-
 already_AddRefed<Promise> nsGlobalWindowInner::PromiseDocumentFlushed(
     PromiseDocumentFlushedCallback& aCallback, ErrorResult& aError) {
   MOZ_RELEASE_ASSERT(IsChromeWindow());
 
   if (!IsCurrentInnerWindow()) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -898,18 +898,16 @@ class nsGlobalWindowInner final : public
   void Maximize();
   void Minimize();
   void Restore();
   void NotifyDefaultButtonLoaded(mozilla::dom::Element& aDefaultButton,
                                  mozilla::ErrorResult& aError);
   mozilla::dom::ChromeMessageBroadcaster* MessageManager();
   mozilla::dom::ChromeMessageBroadcaster* GetGroupMessageManager(
       const nsAString& aGroup);
-  void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent,
-                       mozilla::ErrorResult& aError);
 
   already_AddRefed<mozilla::dom::Promise> PromiseDocumentFlushed(
       mozilla::dom::PromiseDocumentFlushedCallback& aCallback,
       mozilla::ErrorResult& aError);
 
   void DidRefresh() override;
 
   void GetDialogArgumentsOuter(JSContext* aCx,
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -450,27 +450,16 @@ partial interface Window {
   /**
    * Returns the message manager identified by the given group name that
    * manages all frame loaders belonging to that group.
    */
   [Func="nsGlobalWindowInner::IsPrivilegedChromeWindow"]
   ChromeMessageBroadcaster getGroupMessageManager(DOMString aGroup);
 
   /**
-   * On some operating systems, we must allow the window manager to
-   * handle window dragging. This function tells the window manager to
-   * start dragging the window. This function will fail unless called
-   * while the left mouse button is held down, callers must check this.
-   *
-   * Throws NS_ERROR_NOT_IMPLEMENTED if the OS doesn't support this.
-   */
-  [Throws, Func="nsGlobalWindowInner::IsPrivilegedChromeWindow"]
-  void beginWindowMove(Event mouseDownEvent);
-
-  /**
    * Calls the given function as soon as a style or layout flush for the
    * top-level document is not necessary, and returns a Promise which
    * resolves to the callback's return value after it executes.
    *
    * In the event that the window goes away before a flush can occur, the
    * callback will still be called and the Promise resolved as the window
    * tears itself down.
    *
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -79,17 +79,16 @@ toolkit.jar:
    content/global/bindings/richlistbox.xml     (widgets/richlistbox.xml)
    content/global/bindings/scrollbox.xml       (widgets/scrollbox.xml)
    content/global/bindings/spinner.js          (widgets/spinner.js)
    content/global/bindings/tabbox.xml          (widgets/tabbox.xml)
    content/global/bindings/text.xml            (widgets/text.xml)
 *  content/global/bindings/textbox.xml         (widgets/textbox.xml)
    content/global/bindings/timekeeper.js       (widgets/timekeeper.js)
    content/global/bindings/timepicker.js       (widgets/timepicker.js)
-   content/global/bindings/toolbar.xml         (widgets/toolbar.xml)
    content/global/bindings/toolbarbutton.xml   (widgets/toolbarbutton.xml)
    content/global/bindings/tree.xml            (widgets/tree.xml)
    content/global/bindings/videocontrols.xml   (widgets/videocontrols.xml)
 *  content/global/bindings/wizard.xml          (widgets/wizard.xml)
    content/global/elements/browser-custom-element.js          (widgets/browser-custom-element.js)
    content/global/elements/datetimebox.js      (widgets/datetimebox.js)
    content/global/elements/findbar.js          (widgets/findbar.js)
    content/global/elements/editor.js           (widgets/editor.js)
--- a/toolkit/content/tests/chrome/chrome.ini
+++ b/toolkit/content/tests/chrome/chrome.ini
@@ -90,17 +90,16 @@ skip-if = (verify && debug && (os == 'ma
 support-files = bug451540_window.xul
 [test_bug457632.xul]
 [test_bug460942.xul]
 [test_bug471776.xul]
 [test_bug509732.xul]
 [test_bug557987.xul]
 [test_bug562554.xul]
 [test_bug570192.xul]
-[test_bug585946.xul]
 [test_bug624329.xul]
 skip-if = (os == 'mac' && os_version == '10.10') # Unexpectedly perma-passes on OSX 10.10
 [test_bug792324.xul]
 [test_bug1048178.xul]
 skip-if = toolkit == "cocoa"
 [test_button.xul]
 [test_closemenu_attribute.xul]
 [test_contextmenu_list.xul]
deleted file mode 100644
--- a/toolkit/content/tests/chrome/test_bug585946.xul
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-
-<window title="Toolbar" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onload="startTest();">
-
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-
-  <toolbox>
-    <toolbarpalette/>
-    <toolbar id="toolbar" defaultset="node1,node2">
-      <toolbarbutton id="node1" label="node1" removable="true"/>
-      <toolbarbutton id="node2" label="node2" removable="true"/>
-    </toolbar>
-  </toolbox>
-
-  <!-- test resuls are displayed in the html:body -->
-  <body xmlns="http://www.w3.org/1999/xhtml"
-        style="height: 300px; overflow: auto;"/>
-
-  <!-- test code goes here -->
-  <script type="application/javascript"><![CDATA[
-
-SimpleTest.waitForExplicitFinish();
-
-function startTest() {
-  var toolbar = $("toolbar");
-
-  var splitter = document.createElement("splitter");
-  splitter.setAttribute("id", "dynsplitter");
-  splitter.setAttribute("skipintoolbarset", "true");
-
-  toolbar.insertBefore(splitter, $("node2"));
-
-  function checkPos() {
-    is($("dynsplitter").previousSibling, $("node1"));
-    is($("dynsplitter").nextSibling, $("node2"));
-  }
-
-  checkPos();
-  toolbar.style.MozBinding = "url(chrome://global/content/bindings/toolbar.xml#toolbar-drag)";
-  toolbar.clientTop; // style flush
-  checkPos();
-
-  SimpleTest.finish();
-}
-
-  ]]></script>
-</window>
deleted file mode 100644
--- a/toolkit/content/widgets/toolbar.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<bindings id="toolbarBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="toolbar-drag">
-    <implementation>
-      <field name="_dragBindingAlive">true</field>
-      <constructor><![CDATA[
-        if (!this._draggableStarted) {
-          this._draggableStarted = true;
-          try {
-            let tmp = {};
-            ChromeUtils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
-            let draggableThis = new tmp.WindowDraggingElement(this);
-            draggableThis.mouseDownCheck = function(e) {
-              return this._dragBindingAlive;
-            };
-          } catch (e) {}
-        }
-      ]]></constructor>
-    </implementation>
-  </binding>
-</bindings>
deleted file mode 100644
--- a/toolkit/modules/WindowDraggingUtils.jsm
+++ /dev/null
@@ -1,70 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-
-const HAVE_CSS_WINDOW_DRAG_SUPPORT = ["win", "macosx"].includes(AppConstants.platform);
-
-var EXPORTED_SYMBOLS = [ "WindowDraggingElement" ];
-
-function WindowDraggingElement(elem) {
-  if (HAVE_CSS_WINDOW_DRAG_SUPPORT) {
-    return;
-  }
-  this._elem = elem;
-  this._window = elem.ownerGlobal;
-  this._elem.addEventListener("mousedown", this);
-}
-
-WindowDraggingElement.prototype = {
-  mouseDownCheck(e) { return true; },
-  dragTags: ["box", "hbox", "vbox", "spacer", "label", "statusbarpanel", "stack",
-             "toolbaritem", "toolbarseparator", "toolbarspring", "toolbarspacer",
-             "radiogroup", "deck", "scrollbox", "arrowscrollbox", "tabs"],
-  shouldDrag(aEvent) {
-    if (aEvent.button != 0 ||
-        this._window.fullScreen ||
-        !this.mouseDownCheck.call(this._elem, aEvent) ||
-        aEvent.defaultPrevented)
-      return false;
-
-    let target = aEvent.originalTarget, parent = aEvent.originalTarget;
-
-    // The target may be inside an embedded iframe or browser. (bug 615152)
-    if (target.ownerGlobal != this._window)
-      return false;
-
-    while (parent != this._elem) {
-      let mousethrough = parent.getAttribute("mousethrough");
-      if (mousethrough == "always")
-        target = parent.parentNode;
-      else if (mousethrough == "never")
-        break;
-      parent = parent.parentNode;
-    }
-    while (target != this._elem) {
-      if (!this.dragTags.includes(target.localName))
-        return false;
-      target = target.parentNode;
-    }
-    return true;
-  },
-  handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "mousedown":
-        if (this.shouldDrag(aEvent)) {
-          this._window.addEventListener("mousemove", this, { once: true });
-          this._window.addEventListener("mouseup", this, { once: true });
-        }
-        break;
-      case "mousemove":
-        this._window.beginWindowMove(aEvent);
-        this._window.removeEventListener("mouseup", this);
-        break;
-      case "mouseup":
-        this._window.removeEventListener("mousemove", this);
-        break;
-    }
-  },
-};
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -244,17 +244,16 @@ EXTRA_JS_MODULES += [
     'sessionstore/FormData.jsm',
     'ShortcutUtils.jsm',
     'Sqlite.jsm',
     'Timer.jsm',
     'Troubleshoot.jsm',
     'UpdateUtils.jsm',
     'WebChannel.jsm',
     'WebProgressChild.jsm',
-    'WindowDraggingUtils.jsm',
     'ZipUtils.jsm',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXTRA_JS_MODULES += [
         'PropertyListUtils.jsm',
     ]
 
--- a/toolkit/themes/linux/global/global.css
+++ b/toolkit/themes/linux/global/global.css
@@ -14,17 +14,17 @@
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../../shared/global.inc.css
 
 /* ::::: XBL bindings ::::: */
 
 @media (-moz-menubar-drag) {
   toolbar[type="menubar"] {
-    -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
+    -moz-window-dragging: drag;
   }
 }
 
 /* ::::: Variables ::::: */
 :root {
   --default-arrowpanel-background: -moz-field;
   --default-arrowpanel-color: -moz-fieldText;
   --default-arrowpanel-border-color: ThreeDShadow;
--- a/tools/lint/eslint/modules.json
+++ b/tools/lint/eslint/modules.json
@@ -205,14 +205,13 @@
   "util.js": ["getChromeWindow", "Utils", "Svc", "SerializableSet"],
   "utils.js": ["btoa", "encryptPayload", "makeIdentityConfig", "makeFxAccountsInternalMock", "configureFxAccountIdentity", "configureIdentity", "SyncTestingInfrastructure", "waitForZeroTimer", "Promise", "MockFxaStorageManager", "AccountState", "sumHistogram", "CommonUtils", "CryptoUtils", "TestingUtils", "promiseZeroTimer", "promiseNamedTimer", "getLoginTelemetryScalar", "syncTestLogging"],
   "Utils.jsm": ["Utils", "Logger", "PivotContext", "PrefCache"],
   "VariablesView.jsm": ["VariablesView", "escapeHTML"],
   "VariablesViewController.jsm": ["VariablesViewController", "StackFrameUtils"],
   "version.jsm": ["VERSION"],
   "vtt.jsm": ["WebVTT"],
   "WebChannel.jsm": ["WebChannel", "WebChannelBroker"],
-  "WindowDraggingUtils.jsm": ["WindowDraggingElement"],
   "windows.jsm": ["BrowserWindows"],
   "WindowsJumpLists.jsm": ["WinTaskbarJumpList"],
   "WindowsPreviewPerTab.jsm": ["AeroPeek"],
   "xul-app.jsm": ["XulApp"]
 }
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -2305,16 +2305,41 @@ static LayoutDeviceIntPoint GetRefPoint(
   // XXX we're never quite sure which GdkWindow the event came from due to our
   // custom bubbling in scroll_event_cb(), so use ScreenToWidget to translate
   // the screen root coordinates into coordinates relative to this widget.
   return aWindow->GdkEventCoordsToDevicePixels(aEvent->x_root, aEvent->y_root) -
          aWindow->WidgetToScreenOffset();
 }
 
 void nsWindow::OnMotionNotifyEvent(GdkEventMotion *aEvent) {
+  if (mWindowShouldStartDragging) {
+    mWindowShouldStartDragging = false;
+    // find the top-level window
+    GdkWindow *gdk_window = gdk_window_get_toplevel(mGdkWindow);
+    MOZ_ASSERT(gdk_window, "gdk_window_get_toplevel should not return null");
+
+    bool canDrag = true;
+    if (mIsX11Display) {
+      // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=789054
+      // To avoid crashes disable double-click on WM without _NET_WM_MOVERESIZE.
+      // See _should_perform_ewmh_drag() at gdkwindow-x11.c
+      GdkScreen *screen = gdk_window_get_screen(gdk_window);
+      GdkAtom atom = gdk_atom_intern("_NET_WM_MOVERESIZE", FALSE);
+      if (!gdk_x11_screen_supports_net_wm_hint(screen, atom)) {
+        canDrag = false;
+      }
+    }
+
+    if (canDrag) {
+      gdk_window_begin_move_drag(gdk_window, 1, aEvent->x_root, aEvent->y_root,
+                                 aEvent->time);
+      return;
+    }
+  }
+
   // see if we can compress this event
   // XXXldb Why skip every other motion event when we have multiple,
   // but not more than that?
   bool synthEvent = false;
 #ifdef MOZ_X11
   XEvent xevent;
 
   if (mIsX11Display) {
@@ -2533,27 +2558,37 @@ void nsWindow::OnButtonPressEvent(GdkEve
 
   gButtonState |= ButtonMaskFromGDKButton(aEvent->button);
 
   WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal);
   event.button = domButton;
   InitButtonEvent(event, aEvent);
   event.pressure = mLastMotionPressure;
 
-  DispatchInputEvent(&event);
+  nsEventStatus eventStatus = DispatchInputEvent(&event);
+
+  if (mDraggableRegion.Contains(aEvent->x, aEvent->y) &&
+      domButton == WidgetMouseEvent::eLeftButton &&
+      eventStatus != nsEventStatus_eConsumeNoDefault) {
+    mWindowShouldStartDragging = true;
+  }
 
   // right menu click on linux should also pop up a context menu
   if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) {
     DispatchContextMenuEventFromMouseEvent(domButton, aEvent);
   }
 }
 
 void nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent) {
   LOG(("Button %u release on %p\n", aEvent->button, (void *)this));
 
+  if (mWindowShouldStartDragging) {
+    mWindowShouldStartDragging = false;
+  }
+
   uint16_t domButton;
   switch (aEvent->button) {
     case 1:
       domButton = WidgetMouseEvent::eLeftButton;
       break;
     case 2:
       domButton = WidgetMouseEvent::eMiddleButton;
       break;
@@ -5776,36 +5811,16 @@ bool nsWindow::GetDragInfo(WidgetMouseEv
   // from the event.)
   LayoutDeviceIntPoint offset = aMouseEvent->mWidget->WidgetToScreenOffset();
   *aRootX = aMouseEvent->mRefPoint.x + offset.x;
   *aRootY = aMouseEvent->mRefPoint.y + offset.y;
 
   return true;
 }
 
-nsresult nsWindow::BeginMoveDrag(WidgetMouseEvent *aEvent) {
-  MOZ_ASSERT(aEvent, "must have event");
-  MOZ_ASSERT(aEvent->mClass == eMouseEventClass,
-             "event must have correct struct type");
-
-  GdkWindow *gdk_window;
-  gint button, screenX, screenY;
-  if (!GetDragInfo(aEvent, &gdk_window, &button, &screenX, &screenY)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // tell the window manager to start the move
-  screenX = DevicePixelsToGdkCoordRoundDown(screenX);
-  screenY = DevicePixelsToGdkCoordRoundDown(screenY);
-  gdk_window_begin_move_drag(gdk_window, button, screenX, screenY,
-                             aEvent->mTime);
-
-  return NS_OK;
-}
-
 nsresult nsWindow::BeginResizeDrag(WidgetGUIEvent *aEvent, int32_t aHorizontal,
                                    int32_t aVertical) {
   NS_ENSURE_ARG_POINTER(aEvent);
 
   if (aEvent->mClass != eMouseEventClass) {
     // you can only begin a resize drag with a mouse event
     return NS_ERROR_INVALID_ARG;
   }
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -257,18 +257,16 @@ class nsWindow final : public nsBaseWidg
   Window mOldFocusWindow;
 #endif /* MOZ_X11 */
 
   static guint32 sLastButtonPressTime;
 
   virtual MOZ_MUST_USE nsresult BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent,
                                                 int32_t aHorizontal,
                                                 int32_t aVertical) override;
-  virtual MOZ_MUST_USE nsresult
-  BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent) override;
 
   MozContainer* GetMozContainer() { return mContainer; }
   // GetMozContainerWidget returns the MozContainer even for undestroyed
   // descendant windows
   GtkWidget* GetMozContainerWidget();
   GdkWindow* GetGdkWindow() { return mGdkWindow; }
   GtkWidget* GetGtkWidget() { return mShell; }
   bool IsDestroyed() { return mIsDestroyed; }
@@ -464,16 +462,17 @@ class nsWindow final : public nsBaseWidg
 #endif
   nsCString mGtkWindowTypeName;
   nsCString mGtkWindowRoleName;
   void RefreshWindowClass();
 
   GtkWidget* mShell;
   MozContainer* mContainer;
   GdkWindow* mGdkWindow;
+  bool mWindowShouldStartDragging = false;
   PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
 
   uint32_t mHasMappedToplevel : 1, mIsFullyObscured : 1, mRetryPointerGrab : 1;
   nsSizeMode mSizeState;
 
   int32_t mTransparencyBitmapWidth;
   int32_t mTransparencyBitmapHeight;
 
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -267,20 +267,16 @@ class nsBaseWidget : public nsIWidget, p
   virtual void SetDrawsInTitlebar(bool aState) override {}
   virtual bool ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect) override;
   virtual void FreeNativeData(void* data, uint32_t aDataType) override {}
   virtual MOZ_MUST_USE nsresult BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent,
                                                 int32_t aHorizontal,
                                                 int32_t aVertical) override {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
-  virtual MOZ_MUST_USE nsresult
-  BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent) override {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
   virtual nsresult ActivateNativeMenuItemAt(
       const nsAString& indexString) override {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
   virtual nsresult ForceUpdateNativeMenuAt(
       const nsAString& indexString) override {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1456,22 +1456,16 @@ class nsIWidget : public nsISupports {
 
   /**
    * Begin a window resizing drag, based on the event passed in.
    */
   virtual MOZ_MUST_USE nsresult BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent,
                                                 int32_t aHorizontal,
                                                 int32_t aVertical) = 0;
 
-  /**
-   * Begin a window moving drag, based on the event passed in.
-   */
-  virtual MOZ_MUST_USE nsresult
-  BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent) = 0;
-
   enum Modifiers {
     CAPS_LOCK = 0x00000001,  // when CapsLock is active
     NUM_LOCK = 0x00000002,   // when NumLock is active
     SHIFT_L = 0x00000100,
     SHIFT_R = 0x00000200,
     CTRL_L = 0x00000400,
     CTRL_R = 0x00000800,
     ALT_L = 0x00001000,  // includes Option