File: wayland_input_emulate.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (198 lines) | stat: -rw-r--r-- 7,500 bytes parent folder | download | duplicates (3)
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
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_OZONE_PLATFORM_WAYLAND_EMULATE_WAYLAND_INPUT_EMULATE_H_
#define UI_OZONE_PLATFORM_WAYLAND_EMULATE_WAYLAND_INPUT_EMULATE_H_

#include <wayland-util.h>

#include <memory>
#include <string>

#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/base/test/ui_controls.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/proxy/wayland_proxy.h"

struct wl_buffer;
struct wl_registry;
struct zcr_ui_controls_v2;
struct wl_callback;

namespace wl {

// Uses the ui_controls protocol extension to emulate Keyboard, Pointer, and
// Touch events that the interactive_ui_tests test suite sends. Mustn't be
// linked in production code.
class WaylandInputEmulate : public wl::WaylandProxy::Delegate {
 public:
  explicit WaylandInputEmulate(base::RepeatingCallback<void(uint32_t)>);
  ~WaylandInputEmulate() override;

  // |key_state| is a bit-mask of ui_controls::KeyEventType.
  // |accelerator_state| is a bit-mask of ui_controls::AcceleratorState.
  void EmulateKeyboardKey(ui::DomCode dom_code,
                          int key_state,
                          int accelerator_state,
                          uint32_t request_id);

  // Both |mouse_surface_location| and |mouse_screen_location| are in DIP.
  void EmulatePointerMotion(gfx::AcceleratedWidget widget,
                            const gfx::Point& mouse_surface_location,
                            const gfx::Point& mouse_screen_location,
                            uint32_t request_id);

  // |button_state| is a bit-mask of ui_controls::MouseButtonState.
  // |accelerator_state| is a bit-mask of ui_controls::AcceleratorState.
  void EmulatePointerButton(ui_controls::MouseButton button,
                            int button_state,
                            int accelerator_state,
                            uint32_t request_id);

  void ForceUseScreenCoordinatesOnce();

 private:
  enum PendingRequestType {
    KeyPress,
    MouseMove,
    MouseButton,
  };

  // Pending emulation request.
  struct PendingRequest {
    PendingRequest(PendingRequestType request_type, uint32_t request_id);
    ~PendingRequest();

    PendingRequestType type;
    uint32_t request_id;

    // Set for type == KeyPress || type == MouseButton. A bit-mask of
    // ui_controls::AcceleratorState.
    int accelerator_state;

    // Set for type == KeyPress. |key_state| is a bit-mask of
    // ui_controls::KeyEventType.
    ui::DomCode key_dom_code = ui::DomCode::NONE;
    int key_state;

    // Set for type == MouseMove. We hold on to |widget| because we only decide
    // whether to use screen or surface-local coordinates after the window has
    // been configured.
    gfx::AcceleratedWidget widget;
    gfx::Point mouse_surface_location;
    gfx::Point mouse_screen_location;

    // Set for type == MouseButton. |button_state| is a bit-mask of
    // ui_controls::MouseButtonState.
    ui_controls::MouseButton button;
    int button_state;

    // Set for type == Touch. |action| is a bit-mask of ui_controls::TouchType.
    // |touch_screen_location| is in DIP screen coordinates.
    int action = 0;
    gfx::Point touch_screen_location;
    int touch_id = 0;
  };

  // A container that tracks created WaylandWindows and keeps some fundamental
  // bits to make emulation work flawlessly.
  struct TestWindow {
    TestWindow();
    ~TestWindow();

    // Control flag that says if the buffer has been attached and a consequent
    // frame callback has been received. This is required to be able to know
    // that the surface has consumed the attached buffer and Wayland properly
    // set the size of the surface. Otherwise, the surface in question may not
    // receive any events. Set during WaylandInputEmulate::FrameCallbackHandler
    // call.
    bool buffer_attached_and_configured = false;

    // Frame callback that invokes WaylandInputEmulate::FrameCallbackHandler.
    raw_ptr<wl_callback> frame_callback = nullptr;

    // The attached buffer.
    raw_ptr<wl_buffer> buffer = nullptr;

    // True if the window was created or assigned a role and is now waiting for
    // a buffer to be committed.
    bool waiting_for_buffer_commit = false;

    base::WeakPtrFactory<TestWindow> weak_factory{this};
  };

  // Destroys `window`'s frame callback and buffer.
  void DestroyTestWindowState(TestWindow* window);

  // WaylandProxy::Delegate:
  void OnWindowAdded(gfx::AcceleratedWidget widget) override;
  void OnWindowRemoved(gfx::AcceleratedWidget widget) override;
  void OnWindowConfigured(gfx::AcceleratedWidget widget,
                          bool is_configured) override;
  void OnWindowRoleAssigned(gfx::AcceleratedWidget widget) override;

  // zcr_ui_controls_v2_listener callbacks:
  static void OnRequestProcessed(void* data,
                                 zcr_ui_controls_v2* ui_controls,
                                 uint32_t id);

  // wl_registry_listener callbacks:
  static void OnGlobal(void* data,
                       wl_registry* registry,
                       uint32_t name,
                       const char* interface,
                       uint32_t version);

  // wl_registry_listener callbacks:
  static void OnGlobalRemove(void* data, wl_registry* registry, uint32_t name);

  // wl_callback_listener callbacks:
  static void OnFrameDone(void* data, wl_callback* callback, uint32_t time);

  // Returns true if there is at least one window that has been created but that
  // does not yet have a buffer committed.
  bool AnyWindowWaitingForBufferCommit();

  // Dispatches all pending requests.
  void DispatchPendingRequests();

  // Window creation is asynchronous in wayland. First we create the window,
  // then we must attach and commit a buffer before the server will treat it
  // properly w.r.t. input events. This member stores all windows that have been
  // created.
  base::flat_map<gfx::AcceleratedWidget,
                 std::unique_ptr<WaylandInputEmulate::TestWindow>>
      windows_;

  // Stores pending requests in a global queue. We will not dispatch any pending
  // requests while there are windows that are still in the process of being
  // created.
  base::circular_deque<std::unique_ptr<PendingRequest>> pending_requests_;

  base::RepeatingCallback<void(uint32_t)> request_processed_callback_;

  // If true, the next `EmulatePointerMotion` call will use global screen
  // coordinates, i.e. send zcr_ui_controls_v2.mouse_move with the `surface`
  // parameter set to NULL.
  // Note: this does not affect whether `EmulatePointerMotion` uses the
  // coordinates from its `mouse_surface_location` or `mouse_screen_location`
  // parameter. See the comment in that method's definition for more details.
  bool force_use_screen_coordinates_once_ = false;

  // Owned raw pointers. wl::Object is not used because the component this
  // class belongs to cannot depend on the "wayland" target in the
  // //ui/ozone/platform/wayland/BUILD.gn
  raw_ptr<wl_registry> registry_ = nullptr;
  raw_ptr<zcr_ui_controls_v2> ui_controls_ = nullptr;
};

}  // namespace wl

#endif  // UI_OZONE_PLATFORM_WAYLAND_EMULATE_WAYLAND_INPUT_EMULATE_H_