| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/exo/wayland/clients/test/client_version_test.h" |
| |
| #include <alpha-compositing-unstable-v1-client-protocol.h> |
| #include <aura-shell-server-protocol.h> |
| #include <chrome-color-management-server-protocol.h> |
| #include <content-type-v1-server-protocol.h> |
| #include <cursor-shapes-unstable-v1-server-protocol.h> |
| #include <extended-drag-unstable-v1-server-protocol.h> |
| #include <gaming-input-unstable-v2-server-protocol.h> |
| #include <idle-inhibit-unstable-v1-server-protocol.h> |
| #include <keyboard-configuration-unstable-v1-server-protocol.h> |
| #include <keyboard-extension-unstable-v1-server-protocol.h> |
| #include <keyboard-shortcuts-inhibit-unstable-v1-server-protocol.h> |
| #include <notification-shell-unstable-v1-server-protocol.h> |
| #include <overlay-prioritizer-server-protocol.h> |
| #include <pointer-constraints-unstable-v1-server-protocol.h> |
| #include <pointer-gestures-unstable-v1-server-protocol.h> |
| #include <relative-pointer-unstable-v1-server-protocol.h> |
| #include <remote-shell-unstable-v1-server-protocol.h> |
| #include <remote-shell-unstable-v2-server-protocol.h> |
| #include <secure-output-unstable-v1-server-protocol.h> |
| #include <stylus-tools-unstable-v1-server-protocol.h> |
| #include <stylus-unstable-v2-server-protocol.h> |
| #include <surface-augmenter-server-protocol.h> |
| #include <text-input-extension-unstable-v1-server-protocol.h> |
| #include <text-input-unstable-v1-server-protocol.h> |
| #include <touchpad-haptics-unstable-v1-server-protocol.h> |
| #include <viewporter-client-protocol.h> |
| #include <wayland-client-core.h> |
| #include <wayland-client-protocol.h> |
| #include <weston-test-server-protocol.h> |
| #include <xdg-decoration-unstable-v1-server-protocol.h> |
| #include <xdg-shell-server-protocol.h> |
| #include <xdg-shell-unstable-v6-server-protocol.h> |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <utility> |
| |
| #include "base/check_op.h" |
| #include "base/logging.h" |
| |
| #include "components/exo/wayland/clients/client_helper.h" |
| |
| namespace exo { |
| namespace wayland { |
| namespace clients { |
| namespace { |
| |
| struct Globals { |
| Globals() = default; |
| ~Globals() = default; |
| |
| std::unique_ptr<wl_compositor> compositor; |
| std::vector<std::string> protocols; |
| std::string protocol_tested; |
| ClientVersionTest::VersionValidityType validity_type = |
| ClientVersionTest::VersionValidityType::VALID_ADVERTISED; |
| std::unique_ptr<surface_augmenter> surface_augmenter; |
| std::unique_ptr<overlay_prioritizer> overlay_prioritizer; |
| std::unique_ptr<wl_shm> wl_shm; |
| std::unique_ptr<wl_shell> wl_shell; |
| std::unique_ptr<wl_seat> wl_seat; |
| std::unique_ptr<wp_presentation> wp_presentation; |
| std::unique_ptr<zaura_output_manager> zaura_output_manager; |
| std::unique_ptr<zaura_shell> zaura_shell; |
| std::unique_ptr<zwp_linux_dmabuf_v1> zwp_linux_dmabuf_v1; |
| std::unique_ptr<wl_subcompositor> wl_subcompositor; |
| std::unique_ptr<zwp_input_timestamps_manager_v1> |
| zwp_input_timestamps_manager_v1; |
| std::unique_ptr<zwp_fullscreen_shell_v1> zwp_fullscreen_shell_v1; |
| std::unique_ptr<wl_output> wl_output; |
| std::unique_ptr<zwp_linux_explicit_synchronization_v1> |
| zwp_linux_explicit_synchronization_v1; |
| std::unique_ptr<zcr_vsync_feedback_v1> zcr_vsync_feedback_v1; |
| std::unique_ptr<wl_data_device_manager> wl_data_device_manager; |
| std::unique_ptr<wp_content_type_manager_v1> wp_content_type_manager_v1; |
| std::unique_ptr<wp_viewporter> wp_viewporter; |
| std::unique_ptr<zxdg_shell_v6> zxdg_shell_v6; |
| std::unique_ptr<xdg_wm_base> xdg_wm_base; |
| std::unique_ptr<zwp_text_input_manager_v1> zwp_text_input_manager_v1; |
| std::unique_ptr<zcr_secure_output_v1> zcr_secure_output_v1; |
| std::unique_ptr<zcr_alpha_compositing_v1> zcr_alpha_compositing_v1; |
| std::unique_ptr<zcr_stylus_v2> zcr_stylus_v2; |
| std::unique_ptr<zcr_color_manager_v1> zcr_color_manager_v1; |
| std::unique_ptr<zcr_cursor_shapes_v1> zcr_cursor_shapes_v1; |
| std::unique_ptr<zcr_gaming_input_v2> zcr_gaming_input_v2; |
| std::unique_ptr<zcr_text_input_extension_v1> zcr_text_input_extension_v1; |
| std::unique_ptr<zcr_keyboard_configuration_v1> zcr_keyboard_configuration_v1; |
| std::unique_ptr<zcr_keyboard_extension_v1> zcr_keyboard_extension_v1; |
| std::unique_ptr<zwp_keyboard_shortcuts_inhibit_manager_v1> |
| zwp_keyboard_shortcuts_inhibit_manager_v1; |
| std::unique_ptr<zcr_notification_shell_v1> zcr_notification_shell_v1; |
| std::unique_ptr<zcr_remote_shell_v1> zcr_remote_shell_v1; |
| std::unique_ptr<zcr_remote_shell_v2> zcr_remote_shell_v2; |
| std::unique_ptr<zcr_stylus_tools_v1> zcr_stylus_tools_v1; |
| std::unique_ptr<zcr_touchpad_haptics_v1> zcr_touchpad_haptics_v1; |
| std::unique_ptr<zwp_pointer_gestures_v1> zwp_pointer_gestures_v1; |
| std::unique_ptr<zwp_pointer_constraints_v1> zwp_pointer_constraints_v1; |
| std::unique_ptr<zwp_relative_pointer_manager_v1> |
| zwp_relative_pointer_manager_v1; |
| std::unique_ptr<zxdg_decoration_manager_v1> zxdg_decoration_manager_v1; |
| std::unique_ptr<zcr_extended_drag_v1> zcr_extended_drag_v1; |
| std::unique_ptr<zxdg_output_manager_v1> zxdg_output_manager_v1; |
| std::unique_ptr<weston_test> weston_test; |
| std::unique_ptr<zwp_idle_inhibit_manager_v1> zwp_idle_inhibit_manager_v1; |
| }; |
| |
| typedef void (*InterfaceRegistryCallback)(Globals*, |
| wl_registry*, |
| uint32_t, |
| uint32_t); |
| |
| #define REGISTRY_CALLBACK(field, t) \ |
| { \ |
| #t, [](Globals* globals, wl_registry* registry, \ |
| uint32_t id, uint32_t version) { \ |
| globals->field.reset(static_cast<t*>( \ |
| wl_registry_bind(registry, id, &(t##_interface), version))); \ |
| } \ |
| } |
| |
| void RegistryHandler(void* data, |
| wl_registry* registry, |
| uint32_t id, |
| const char* interface, |
| uint32_t version) { |
| Globals* globals = static_cast<Globals*>(data); |
| if (globals->protocol_tested.length() == 0) { |
| globals->protocols.push_back(interface); |
| return; |
| } else if (strcmp(interface, globals->protocol_tested.c_str()) == 0) { |
| switch (globals->validity_type) { |
| case ClientVersionTest::VersionValidityType::INVALID_NULL: |
| version = 0; |
| break; |
| case ClientVersionTest::VersionValidityType::VALID_SKEWED: |
| if (version > 1) { |
| version = version - 1; |
| } |
| break; |
| case ClientVersionTest::VersionValidityType::INVALID_UNSUPPORTED: |
| version = version + 1; |
| break; |
| case ClientVersionTest::VersionValidityType::VALID_ADVERTISED: |
| default: |
| // Use advertised |
| break; |
| } |
| } |
| |
| std::unordered_map<std::string, InterfaceRegistryCallback> |
| interfaces_callbacks = { |
| REGISTRY_CALLBACK(compositor, wl_compositor), |
| REGISTRY_CALLBACK(wl_shm, wl_shm), |
| REGISTRY_CALLBACK(wl_shell, wl_shell), |
| REGISTRY_CALLBACK(wl_seat, wl_seat), |
| REGISTRY_CALLBACK(wp_presentation, wp_presentation), |
| REGISTRY_CALLBACK(zaura_output_manager, zaura_output_manager), |
| REGISTRY_CALLBACK(zaura_shell, zaura_shell), |
| REGISTRY_CALLBACK(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1), |
| REGISTRY_CALLBACK(wl_subcompositor, wl_subcompositor), |
| REGISTRY_CALLBACK(zwp_input_timestamps_manager_v1, |
| zwp_input_timestamps_manager_v1), |
| REGISTRY_CALLBACK(zwp_fullscreen_shell_v1, zwp_fullscreen_shell_v1), |
| REGISTRY_CALLBACK(wl_output, wl_output), |
| REGISTRY_CALLBACK(zwp_linux_explicit_synchronization_v1, |
| zwp_linux_explicit_synchronization_v1), |
| REGISTRY_CALLBACK(zcr_vsync_feedback_v1, zcr_vsync_feedback_v1), |
| REGISTRY_CALLBACK(wl_data_device_manager, wl_data_device_manager), |
| REGISTRY_CALLBACK(wp_content_type_manager_v1, |
| wp_content_type_manager_v1), |
| REGISTRY_CALLBACK(wp_viewporter, wp_viewporter), |
| REGISTRY_CALLBACK(zxdg_shell_v6, zxdg_shell_v6), |
| REGISTRY_CALLBACK(xdg_wm_base, xdg_wm_base), |
| REGISTRY_CALLBACK(zwp_text_input_manager_v1, |
| zwp_text_input_manager_v1), |
| REGISTRY_CALLBACK(zcr_secure_output_v1, zcr_secure_output_v1), |
| REGISTRY_CALLBACK(zcr_alpha_compositing_v1, zcr_alpha_compositing_v1), |
| REGISTRY_CALLBACK(zcr_stylus_v2, zcr_stylus_v2), |
| REGISTRY_CALLBACK(zcr_color_manager_v1, zcr_color_manager_v1), |
| REGISTRY_CALLBACK(zcr_cursor_shapes_v1, zcr_cursor_shapes_v1), |
| REGISTRY_CALLBACK(zcr_gaming_input_v2, zcr_gaming_input_v2), |
| REGISTRY_CALLBACK(zcr_keyboard_configuration_v1, |
| zcr_keyboard_configuration_v1), |
| REGISTRY_CALLBACK(zcr_keyboard_extension_v1, |
| zcr_keyboard_extension_v1), |
| REGISTRY_CALLBACK(zwp_keyboard_shortcuts_inhibit_manager_v1, |
| zwp_keyboard_shortcuts_inhibit_manager_v1), |
| REGISTRY_CALLBACK(zcr_notification_shell_v1, |
| zcr_notification_shell_v1), |
| REGISTRY_CALLBACK(zcr_remote_shell_v1, zcr_remote_shell_v1), |
| REGISTRY_CALLBACK(zcr_remote_shell_v2, zcr_remote_shell_v2), |
| REGISTRY_CALLBACK(zcr_stylus_tools_v1, zcr_stylus_tools_v1), |
| REGISTRY_CALLBACK(zcr_text_input_extension_v1, |
| zcr_text_input_extension_v1), |
| REGISTRY_CALLBACK(zcr_touchpad_haptics_v1, zcr_touchpad_haptics_v1), |
| REGISTRY_CALLBACK(zwp_pointer_gestures_v1, zwp_pointer_gestures_v1), |
| REGISTRY_CALLBACK(zwp_pointer_constraints_v1, |
| zwp_pointer_constraints_v1), |
| REGISTRY_CALLBACK(zwp_relative_pointer_manager_v1, |
| zwp_relative_pointer_manager_v1), |
| REGISTRY_CALLBACK(zxdg_decoration_manager_v1, |
| zxdg_decoration_manager_v1), |
| REGISTRY_CALLBACK(zcr_extended_drag_v1, zcr_extended_drag_v1), |
| REGISTRY_CALLBACK(zxdg_output_manager_v1, zxdg_output_manager_v1), |
| REGISTRY_CALLBACK(surface_augmenter, surface_augmenter), |
| REGISTRY_CALLBACK(overlay_prioritizer, overlay_prioritizer), |
| REGISTRY_CALLBACK(weston_test, weston_test), |
| REGISTRY_CALLBACK(zwp_idle_inhibit_manager_v1, |
| zwp_idle_inhibit_manager_v1), |
| }; |
| if (interfaces_callbacks.find(interface) != interfaces_callbacks.end()) { |
| interfaces_callbacks[interface](globals, registry, id, version); |
| } else { |
| LOG(ERROR) << "Unbound interface: " << interface; |
| } |
| } |
| |
| void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { |
| LOG(WARNING) << "Got a registry losing event for " << id; |
| } |
| |
| wl_registry_listener g_registry_listener = {RegistryHandler, RegistryRemover}; |
| |
| } // namespace |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // ClientVersionTest, public: |
| |
| void ClientVersionTest::TestProtocol(const std::string& protocol, |
| VersionValidityType validity_type) { |
| auto globals = std::make_unique<Globals>(); |
| globals->protocol_tested = protocol; |
| globals->validity_type = validity_type; |
| std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); |
| CHECK(display) << "wl_display_connect failed"; |
| |
| std::unique_ptr<wl_registry> registry(wl_display_get_registry(display.get())); |
| wl_registry_add_listener(registry.get(), &g_registry_listener, globals.get()); |
| |
| wl_display_roundtrip(display.get()); |
| CHECK(globals->compositor) << "no compositor bound"; |
| |
| std::unique_ptr<wl_surface> surface; |
| surface.reset(static_cast<wl_surface*>( |
| wl_compositor_create_surface(globals->compositor.get()))); |
| wl_surface_attach(surface.get(), nullptr, 0, 0); |
| wl_display_roundtrip(display.get()); |
| |
| int err = wl_display_get_error(display.get()); |
| if (validity_type == VersionValidityType::VALID_SKEWED || |
| validity_type == VersionValidityType::VALID_ADVERTISED) { |
| DCHECK_EQ(err, 0) << "Couldn't bind valid version of " << protocol; |
| } else { |
| DCHECK_EQ(err, EPROTO) << "Invalid version bound for " << protocol; |
| |
| uint32_t errorcode; |
| errorcode = wl_display_get_protocol_error(display.get(), nullptr, nullptr); |
| DCHECK_EQ(errorcode, WL_DISPLAY_ERROR_INVALID_OBJECT) |
| << "Invalid error code for invalid version of " << protocol; |
| } |
| |
| globals.reset(); |
| } |
| |
| const std::vector<std::string> ClientVersionTest::Protocols() { |
| Globals globals; |
| std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); |
| std::unique_ptr<wl_registry> registry(wl_display_get_registry(display.get())); |
| wl_registry_add_listener(registry.get(), &g_registry_listener, &globals); |
| wl_display_roundtrip(display.get()); |
| return std::move(globals.protocols); |
| } |
| } // namespace clients |
| } // namespace wayland |
| } // namespace exo |