-
Notifications
You must be signed in to change notification settings - Fork 5.9k
/
flutter_windows_view.h
460 lines (361 loc) · 16.3 KB
/
flutter_windows_view.h
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "flutter/fml/macros.h"
#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
#include "flutter/shell/platform/common/geometry.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
#include "flutter/shell/platform/windows/window_state.h"
#include "flutter/shell/platform/windows/windows_proc_table.h"
namespace flutter {
// A unique identifier for a view.
using FlutterViewId = int64_t;
// An OS-windowing neutral abstration for a Flutter view that works
// with win32 HWNDs.
class FlutterWindowsView : public WindowBindingHandlerDelegate {
public:
// Creates a FlutterWindowsView with the given implementor of
// WindowBindingHandler.
FlutterWindowsView(
FlutterViewId view_id,
FlutterWindowsEngine* engine,
std::unique_ptr<WindowBindingHandler> window_binding,
std::shared_ptr<WindowsProcTable> windows_proc_table = nullptr);
virtual ~FlutterWindowsView();
// Get the view's unique identifier.
FlutterViewId view_id() const;
// Whether this view is the implicit view.
//
// The implicit view is a special view for backwards compatibility.
// The engine assumes it can always render to this view, even if the app has
// destroyed the window for this view.
//
// Today, the implicit view is the first view that is created. It is the only
// view that can be created before the engine is launched.
//
// The embedder must ignore presents to this view before it is created and
// after it is destroyed.
//
// See:
// https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/implicitView.html
bool IsImplicitView() const;
// Create a rendering surface for Flutter engine to draw into.
//
// This is a no-op if using software rasterization.
void CreateRenderSurface();
// Get the EGL surface that backs the Flutter view.
//
// This might be nullptr or an invalid surface.
egl::WindowSurface* surface() const;
// Return the currently configured HWND.
virtual HWND GetWindowHandle() const;
// Returns the engine backing this view.
FlutterWindowsEngine* GetEngine() const;
// Tells the engine to generate a new frame
void ForceRedraw();
// Callback to clear a previously presented software bitmap.
virtual bool ClearSoftwareBitmap();
// Callback for presenting a software bitmap.
virtual bool PresentSoftwareBitmap(const void* allocation,
size_t row_bytes,
size_t height);
// Creates a window metric for this view.
//
// Used to notify the engine of a view's current size and device pixel ratio.
FlutterWindowMetricsEvent CreateWindowMetricsEvent() const;
// Send initial bounds to embedder. Must occur after engine has initialized.
//
// This is a no-op if this is not the implicit view. Non-implicit views'
// initial window metrics are sent when the view is added to the engine.
void SendInitialBounds();
// Set the text of the alert, and create it if it does not yet exist.
void AnnounceAlert(const std::wstring& text);
// |WindowBindingHandlerDelegate|
void OnHighContrastChanged() override;
// Called on the raster thread when |CompositorOpenGL| receives an empty
// frame. Returns true if the frame can be presented.
//
// This destroys and then re-creates the view's surface if a resize is
// pending.
bool OnEmptyFrameGenerated();
// Called on the raster thread when |CompositorOpenGL| receives a frame.
// Returns true if the frame can be presented.
//
// This destroys and then re-creates the view's surface if a resize is pending
// and |width| and |height| match the target size.
bool OnFrameGenerated(size_t width, size_t height);
// Called on the raster thread after |CompositorOpenGL| presents a frame.
//
// This completes a view resize if one is pending.
virtual void OnFramePresented();
// Sets the cursor that should be used when the mouse is over the Flutter
// content. See mouse_cursor.dart for the values and meanings of cursor_name.
void UpdateFlutterCursor(const std::string& cursor_name);
// Sets the cursor directly from a cursor handle.
void SetFlutterCursor(HCURSOR cursor);
// |WindowBindingHandlerDelegate|
bool OnWindowSizeChanged(size_t width, size_t height) override;
// |WindowBindingHandlerDelegate|
void OnWindowRepaint() override;
// |WindowBindingHandlerDelegate|
void OnPointerMove(double x,
double y,
FlutterPointerDeviceKind device_kind,
int32_t device_id,
int modifiers_state) override;
// |WindowBindingHandlerDelegate|
void OnPointerDown(double x,
double y,
FlutterPointerDeviceKind device_kind,
int32_t device_id,
FlutterPointerMouseButtons button) override;
// |WindowBindingHandlerDelegate|
void OnPointerUp(double x,
double y,
FlutterPointerDeviceKind device_kind,
int32_t device_id,
FlutterPointerMouseButtons button) override;
// |WindowBindingHandlerDelegate|
void OnPointerLeave(double x,
double y,
FlutterPointerDeviceKind device_kind,
int32_t device_id = 0) override;
// |WindowBindingHandlerDelegate|
virtual void OnPointerPanZoomStart(int32_t device_id) override;
// |WindowBindingHandlerDelegate|
virtual void OnPointerPanZoomUpdate(int32_t device_id,
double pan_x,
double pan_y,
double scale,
double rotation) override;
// |WindowBindingHandlerDelegate|
virtual void OnPointerPanZoomEnd(int32_t device_id) override;
// |WindowBindingHandlerDelegate|
void OnText(const std::u16string&) override;
// |WindowBindingHandlerDelegate|
void OnKey(int key,
int scancode,
int action,
char32_t character,
bool extended,
bool was_down,
KeyEventCallback callback) override;
// |WindowBindingHandlerDelegate|
void OnComposeBegin() override;
// |WindowBindingHandlerDelegate|
void OnComposeCommit() override;
// |WindowBindingHandlerDelegate|
void OnComposeEnd() override;
// |WindowBindingHandlerDelegate|
void OnComposeChange(const std::u16string& text, int cursor_pos) override;
// |WindowBindingHandlerDelegate|
void OnScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier,
FlutterPointerDeviceKind device_kind,
int32_t device_id) override;
// |WindowBindingHandlerDelegate|
void OnScrollInertiaCancel(int32_t device_id) override;
// |WindowBindingHandlerDelegate|
virtual void OnUpdateSemanticsEnabled(bool enabled) override;
// |WindowBindingHandlerDelegate|
virtual gfx::NativeViewAccessible GetNativeViewAccessible() override;
// Notifies the delegate of the updated the cursor rect in Flutter root view
// coordinates.
virtual void OnCursorRectUpdated(const Rect& rect);
// Notifies the delegate that the system IME composing state should be reset.
virtual void OnResetImeComposing();
// Called when a WM_ONCOMPOSITIONCHANGED message is received.
void OnDwmCompositionChanged();
// Get a pointer to the alert node for this view.
ui::AXPlatformNodeWin* AlertNode() const;
// |WindowBindingHandlerDelegate|
virtual ui::AXFragmentRootDelegateWin* GetAxFragmentRootDelegate() override;
// Called to re/set the accessibility bridge pointer.
virtual void UpdateSemanticsEnabled(bool enabled);
std::weak_ptr<AccessibilityBridgeWindows> accessibility_bridge() {
return accessibility_bridge_;
}
// |WindowBindingHandlerDelegate|
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event) override;
protected:
virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
ax::mojom::Event event);
// Create an AccessibilityBridgeWindows using this view.
virtual std::shared_ptr<AccessibilityBridgeWindows>
CreateAccessibilityBridge();
private:
// Allows setting the surface in tests.
friend class ViewModifier;
// Struct holding the state of an individual pointer. The engine doesn't keep
// track of which buttons have been pressed, so it's the embedding's
// responsibility.
struct PointerState {
// The device kind.
FlutterPointerDeviceKind device_kind = kFlutterPointerDeviceKindMouse;
// A virtual pointer ID that is unique across all device kinds.
int32_t pointer_id = 0;
// True if the last event sent to Flutter had at least one button pressed.
bool flutter_state_is_down = false;
// True if kAdd has been sent to Flutter. Used to determine whether
// to send a kAdd event before sending an incoming pointer event, since
// Flutter expects pointers to be added before events are sent for them.
bool flutter_state_is_added = false;
// The currently pressed buttons, as represented in FlutterPointerEvent.
uint64_t buttons = 0;
// The x position where the last pan/zoom started.
double pan_zoom_start_x = 0;
// The y position where the last pan/zoom started.
double pan_zoom_start_y = 0;
};
// States a resize event can be in.
enum class ResizeState {
// When a resize event has started but is in progress.
kResizeStarted,
// After a resize event starts and the framework has been notified to
// generate a frame for the right size.
kFrameGenerated,
// Default state for when no resize is in progress. Also used to indicate
// that during a resize event, a frame with the right size has been rendered
// and the buffers have been swapped.
kDone,
};
// Resize the surface to the desired size.
//
// If the dimensions have changed, this destroys the original surface and
// creates a new one.
//
// This must be run on the raster thread. This binds the surface to the
// current thread.
//
// Width and height are the surface's desired physical pixel dimensions.
bool ResizeRenderSurface(size_t width, size_t height);
// Sends a window metrics update to the Flutter engine using current window
// dimensions in physical pixels.
void SendWindowMetrics(size_t width, size_t height, double pixel_ratio) const;
// Reports a mouse movement to Flutter engine.
void SendPointerMove(double x, double y, PointerState* state);
// Reports mouse press to Flutter engine.
void SendPointerDown(double x, double y, PointerState* state);
// Reports mouse release to Flutter engine.
void SendPointerUp(double x, double y, PointerState* state);
// Reports mouse left the window client area.
//
// Win32 api doesn't have "mouse enter" event. Therefore, there is no
// SendPointerEnter method. A mouse enter event is tracked then the "move"
// event is called.
void SendPointerLeave(double x, double y, PointerState* state);
void SendPointerPanZoomStart(int32_t device_id, double x, double y);
void SendPointerPanZoomUpdate(int32_t device_id,
double pan_x,
double pan_y,
double scale,
double rotation);
void SendPointerPanZoomEnd(int32_t device_id);
// Reports a keyboard character to Flutter engine.
void SendText(const std::u16string&);
// Reports a raw keyboard message to Flutter engine.
void SendKey(int key,
int scancode,
int action,
char32_t character,
bool extended,
bool was_down,
KeyEventCallback callback);
// Reports an IME compose begin event.
//
// Triggered when the user begins editing composing text using a multi-step
// input method such as in CJK text input.
void SendComposeBegin();
// Reports an IME compose commit event.
//
// Triggered when the user commits the current composing text while using a
// multi-step input method such as in CJK text input. Composing continues with
// the next keypress.
void SendComposeCommit();
// Reports an IME compose end event.
//
// Triggered when the user commits the composing text while using a multi-step
// input method such as in CJK text input.
void SendComposeEnd();
// Reports an IME composing region change event.
//
// Triggered when the user edits the composing text while using a multi-step
// input method such as in CJK text input.
void SendComposeChange(const std::u16string& text, int cursor_pos);
// Reports scroll wheel events to Flutter engine.
void SendScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier,
FlutterPointerDeviceKind device_kind,
int32_t device_id);
// Reports scroll inertia cancel events to Flutter engine.
void SendScrollInertiaCancel(int32_t device_id, double x, double y);
// Creates a PointerState object unless it already exists.
PointerState* GetOrCreatePointerState(FlutterPointerDeviceKind device_kind,
int32_t device_id);
// Sets |event_data|'s phase to either kMove or kHover depending on the
// current primary mouse button state.
void SetEventPhaseFromCursorButtonState(FlutterPointerEvent* event_data,
const PointerState* state) const;
// Sends a pointer event to the Flutter engine based on given data. Since
// all input messages are passed in physical pixel values, no translation is
// needed before passing on to engine.
void SendPointerEventWithData(const FlutterPointerEvent& event_data,
PointerState* state);
// If true, rendering to the window should synchronize with the vsync
// to prevent screen tearing.
bool NeedsVsync() const;
// The view's unique identifier.
FlutterViewId view_id_;
// The engine associated with this view.
FlutterWindowsEngine* engine_ = nullptr;
// Mocks win32 APIs.
std::shared_ptr<WindowsProcTable> windows_proc_table_;
// The EGL surface backing the view.
//
// Null if using software rasterization, the surface hasn't been created yet,
// or if surface creation failed.
std::unique_ptr<egl::WindowSurface> surface_ = nullptr;
// Keeps track of pointer states in relation to the window.
std::unordered_map<int32_t, std::unique_ptr<PointerState>> pointer_states_;
// Currently configured WindowBindingHandler for view.
std::unique_ptr<WindowBindingHandler> binding_handler_;
// Resize events are synchronized using this mutex and the corresponding
// condition variable.
std::mutex resize_mutex_;
std::condition_variable resize_cv_;
// Indicates the state of a window resize event. Platform thread will be
// blocked while this is not done. Guarded by resize_mutex_.
ResizeState resize_status_ = ResizeState::kDone;
// Target for the window width. Valid when resize_pending_ is set. Guarded by
// resize_mutex_.
size_t resize_target_width_ = 0;
// Target for the window width. Valid when resize_pending_ is set. Guarded by
// resize_mutex_.
size_t resize_target_height_ = 0;
// True when flutter's semantics tree is enabled.
bool semantics_enabled_ = false;
// The accessibility bridge associated with this view.
std::shared_ptr<AccessibilityBridgeWindows> accessibility_bridge_;
FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsView);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_