Bug 1399956 - Support synthesized mouse events. r?jrmuizel draft
authorBrendan Dahl <brendan.dahl@gmail.com>
Tue, 19 Sep 2017 15:22:41 -0700
changeset 677764 f3dcd1ceb17139d9f19a8f49968eee21927fb04b
parent 675231 2d5747516d6988595d0de909b6743023f587f59b
child 677765 30544d9631b3c0d557889f22828b601c8614005f
push id83803
push userbmo:bdahl@mozilla.com
push dateTue, 10 Oct 2017 18:53:32 +0000
reviewersjrmuizel
bugs1399956
milestone58.0a1
Bug 1399956 - Support synthesized mouse events. r?jrmuizel Fixes: - test_pointerlock-api.html - test_group_mouseevents.html MozReview-Commit-ID: 82RKzjJv9X1
widget/headless/HeadlessWidget.cpp
widget/headless/HeadlessWidget.h
--- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp
@@ -2,16 +2,17 @@
  * 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/. */
 #include "HeadlessWidget.h"
 #include "HeadlessCompositorWidget.h"
 #include "Layers.h"
 #include "BasicLayers.h"
 #include "BasicEvents.h"
+#include "MouseEvents.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ClearOnShutdown.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 /*static*/ already_AddRefed<nsIWidget>
 nsIWidget::CreateHeadlessWidget()
@@ -407,10 +408,45 @@ HeadlessWidget::DispatchEvent(WidgetGUIE
     aStatus = mAttachedWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   } else if (mWidgetListener) {
     aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   }
 
   return NS_OK;
 }
 
+nsresult
+HeadlessWidget::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
+                                           uint32_t aNativeMessage,
+                                           uint32_t aModifierFlags,
+                                           nsIObserver* aObserver)
+{
+  AutoObserverNotifier notifier(aObserver, "mouseevent");
+  EventMessage msg;
+  switch (aNativeMessage) {
+    case MOZ_HEADLESS_MOUSE_MOVE:
+      msg = eMouseMove;
+      break;
+    case MOZ_HEADLESS_MOUSE_DOWN:
+      msg = eMouseDown;
+      break;
+    case MOZ_HEADLESS_MOUSE_UP:
+      msg = eMouseUp;
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Unsupported synthesized mouse event");
+      return NS_ERROR_UNEXPECTED;
+  }
+  WidgetMouseEvent event(true, msg, this, WidgetMouseEvent::eReal);
+  event.mRefPoint = aPoint - WidgetToScreenOffset();
+  if (msg == eMouseDown || msg == eMouseUp) {
+    event.button = WidgetMouseEvent::eLeftButton;
+  }
+  if (msg == eMouseDown) {
+    event.mClickCount = 1;
+  }
+  event.AssignEventTime(WidgetEventTime());
+  DispatchInputEvent(&event);
+  return NS_OK;
+}
+
 } // namespace widget
 } // namespace mozilla
--- a/widget/headless/HeadlessWidget.h
+++ b/widget/headless/HeadlessWidget.h
@@ -6,16 +6,40 @@
 
 #ifndef HEADLESSWIDGET_H
 #define HEADLESSWIDGET_H
 
 #include "mozilla/widget/InProcessCompositorWidget.h"
 #include "nsBaseWidget.h"
 #include "CompositorWidget.h"
 
+// The various synthesized event values are hardcoded to avoid pulling
+// in the platform specific widget code.
+#if defined(MOZ_WIDGET_GTK)
+#define MOZ_HEADLESS_MOUSE_MOVE 3 // GDK_MOTION_NOTIFY
+#define MOZ_HEADLESS_MOUSE_DOWN 4 // GDK_BUTTON_PRESS
+#define MOZ_HEADLESS_MOUSE_UP   7 // GDK_BUTTON_RELEASE
+#elif defined(XP_WIN)
+#define MOZ_HEADLESS_MOUSE_MOVE 1 // MOUSEEVENTF_MOVE
+#define MOZ_HEADLESS_MOUSE_DOWN 2 // MOUSEEVENTF_LEFTDOWN
+#define MOZ_HEADLESS_MOUSE_UP   4 // MOUSEEVENTF_LEFTUP
+#elif defined(XP_MACOSX)
+#define MOZ_HEADLESS_MOUSE_MOVE 5 // NSMouseMoved
+#define MOZ_HEADLESS_MOUSE_DOWN 1 // NSLeftMouseDown
+#define MOZ_HEADLESS_MOUSE_UP   2 // NSLeftMouseUp
+#elif defined(ANDROID)
+#define MOZ_HEADLESS_MOUSE_MOVE 7 // ACTION_HOVER_MOVE
+#define MOZ_HEADLESS_MOUSE_DOWN 5 // ACTION_POINTER_DOWN
+#define MOZ_HEADLESS_MOUSE_UP   6 // ACTION_POINTER_UP
+#else
+#define MOZ_HEADLESS_MOUSE_MOVE -1
+#define MOZ_HEADLESS_MOUSE_DOWN -1
+#define MOZ_HEADLESS_MOUSE_UP   -1
+#endif
+
 namespace mozilla {
 namespace widget {
 
 class HeadlessWidget : public nsBaseWidget
 {
 public:
   HeadlessWidget();
 
@@ -87,16 +111,24 @@ public:
                   LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
                   LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
 
   void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override;
 
   virtual nsresult DispatchEvent(WidgetGUIEvent* aEvent,
                                  nsEventStatus& aStatus) override;
 
+  virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
+                                              uint32_t aNativeMessage,
+                                              uint32_t aModifierFlags,
+                                              nsIObserver* aObserver) override;
+  virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
+                                             nsIObserver* aObserver) override
+                   { return SynthesizeNativeMouseEvent(aPoint, MOZ_HEADLESS_MOUSE_MOVE, 0, aObserver); };
+
 private:
   ~HeadlessWidget();
   bool mEnabled;
   bool mVisible;
   bool mDestroyed;
   nsIWidget* mTopLevel;
   HeadlessCompositorWidget* mCompositorWidget;
   // The size mode before entering fullscreen mode.