summaryrefslogtreecommitdiffstats
path: root/widget/headless/HeadlessWidget.h
blob: 25cb1623ba86109c232ab21ff5c67a349c1bf060 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * 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/. */

#ifndef HEADLESSWIDGET_H
#define HEADLESSWIDGET_H

#include "mozilla/widget/InProcessCompositorWidget.h"
#include "nsBaseWidget.h"
#include "CompositorWidget.h"
#include "mozilla/dom/WheelEventBinding.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
#  define MOZ_HEADLESS_SCROLL_MULTIPLIER 3
#  define MOZ_HEADLESS_SCROLL_DELTA_MODE \
    mozilla::dom::WheelEvent_Binding::DOM_DELTA_LINE
#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
#  define MOZ_HEADLESS_SCROLL_MULTIPLIER \
    .025  // default scroll lines (3) / WHEEL_DELTA (120)
#  define MOZ_HEADLESS_SCROLL_DELTA_MODE \
    mozilla::dom::WheelEvent_Binding::DOM_DELTA_LINE
#elif defined(XP_MACOSX)
#  define MOZ_HEADLESS_MOUSE_MOVE 5  // NSEventTypeMouseMoved
#  define MOZ_HEADLESS_MOUSE_DOWN 1  // NSEventTypeLeftMouseDown
#  define MOZ_HEADLESS_MOUSE_UP 2    // NSEventTypeLeftMouseUp
#  define MOZ_HEADLESS_SCROLL_MULTIPLIER 1
#  define MOZ_HEADLESS_SCROLL_DELTA_MODE \
    mozilla::dom::WheelEvent_Binding::DOM_DELTA_PIXEL
#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
#  define MOZ_HEADLESS_SCROLL_MULTIPLIER 1
#  define MOZ_HEADLESS_SCROLL_DELTA_MODE \
    mozilla::dom::WheelEvent_Binding::DOM_DELTA_LINE
#else
#  define MOZ_HEADLESS_MOUSE_MOVE -1
#  define MOZ_HEADLESS_MOUSE_DOWN -1
#  define MOZ_HEADLESS_MOUSE_UP -1
#  define MOZ_HEADLESS_SCROLL_MULTIPLIER -1
#  define MOZ_HEADLESS_SCROLL_DELTA_MODE -1
#endif

namespace mozilla {
namespace widget {

class HeadlessWidget : public nsBaseWidget {
 public:
  HeadlessWidget();

  NS_INLINE_DECL_REFCOUNTING_INHERITED(HeadlessWidget, nsBaseWidget)

  void* GetNativeData(uint32_t aDataType) override {
    // Headless widgets have no native data.
    return nullptr;
  }

  virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
                          const LayoutDeviceIntRect& aRect,
                          nsWidgetInitData* aInitData = nullptr) override;
  using nsBaseWidget::Create;  // for Create signature not overridden here
  virtual already_AddRefed<nsIWidget> CreateChild(
      const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData = nullptr,
      bool aForceUseIWidgetParent = false) override;

  virtual nsIWidget* GetTopLevelWidget() override;

  virtual void GetCompositorWidgetInitData(
      mozilla::widget::CompositorWidgetInitData* aInitData) override;

  virtual void Destroy() override;
  virtual void Show(bool aState) override;
  virtual bool IsVisible() const override;
  virtual void Move(double aX, double aY) override;
  virtual void Resize(double aWidth, double aHeight, bool aRepaint) override;
  virtual void Resize(double aX, double aY, double aWidth, double aHeight,
                      bool aRepaint) override;
  virtual void SetSizeMode(nsSizeMode aMode) override;
  virtual nsresult MakeFullScreen(bool aFullScreen,
                                  nsIScreen* aTargetScreen = nullptr) override;
  virtual void Enable(bool aState) override;
  virtual bool IsEnabled() const override;
  virtual void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override;
  virtual nsresult ConfigureChildren(
      const nsTArray<Configuration>& aConfigurations) override {
    MOZ_ASSERT_UNREACHABLE(
        "Headless widgets do not support configuring children.");
    return NS_ERROR_FAILURE;
  }
  virtual void Invalidate(const LayoutDeviceIntRect& aRect) override {
    // TODO: see if we need to do anything here.
  }
  virtual nsresult SetTitle(const nsAString& title) override {
    // Headless widgets have no title, so just ignore it.
    return NS_OK;
  }
  virtual nsresult SetNonClientMargins(
      LayoutDeviceIntMargin& margins) override {
    // Headless widgets have no chrome margins, so just ignore the call.
    return NS_OK;
  }
  virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
  virtual void SetInputContext(const InputContext& aContext,
                               const InputContextAction& aAction) override {
    mInputContext = aContext;
  }
  virtual InputContext GetInputContext() override { return mInputContext; }

  virtual LayerManager* GetLayerManager(
      PLayerTransactionChild* aShadowManager = nullptr,
      LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
      LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;

  void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override;

  [[nodiscard]] virtual nsresult AttachNativeKeyEvent(
      WidgetKeyboardEvent& aEvent) override;
  virtual bool GetEditCommands(NativeKeyBindingsType aType,
                               const WidgetKeyboardEvent& aEvent,
                               nsTArray<CommandInt>& aCommands) 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);
  };

  virtual nsresult SynthesizeNativeMouseScrollEvent(
      LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, double aDeltaX,
      double aDeltaY, double aDeltaZ, uint32_t aModifierFlags,
      uint32_t aAdditionalFlags, nsIObserver* aObserver) override;

  virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
                                              TouchPointerState aPointerState,
                                              LayoutDeviceIntPoint aPoint,
                                              double aPointerPressure,
                                              uint32_t aPointerOrientation,
                                              nsIObserver* aObserver) override;

 private:
  ~HeadlessWidget();
  bool mEnabled;
  bool mVisible;
  bool mDestroyed;
  nsIWidget* mTopLevel;
  HeadlessCompositorWidget* mCompositorWidget;
  // The size mode before entering fullscreen mode.
  nsSizeMode mLastSizeMode;
  // The last size mode set while the window was visible.
  nsSizeMode mEffectiveSizeMode;
  InputContext mInputContext;
  mozilla::UniquePtr<mozilla::MultiTouchInput> mSynthesizedTouchInput;
  // In headless there is no window manager to track window bounds
  // across size mode changes, so we must track it to emulate.
  LayoutDeviceIntRect mRestoreBounds;
  void ApplySizeModeSideEffects();
  // Similarly, we must track the active window ourselves in order
  // to dispatch (de)activation events properly.
  void RaiseWindow();
  // The top level widgets are tracked for window ordering. They are
  // stored in order of activation where the last element is always the
  // currently active widget.
  static StaticAutoPtr<nsTArray<HeadlessWidget*>> sActiveWindows;
  // Get the most recently activated widget or null if there are none.
  static already_AddRefed<HeadlessWidget> GetActiveWindow();
};

}  // namespace widget
}  // namespace mozilla

#endif