Bug 1399956 - Support synthesized mouse events. r?jrmuizel
Fixes:
- test_pointerlock-api.html
- test_group_mouseevents.html
MozReview-Commit-ID: 82RKzjJv9X1
--- 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.