Flutter Windows Embedder
flutter_windows_view.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
6 #define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
7 
8 #include <memory>
9 #include <mutex>
10 #include <string>
11 #include <unordered_map>
12 #include <utility>
13 #include <vector>
14 
15 #include "flutter/fml/macros.h"
18 #include "flutter/shell/platform/embedder/embedder.h"
26 
27 namespace flutter {
28 
29 // A unique identifier for a view.
30 using FlutterViewId = int64_t;
31 
32 // An OS-windowing neutral abstration for a Flutter view that works
33 // with win32 HWNDs.
35  public:
36  // Creates a FlutterWindowsView with the given implementor of
37  // WindowBindingHandler.
40  FlutterWindowsEngine* engine,
41  std::unique_ptr<WindowBindingHandler> window_binding,
42  std::shared_ptr<WindowsProcTable> windows_proc_table = nullptr);
43 
44  virtual ~FlutterWindowsView();
45 
46  // Get the view's unique identifier.
47  FlutterViewId view_id() const;
48 
49  // Whether this view is the implicit view.
50  //
51  // The implicit view is a special view for backwards compatibility.
52  // The engine assumes it can always render to this view, even if the app has
53  // destroyed the window for this view.
54  //
55  // Today, the implicit view is the first view that is created. It is the only
56  // view that can be created before the engine is launched.
57  //
58  // The embedder must ignore presents to this view before it is created and
59  // after it is destroyed.
60  //
61  // See:
62  // https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/implicitView.html
63  bool IsImplicitView() const;
64 
65  // Create a rendering surface for Flutter engine to draw into.
66  //
67  // This is a no-op if using software rasterization.
68  void CreateRenderSurface();
69 
70  // Get the EGL surface that backs the Flutter view.
71  //
72  // This might be nullptr or an invalid surface.
73  egl::WindowSurface* surface() const;
74 
75  // Return the currently configured HWND.
76  virtual HWND GetWindowHandle() const;
77 
78  // Returns the engine backing this view.
80 
81  // Tells the engine to generate a new frame
82  void ForceRedraw();
83 
84  // Callback to clear a previously presented software bitmap.
85  virtual bool ClearSoftwareBitmap();
86 
87  // Callback for presenting a software bitmap.
88  virtual bool PresentSoftwareBitmap(const void* allocation,
89  size_t row_bytes,
90  size_t height);
91 
92  // Creates a window metric for this view.
93  //
94  // Used to notify the engine of a view's current size and device pixel ratio.
95  FlutterWindowMetricsEvent CreateWindowMetricsEvent() const;
96 
97  // Send initial bounds to embedder. Must occur after engine has initialized.
98  //
99  // This is a no-op if this is not the implicit view. Non-implicit views'
100  // initial window metrics are sent when the view is added to the engine.
101  void SendInitialBounds();
102 
103  // Set the text of the alert, and create it if it does not yet exist.
104  void AnnounceAlert(const std::wstring& text);
105 
106  // |WindowBindingHandlerDelegate|
107  void OnHighContrastChanged() override;
108 
109  // Called on the raster thread when |CompositorOpenGL| receives an empty
110  // frame. Returns true if the frame can be presented.
111  //
112  // This destroys and then re-creates the view's surface if a resize is
113  // pending.
114  bool OnEmptyFrameGenerated();
115 
116  // Called on the raster thread when |CompositorOpenGL| receives a frame.
117  // Returns true if the frame can be presented.
118  //
119  // This destroys and then re-creates the view's surface if a resize is pending
120  // and |width| and |height| match the target size.
121  bool OnFrameGenerated(size_t width, size_t height);
122 
123  // Called on the raster thread after |CompositorOpenGL| presents a frame.
124  //
125  // This completes a view resize if one is pending.
126  virtual void OnFramePresented();
127 
128  // |WindowBindingHandlerDelegate|
129  bool OnWindowSizeChanged(size_t width, size_t height) override;
130 
131  // |WindowBindingHandlerDelegate|
132  void OnWindowRepaint() override;
133 
134  // |WindowBindingHandlerDelegate|
135  void OnPointerMove(double x,
136  double y,
137  FlutterPointerDeviceKind device_kind,
138  int32_t device_id,
139  int modifiers_state) override;
140 
141  // |WindowBindingHandlerDelegate|
142  void OnPointerDown(double x,
143  double y,
144  FlutterPointerDeviceKind device_kind,
145  int32_t device_id,
146  FlutterPointerMouseButtons button) override;
147 
148  // |WindowBindingHandlerDelegate|
149  void OnPointerUp(double x,
150  double y,
151  FlutterPointerDeviceKind device_kind,
152  int32_t device_id,
153  FlutterPointerMouseButtons button) override;
154 
155  // |WindowBindingHandlerDelegate|
156  void OnPointerLeave(double x,
157  double y,
158  FlutterPointerDeviceKind device_kind,
159  int32_t device_id = 0) override;
160 
161  // |WindowBindingHandlerDelegate|
162  virtual void OnPointerPanZoomStart(int32_t device_id) override;
163 
164  // |WindowBindingHandlerDelegate|
165  virtual void OnPointerPanZoomUpdate(int32_t device_id,
166  double pan_x,
167  double pan_y,
168  double scale,
169  double rotation) override;
170 
171  // |WindowBindingHandlerDelegate|
172  virtual void OnPointerPanZoomEnd(int32_t device_id) override;
173 
174  // |WindowBindingHandlerDelegate|
175  void OnText(const std::u16string&) override;
176 
177  // |WindowBindingHandlerDelegate|
178  void OnKey(int key,
179  int scancode,
180  int action,
181  char32_t character,
182  bool extended,
183  bool was_down,
184  KeyEventCallback callback) override;
185 
186  // |WindowBindingHandlerDelegate|
187  void OnFocus(FlutterViewFocusState focus_state,
188  FlutterViewFocusDirection direction) override;
189 
190  // |WindowBindingHandlerDelegate|
191  void OnComposeBegin() override;
192 
193  // |WindowBindingHandlerDelegate|
194  void OnComposeCommit() override;
195 
196  // |WindowBindingHandlerDelegate|
197  void OnComposeEnd() override;
198 
199  // |WindowBindingHandlerDelegate|
200  void OnComposeChange(const std::u16string& text, int cursor_pos) override;
201 
202  // |WindowBindingHandlerDelegate|
203  void OnScroll(double x,
204  double y,
205  double delta_x,
206  double delta_y,
207  int scroll_offset_multiplier,
208  FlutterPointerDeviceKind device_kind,
209  int32_t device_id) override;
210 
211  // |WindowBindingHandlerDelegate|
212  void OnScrollInertiaCancel(int32_t device_id) override;
213 
214  // |WindowBindingHandlerDelegate|
215  virtual void OnUpdateSemanticsEnabled(bool enabled) override;
216 
217  // |WindowBindingHandlerDelegate|
218  virtual gfx::NativeViewAccessible GetNativeViewAccessible() override;
219 
220  // Notifies the delegate of the updated the cursor rect in Flutter root view
221  // coordinates.
222  virtual void OnCursorRectUpdated(const Rect& rect);
223 
224  // Notifies the delegate that the system IME composing state should be reset.
225  virtual void OnResetImeComposing();
226 
227  // Called when a WM_ONCOMPOSITIONCHANGED message is received.
229 
230  // Get a pointer to the alert node for this view.
231  ui::AXPlatformNodeWin* AlertNode() const;
232 
233  // |WindowBindingHandlerDelegate|
234  virtual ui::AXFragmentRootDelegateWin* GetAxFragmentRootDelegate() override;
235 
236  // Called to re/set the accessibility bridge pointer.
237  virtual void UpdateSemanticsEnabled(bool enabled);
238 
239  std::weak_ptr<AccessibilityBridgeWindows> accessibility_bridge() {
240  return accessibility_bridge_;
241  }
242 
243  // |WindowBindingHandlerDelegate|
244  void OnWindowStateEvent(HWND hwnd, WindowStateEvent event) override;
245 
246  // Focus the view.
247  // Returns true if the view was focused.
248  virtual bool Focus();
249 
250  protected:
251  virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
252  ax::mojom::Event event);
253 
254  // Create an AccessibilityBridgeWindows using this view.
255  virtual std::shared_ptr<AccessibilityBridgeWindows>
257 
258  private:
259  // Allows setting the surface in tests.
260  friend class ViewModifier;
261 
262  // Struct holding the state of an individual pointer. The engine doesn't keep
263  // track of which buttons have been pressed, so it's the embedding's
264  // responsibility.
265  struct PointerState {
266  // The device kind.
267  FlutterPointerDeviceKind device_kind = kFlutterPointerDeviceKindMouse;
268 
269  // A virtual pointer ID that is unique across all device kinds.
270  int32_t pointer_id = 0;
271 
272  // True if the last event sent to Flutter had at least one button pressed.
273  bool flutter_state_is_down = false;
274 
275  // True if kAdd has been sent to Flutter. Used to determine whether
276  // to send a kAdd event before sending an incoming pointer event, since
277  // Flutter expects pointers to be added before events are sent for them.
278  bool flutter_state_is_added = false;
279 
280  // The currently pressed buttons, as represented in FlutterPointerEvent.
281  uint64_t buttons = 0;
282 
283  // The x position where the last pan/zoom started.
284  double pan_zoom_start_x = 0;
285 
286  // The y position where the last pan/zoom started.
287  double pan_zoom_start_y = 0;
288  };
289 
290  // States a resize event can be in.
291  enum class ResizeState {
292  // When a resize event has started but is in progress.
293  kResizeStarted,
294  // After a resize event starts and the framework has been notified to
295  // generate a frame for the right size.
296  kFrameGenerated,
297  // Default state for when no resize is in progress. Also used to indicate
298  // that during a resize event, a frame with the right size has been rendered
299  // and the buffers have been swapped.
300  kDone,
301  };
302 
303  // Resize the surface to the desired size.
304  //
305  // If the dimensions have changed, this destroys the original surface and
306  // creates a new one.
307  //
308  // This must be run on the raster thread. This binds the surface to the
309  // current thread.
310  //
311  // Width and height are the surface's desired physical pixel dimensions.
312  bool ResizeRenderSurface(size_t width, size_t height);
313 
314  // Sends a window metrics update to the Flutter engine using current window
315  // dimensions in physical pixels.
316  void SendWindowMetrics(size_t width, size_t height, double pixel_ratio) const;
317 
318  // Reports a mouse movement to Flutter engine.
319  void SendPointerMove(double x, double y, PointerState* state);
320 
321  // Reports mouse press to Flutter engine.
322  void SendPointerDown(double x, double y, PointerState* state);
323 
324  // Reports mouse release to Flutter engine.
325  void SendPointerUp(double x, double y, PointerState* state);
326 
327  // Reports mouse left the window client area.
328  //
329  // Win32 api doesn't have "mouse enter" event. Therefore, there is no
330  // SendPointerEnter method. A mouse enter event is tracked then the "move"
331  // event is called.
332  void SendPointerLeave(double x, double y, PointerState* state);
333 
334  void SendPointerPanZoomStart(int32_t device_id, double x, double y);
335 
336  void SendPointerPanZoomUpdate(int32_t device_id,
337  double pan_x,
338  double pan_y,
339  double scale,
340  double rotation);
341 
342  void SendPointerPanZoomEnd(int32_t device_id);
343 
344  // Reports a keyboard character to Flutter engine.
345  void SendText(const std::u16string&);
346 
347  // Reports a raw keyboard message to Flutter engine.
348  void SendKey(int key,
349  int scancode,
350  int action,
351  char32_t character,
352  bool extended,
353  bool was_down,
355 
356  // Reports a focus event to Flutter engine.
357  void SendFocus(FlutterViewFocusState focus_state,
358  FlutterViewFocusDirection direction);
359 
360  // Reports an IME compose begin event.
361  //
362  // Triggered when the user begins editing composing text using a multi-step
363  // input method such as in CJK text input.
364  void SendComposeBegin();
365 
366  // Reports an IME compose commit event.
367  //
368  // Triggered when the user commits the current composing text while using a
369  // multi-step input method such as in CJK text input. Composing continues with
370  // the next keypress.
371  void SendComposeCommit();
372 
373  // Reports an IME compose end event.
374  //
375  // Triggered when the user commits the composing text while using a multi-step
376  // input method such as in CJK text input.
377  void SendComposeEnd();
378 
379  // Reports an IME composing region change event.
380  //
381  // Triggered when the user edits the composing text while using a multi-step
382  // input method such as in CJK text input.
383  void SendComposeChange(const std::u16string& text, int cursor_pos);
384 
385  // Reports scroll wheel events to Flutter engine.
386  void SendScroll(double x,
387  double y,
388  double delta_x,
389  double delta_y,
390  int scroll_offset_multiplier,
391  FlutterPointerDeviceKind device_kind,
392  int32_t device_id);
393 
394  // Reports scroll inertia cancel events to Flutter engine.
395  void SendScrollInertiaCancel(int32_t device_id, double x, double y);
396 
397  // Creates a PointerState object unless it already exists.
398  PointerState* GetOrCreatePointerState(FlutterPointerDeviceKind device_kind,
399  int32_t device_id);
400 
401  // Sets |event_data|'s phase to either kMove or kHover depending on the
402  // current primary mouse button state.
403  void SetEventPhaseFromCursorButtonState(FlutterPointerEvent* event_data,
404  const PointerState* state) const;
405 
406  // Sends a pointer event to the Flutter engine based on given data. Since
407  // all input messages are passed in physical pixel values, no translation is
408  // needed before passing on to engine.
409  void SendPointerEventWithData(const FlutterPointerEvent& event_data,
410  PointerState* state);
411 
412  // If true, rendering to the window should synchronize with the vsync
413  // to prevent screen tearing.
414  bool NeedsVsync() const;
415 
416  // The view's unique identifier.
417  FlutterViewId view_id_;
418 
419  // The engine associated with this view.
420  FlutterWindowsEngine* engine_ = nullptr;
421 
422  // Mocks win32 APIs.
423  std::shared_ptr<WindowsProcTable> windows_proc_table_;
424 
425  // The EGL surface backing the view.
426  //
427  // Null if using software rasterization, the surface hasn't been created yet,
428  // or if surface creation failed.
429  std::unique_ptr<egl::WindowSurface> surface_ = nullptr;
430 
431  // Keeps track of pointer states in relation to the window.
432  std::unordered_map<int32_t, std::unique_ptr<PointerState>> pointer_states_;
433 
434  // Currently configured WindowBindingHandler for view.
435  std::unique_ptr<WindowBindingHandler> binding_handler_;
436 
437  // Protects resize_status_, resize_target_width_ and resize_target_height_.
438  std::mutex resize_mutex_;
439 
440  // Indicates the state of a window resize event. Platform thread will be
441  // blocked while this is not done. Guarded by resize_mutex_.
442  ResizeState resize_status_ = ResizeState::kDone;
443 
444  // Target for the window width. Valid when resize_pending_ is set. Guarded by
445  // resize_mutex_.
446  size_t resize_target_width_ = 0;
447 
448  // Target for the window width. Valid when resize_pending_ is set. Guarded by
449  // resize_mutex_.
450  size_t resize_target_height_ = 0;
451 
452  // True when flutter's semantics tree is enabled.
453  bool semantics_enabled_ = false;
454 
455  // The accessibility bridge associated with this view.
456  std::shared_ptr<AccessibilityBridgeWindows> accessibility_bridge_;
457 
458  FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsView);
459 };
460 
461 } // namespace flutter
462 
463 #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
virtual void OnPointerPanZoomStart(int32_t device_id) override
void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button) override
FlutterWindowsView(FlutterViewId view_id, FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > window_binding, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
virtual void UpdateSemanticsEnabled(bool enabled)
virtual ui::AXFragmentRootDelegateWin * GetAxFragmentRootDelegate() override
void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state) override
void OnScrollInertiaCancel(int32_t device_id) override
virtual std::shared_ptr< AccessibilityBridgeWindows > CreateAccessibilityBridge()
ui::AXPlatformNodeWin * AlertNode() const
std::weak_ptr< AccessibilityBridgeWindows > accessibility_bridge()
virtual void OnUpdateSemanticsEnabled(bool enabled) override
void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id=0) override
virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin *node, ax::mojom::Event event)
FlutterWindowsEngine * GetEngine() const
void OnScroll(double x, double y, double delta_x, double delta_y, int scroll_offset_multiplier, FlutterPointerDeviceKind device_kind, int32_t device_id) override
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event) override
virtual void OnPointerPanZoomEnd(int32_t device_id) override
FlutterWindowMetricsEvent CreateWindowMetricsEvent() const
void AnnounceAlert(const std::wstring &text)
virtual bool PresentSoftwareBitmap(const void *allocation, size_t row_bytes, size_t height)
void OnFocus(FlutterViewFocusState focus_state, FlutterViewFocusDirection direction) override
virtual HWND GetWindowHandle() const
egl::WindowSurface * surface() const
bool OnWindowSizeChanged(size_t width, size_t height) override
void OnText(const std::u16string &) override
virtual void OnPointerPanZoomUpdate(int32_t device_id, double pan_x, double pan_y, double scale, double rotation) override
void OnComposeChange(const std::u16string &text, int cursor_pos) override
void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, FlutterPointerMouseButtons button) override
virtual gfx::NativeViewAccessible GetNativeViewAccessible() override
virtual void OnCursorRectUpdated(const Rect &rect)
void OnKey(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
bool OnFrameGenerated(size_t width, size_t height)
FlutterDesktopBinaryReply callback
std::u16string text
WindowStateEvent
An event representing a change in window state that may update the.
int64_t FlutterViewId
Definition: flutter_view.h:13