| // Copyright 2016 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_TEST_TEST_WAYLAND_SERVER_THREAD_H_ |
| #define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_SERVER_THREAD_H_ |
| |
| #include <wayland-server-core.h> |
| |
| #include <cstdint> |
| #include <memory> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/message_loop/message_pump_libevent.h" |
| #include "base/threading/thread.h" |
| #include "base/threading/thread_checker.h" |
| #include "ui/display/types/display_constants.h" |
| #include "ui/ozone/platform/wayland/test/global_object.h" |
| #include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" |
| #include "ui/ozone/platform/wayland/test/mock_wp_presentation.h" |
| #include "ui/ozone/platform/wayland/test/mock_xdg_activation_v1.h" |
| #include "ui/ozone/platform/wayland/test/mock_xdg_shell.h" |
| #include "ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h" |
| #include "ui/ozone/platform/wayland/test/test_alpha_compositing.h" |
| #include "ui/ozone/platform/wayland/test/test_compositor.h" |
| #include "ui/ozone/platform/wayland/test/test_data_device_manager.h" |
| #include "ui/ozone/platform/wayland/test/test_output.h" |
| #include "ui/ozone/platform/wayland/test/test_overlay_prioritizer.h" |
| #include "ui/ozone/platform/wayland/test/test_seat.h" |
| #include "ui/ozone/platform/wayland/test/test_subcompositor.h" |
| #include "ui/ozone/platform/wayland/test/test_surface_augmenter.h" |
| #include "ui/ozone/platform/wayland/test/test_viewporter.h" |
| #include "ui/ozone/platform/wayland/test/test_wp_pointer_gestures.h" |
| #include "ui/ozone/platform/wayland/test/test_zaura_output_manager.h" |
| #include "ui/ozone/platform/wayland/test/test_zaura_shell.h" |
| #include "ui/ozone/platform/wayland/test/test_zcr_stylus.h" |
| #include "ui/ozone/platform/wayland/test/test_zcr_text_input_extension.h" |
| #include "ui/ozone/platform/wayland/test/test_zwp_linux_explicit_synchronization.h" |
| #include "ui/ozone/platform/wayland/test/test_zwp_text_input_manager.h" |
| #include "ui/ozone/platform/wayland/test/test_zxdg_output_manager.h" |
| |
| struct wl_client; |
| struct wl_display; |
| struct wl_event_loop; |
| struct wl_resource; |
| |
| namespace wl { |
| |
| struct DisplayDeleter { |
| void operator()(wl_display* display); |
| }; |
| |
| // Server configuration related enums and structs. |
| enum class PrimarySelectionProtocol { kNone, kGtk, kZwp }; |
| enum class ShouldUseExplicitSynchronizationProtocol { kNone, kUse }; |
| enum class EnableAuraShellProtocol { kEnabled, kDisabled }; |
| |
| struct ServerConfig { |
| TestZcrTextInputExtensionV1::Version text_input_extension_version = |
| TestZcrTextInputExtensionV1::Version::kV10; |
| TestCompositor::Version compositor_version = TestCompositor::Version::kV4; |
| PrimarySelectionProtocol primary_selection_protocol = |
| PrimarySelectionProtocol::kNone; |
| ShouldUseExplicitSynchronizationProtocol use_explicit_synchronization = |
| ShouldUseExplicitSynchronizationProtocol::kUse; |
| EnableAuraShellProtocol enable_aura_shell = |
| EnableAuraShellProtocol::kDisabled; |
| bool surface_submission_in_pixel_coordinates = true; |
| bool supports_viewporter_surface_scaling = false; |
| bool use_aura_output_manager = false; |
| bool use_ime_keep_selection_fix = false; |
| }; |
| |
| class TestWaylandServerThread; |
| |
| // A custom listener that holds wl_listener and the pointer to a test_server. |
| struct TestServerListener { |
| public: |
| explicit TestServerListener(TestWaylandServerThread* server) |
| : test_server(server) {} |
| wl_listener listener; |
| const raw_ptr<TestWaylandServerThread> test_server; |
| }; |
| |
| class TestSelectionDeviceManager; |
| |
| class TestWaylandServerThread : public base::Thread, |
| base::MessagePumpLibevent::FdWatcher { |
| public: |
| class OutputDelegate; |
| |
| TestWaylandServerThread(); |
| explicit TestWaylandServerThread(const ServerConfig& config); |
| |
| TestWaylandServerThread(const TestWaylandServerThread&) = delete; |
| TestWaylandServerThread& operator=(const TestWaylandServerThread&) = delete; |
| |
| ~TestWaylandServerThread() override; |
| |
| // Starts the test Wayland server thread. If this succeeds, the WAYLAND_SOCKET |
| // environment variable will be set to the string representation of a file |
| // descriptor that a client can connect to. The caller is responsible for |
| // ensuring that this file descriptor gets closed (for example, by calling |
| // wl_display_connect). |
| bool Start(); |
| |
| // Runs 'callback' or 'closure' on the server thread; blocks until the |
| // callable is run and all pending Wayland requests and events are delivered. |
| void RunAndWait(base::OnceCallback<void(TestWaylandServerThread*)> callback); |
| void RunAndWait(base::OnceClosure closure); |
| |
| // Returns WpPresentation. If it hasn't been initialized yet, initializes that |
| // first and then returns. |
| MockWpPresentation* EnsureAndGetWpPresentation(); |
| // Initializes and returns SurfaceAugmenter. |
| TestSurfaceAugmenter* EnsureSurfaceAugmenter(); |
| |
| template <typename T> |
| T* GetObject(uint32_t id) { |
| // All the protocol calls must be made on the correct thread. |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| wl_resource* resource = wl_client_get_object(client_, id); |
| return resource ? T::FromResource(resource) : nullptr; |
| } |
| |
| TestOutput* CreateAndInitializeOutput(TestOutputMetrics metrics = {}) { |
| auto output = std::make_unique<TestOutput>( |
| base::BindRepeating(&TestWaylandServerThread::OnTestOutputMetricsFlush, |
| base::Unretained(this)), |
| std::move(metrics)); |
| if (output_.aura_shell_enabled()) { |
| output->set_aura_shell_enabled(); |
| } |
| output->Initialize(display()); |
| |
| TestOutput* output_ptr = output.get(); |
| globals_.push_back(std::move(output)); |
| return output_ptr; |
| } |
| |
| // Called when the Flush() is called for a TestOutput associated with |
| // `output_resource`. When called sends the corresponding events for the |
| // `metrics` to clients of the zaura_output_manager. |
| void OnTestOutputMetricsFlush(wl_resource* output_resource, |
| const TestOutputMetrics& metrics); |
| |
| TestDataDeviceManager* data_device_manager() { return &data_device_manager_; } |
| TestSeat* seat() { return &seat_; } |
| MockXdgShell* xdg_shell() { return &xdg_shell_; } |
| TestZAuraOutputManager* zaura_output_manager() { |
| return &zaura_output_manager_; |
| } |
| TestZAuraShell* zaura_shell() { return &zaura_shell_; } |
| TestOutput* output() { return &output_; } |
| TestZcrTextInputExtensionV1* text_input_extension_v1() { |
| return &zcr_text_input_extension_v1_; |
| } |
| TestZwpTextInputManagerV1* text_input_manager_v1() { |
| return &zwp_text_input_manager_v1_; |
| } |
| TestZwpLinuxExplicitSynchronizationV1* |
| zwp_linux_explicit_synchronization_v1() { |
| return &zwp_linux_explicit_synchronization_v1_; |
| } |
| MockZwpLinuxDmabufV1* zwp_linux_dmabuf_v1() { return &zwp_linux_dmabuf_v1_; } |
| |
| wl_display* display() const { return display_.get(); } |
| |
| TestSelectionDeviceManager* primary_selection_device_manager() { |
| return primary_selection_device_manager_.get(); |
| } |
| |
| TestWpPointerGestures& wp_pointer_gestures() { return wp_pointer_gestures_; } |
| |
| MockZcrColorManagerV1* zcr_color_manager_v1() { |
| return &zcr_color_manager_v1_; |
| } |
| |
| MockXdgActivationV1* xdg_activation_v1() { return &xdg_activation_v1_; } |
| |
| void set_output_delegate(OutputDelegate* delegate) { |
| output_delegate_ = delegate; |
| } |
| |
| wl_client* client() const { return client_; } |
| |
| void OnClientDestroyed(wl_client* client); |
| |
| // Returns next available serial. Must be called on the server thread. |
| uint32_t GetNextSerial() const; |
| // Returns next available timestamp. Suitable for events sent from the server |
| // the client. Must be called on the server thread. |
| uint32_t GetNextTime(); |
| |
| private: |
| void SetupOutputs(); |
| bool SetupPrimarySelectionManager(PrimarySelectionProtocol protocol); |
| bool SetupExplicitSynchronizationProtocol( |
| ShouldUseExplicitSynchronizationProtocol usage); |
| |
| std::unique_ptr<base::MessagePump> CreateMessagePump(); |
| |
| // Executes the closure and flushes the server event queue. Must be run on |
| // server's thread. |
| void DoRun(base::OnceClosure closure); |
| |
| // base::MessagePumpLibevent::FdWatcher |
| void OnFileCanReadWithoutBlocking(int fd) override; |
| void OnFileCanWriteWithoutBlocking(int fd) override; |
| |
| // wl_protocol_logger. Whenever there is a call to a protocol from the server |
| // side, the logger is invoked. This is handy as we can use this to verify all |
| // the protocol calls happen only when the server thread is not running. This |
| // helps to avoid thread races as the client runs on a different from the |
| // server tread. |
| static void ProtocolLogger(void* user_data, |
| enum wl_protocol_logger_type direction, |
| const struct wl_protocol_logger_message* message); |
| |
| std::unique_ptr<wl_display, DisplayDeleter> display_; |
| TestServerListener client_destroy_listener_; |
| raw_ptr<wl_client> client_ = nullptr; |
| raw_ptr<wl_event_loop> event_loop_ = nullptr; |
| raw_ptr<wl_protocol_logger> protocol_logger_ = nullptr; |
| |
| ServerConfig config_; |
| |
| // Represent Wayland global objects |
| TestCompositor compositor_; |
| |
| TestSubCompositor sub_compositor_; |
| TestViewporter viewporter_; |
| TestAlphaCompositing alpha_compositing_; |
| TestDataDeviceManager data_device_manager_; |
| TestOutput output_; |
| TestOverlayPrioritizer overlay_prioritizer_; |
| TestSurfaceAugmenter surface_augmenter_; |
| TestSeat seat_; |
| TestZXdgOutputManager zxdg_output_manager_; |
| MockXdgShell xdg_shell_; |
| TestZAuraOutputManager zaura_output_manager_; |
| TestZAuraShell zaura_shell_; |
| MockZcrColorManagerV1 zcr_color_manager_v1_; |
| TestZcrStylus zcr_stylus_; |
| TestZcrTextInputExtensionV1 zcr_text_input_extension_v1_; |
| TestZwpTextInputManagerV1 zwp_text_input_manager_v1_; |
| TestZwpLinuxExplicitSynchronizationV1 zwp_linux_explicit_synchronization_v1_; |
| MockZwpLinuxDmabufV1 zwp_linux_dmabuf_v1_; |
| MockWpPresentation wp_presentation_; |
| TestWpPointerGestures wp_pointer_gestures_; |
| MockXdgActivationV1 xdg_activation_v1_; |
| std::unique_ptr<TestSelectionDeviceManager> primary_selection_device_manager_; |
| |
| std::vector<std::unique_ptr<GlobalObject>> globals_; |
| |
| base::MessagePumpLibevent::FdWatchController controller_; |
| |
| raw_ptr<OutputDelegate> output_delegate_ = nullptr; |
| |
| THREAD_CHECKER(thread_checker_); |
| }; |
| |
| class TestWaylandServerThread::OutputDelegate { |
| public: |
| // Tests may implement this such that it emulates different display/output |
| // test scenarios. For example, multi-screen, lazy configuration, arbitrary |
| // ordering of the outputs metadata events, etc. |
| virtual void SetupOutputs(TestOutput* primary_output) = 0; |
| |
| protected: |
| virtual ~OutputDelegate() = default; |
| }; |
| |
| } // namespace wl |
| |
| #endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_SERVER_THREAD_H_ |