diff options
Diffstat (limited to 'chromium/ui/ozone/platform/wayland')
17 files changed, 520 insertions, 348 deletions
diff --git a/chromium/ui/ozone/platform/wayland/fake_server.cc b/chromium/ui/ozone/platform/wayland/fake_server.cc index 7adfe81029e..84c6594cb95 100644 --- a/chromium/ui/ozone/platform/wayland/fake_server.cc +++ b/chromium/ui/ozone/platform/wayland/fake_server.cc @@ -23,6 +23,11 @@ const uint32_t kOutputVersion = 2; const uint32_t kSeatVersion = 4; const uint32_t kXdgShellVersion = 1; +template <class T> +T* GetUserDataAs(wl_resource* resource) { + return static_cast<T*>(wl_resource_get_user_data(resource)); +} + void DestroyResource(wl_client* client, wl_resource* resource) { wl_resource_destroy(resource); } @@ -30,8 +35,7 @@ void DestroyResource(wl_client* client, wl_resource* resource) { // wl_compositor void CreateSurface(wl_client* client, wl_resource* resource, uint32_t id) { - auto* compositor = - static_cast<MockCompositor*>(wl_resource_get_user_data(resource)); + auto* compositor = GetUserDataAs<MockCompositor>(resource); wl_resource* surface_resource = wl_resource_create( client, &wl_surface_interface, wl_resource_get_version(resource), id); if (!surface_resource) { @@ -53,8 +57,7 @@ void Attach(wl_client* client, wl_resource* buffer_resource, int32_t x, int32_t y) { - static_cast<MockSurface*>(wl_resource_get_user_data(resource)) - ->Attach(buffer_resource, x, y); + GetUserDataAs<MockSurface>(resource)->Attach(buffer_resource, x, y); } void Damage(wl_client* client, @@ -63,12 +66,11 @@ void Damage(wl_client* client, int32_t y, int32_t width, int32_t height) { - static_cast<MockSurface*>(wl_resource_get_user_data(resource)) - ->Damage(x, y, width, height); + GetUserDataAs<MockSurface>(resource)->Damage(x, y, width, height); } void Commit(wl_client* client, wl_resource* resource) { - static_cast<MockSurface*>(wl_resource_get_user_data(resource))->Commit(); + GetUserDataAs<MockSurface>(resource)->Commit(); } const struct wl_surface_interface surface_impl = { @@ -89,14 +91,13 @@ const struct wl_surface_interface surface_impl = { void UseUnstableVersion(wl_client* client, wl_resource* resource, int32_t version) { - static_cast<MockXdgShell*>(wl_resource_get_user_data(resource)) - ->UseUnstableVersion(version); + GetUserDataAs<MockXdgShell>(resource)->UseUnstableVersion(version); } // xdg_shell and zxdg_shell_v6 void Pong(wl_client* client, wl_resource* resource, uint32_t serial) { - static_cast<MockXdgShell*>(wl_resource_get_user_data(resource))->Pong(serial); + GetUserDataAs<MockXdgShell>(resource)->Pong(serial); } // xdg_shell @@ -131,36 +132,36 @@ const struct zxdg_shell_v6_interface zxdg_shell_v6_impl = { // wl_seat void GetPointer(wl_client* client, wl_resource* resource, uint32_t id) { - auto* seat = static_cast<MockSeat*>(wl_resource_get_user_data(resource)); wl_resource* pointer_resource = wl_resource_create( client, &wl_pointer_interface, wl_resource_get_version(resource), id); if (!pointer_resource) { wl_client_post_no_memory(client); return; } - seat->pointer.reset(new MockPointer(pointer_resource)); + auto* seat = GetUserDataAs<MockSeat>(resource); + seat->set_pointer(std::make_unique<MockPointer>(pointer_resource)); } void GetKeyboard(wl_client* client, wl_resource* resource, uint32_t id) { - auto* seat = static_cast<MockSeat*>(wl_resource_get_user_data(resource)); wl_resource* keyboard_resource = wl_resource_create( client, &wl_keyboard_interface, wl_resource_get_version(resource), id); if (!keyboard_resource) { wl_client_post_no_memory(client); return; } - seat->keyboard.reset(new MockKeyboard(keyboard_resource)); + auto* seat = GetUserDataAs<MockSeat>(resource); + seat->set_keyboard(std::make_unique<MockKeyboard>(keyboard_resource)); } void GetTouch(wl_client* client, wl_resource* resource, uint32_t id) { - auto* seat = static_cast<MockSeat*>(wl_resource_get_user_data(resource)); wl_resource* touch_resource = wl_resource_create( client, &wl_touch_interface, wl_resource_get_version(resource), id); if (!touch_resource) { wl_client_post_no_memory(client); return; } - seat->touch.reset(new MockTouch(touch_resource)); + auto* seat = GetUserDataAs<MockSeat>(resource); + seat->set_touch(std::make_unique<MockTouch>(touch_resource)); } const struct wl_seat_interface seat_impl = { @@ -192,18 +193,15 @@ const struct wl_touch_interface touch_impl = { // xdg_surface, zxdg_surface_v6 and zxdg_toplevel shared methods. void SetTitle(wl_client* client, wl_resource* resource, const char* title) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->SetTitle(title); + GetUserDataAs<MockXdgSurface>(resource)->SetTitle(title); } void SetAppId(wl_client* client, wl_resource* resource, const char* app_id) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->SetAppId(app_id); + GetUserDataAs<MockXdgSurface>(resource)->SetAppId(app_id); } void AckConfigure(wl_client* client, wl_resource* resource, uint32_t serial) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->AckConfigure(serial); + GetUserDataAs<MockXdgSurface>(resource)->AckConfigure(serial); } void SetWindowGeometry(wl_client* client, @@ -212,35 +210,30 @@ void SetWindowGeometry(wl_client* client, int32_t y, int32_t width, int32_t height) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->SetWindowGeometry(x, y, width, height); + GetUserDataAs<MockXdgSurface>(resource)->SetWindowGeometry(x, y, width, + height); } void SetMaximized(wl_client* client, wl_resource* resource) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->SetMaximized(); + GetUserDataAs<MockXdgSurface>(resource)->SetMaximized(); } void UnsetMaximized(wl_client* client, wl_resource* resource) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->UnsetMaximized(); + GetUserDataAs<MockXdgSurface>(resource)->UnsetMaximized(); } void SetFullscreen(wl_client* client, wl_resource* resource, wl_resource* output) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->SetFullscreen(); + GetUserDataAs<MockXdgSurface>(resource)->SetFullscreen(); } void UnsetFullscreen(wl_client* client, wl_resource* resource) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->UnsetFullscreen(); + GetUserDataAs<MockXdgSurface>(resource)->UnsetFullscreen(); } void SetMinimized(wl_client* client, wl_resource* resource) { - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)) - ->SetMinimized(); + GetUserDataAs<MockXdgSurface>(resource)->SetMinimized(); } const struct xdg_surface_interface xdg_surface_impl = { @@ -263,9 +256,8 @@ const struct xdg_surface_interface xdg_surface_impl = { // zxdg_surface specific interface void GetTopLevel(wl_client* client, wl_resource* resource, uint32_t id) { - auto* surface = - static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource)); - if (surface->xdg_toplevel) { + auto* surface = GetUserDataAs<MockXdgSurface>(resource); + if (surface->xdg_toplevel()) { wl_resource_post_error(resource, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED, "surface has already been constructed"); return; @@ -276,7 +268,8 @@ void GetTopLevel(wl_client* client, wl_resource* resource, uint32_t id) { wl_client_post_no_memory(client); return; } - surface->xdg_toplevel.reset(new MockXdgTopLevel(xdg_toplevel_resource)); + surface->set_xdg_toplevel( + std::make_unique<MockXdgTopLevel>(xdg_toplevel_resource)); } const struct zxdg_surface_v6_interface zxdg_surface_v6_impl = { @@ -310,9 +303,8 @@ void GetXdgSurfaceImpl(wl_client* client, wl_resource* surface_resource, const struct wl_interface* interface, const void* implementation) { - auto* surface = - static_cast<MockSurface*>(wl_resource_get_user_data(surface_resource)); - if (surface->xdg_surface) { + auto* surface = GetUserDataAs<MockSurface>(surface_resource); + if (surface->xdg_surface()) { uint32_t xdg_error = implementation == &xdg_surface_impl ? XDG_SHELL_ERROR_ROLE : ZXDG_SHELL_V6_ERROR_ROLE; @@ -326,8 +318,8 @@ void GetXdgSurfaceImpl(wl_client* client, wl_client_post_no_memory(client); return; } - surface->xdg_surface.reset( - new MockXdgSurface(xdg_surface_resource, implementation)); + surface->set_xdg_surface( + std::make_unique<MockXdgSurface>(xdg_surface_resource, implementation)); } // xdg_shell @@ -361,60 +353,62 @@ ServerObject::~ServerObject() { // static void ServerObject::OnResourceDestroyed(wl_resource* resource) { - auto* obj = static_cast<ServerObject*>(wl_resource_get_user_data(resource)); + auto* obj = GetUserDataAs<ServerObject>(resource); obj->resource_ = nullptr; } +template <class T> +void SetImplementation(wl_resource* resource, + const void* implementation, + T* user_data) { + wl_resource_set_implementation(resource, implementation, user_data, + &ServerObject::OnResourceDestroyed); +} + MockXdgSurface::MockXdgSurface(wl_resource* resource, const void* implementation) : ServerObject(resource) { - wl_resource_set_implementation(resource, implementation, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, implementation, this); } MockXdgSurface::~MockXdgSurface() {} MockXdgTopLevel::MockXdgTopLevel(wl_resource* resource) : MockXdgSurface(resource, &zxdg_surface_v6_impl) { - wl_resource_set_implementation(resource, &zxdg_toplevel_v6_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &zxdg_toplevel_v6_impl, this); } MockXdgTopLevel::~MockXdgTopLevel() {} MockSurface::MockSurface(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &surface_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &surface_impl, this); } MockSurface::~MockSurface() { - if (xdg_surface && xdg_surface->resource()) - wl_resource_destroy(xdg_surface->resource()); + if (xdg_surface_ && xdg_surface_->resource()) + wl_resource_destroy(xdg_surface_->resource()); } MockSurface* MockSurface::FromResource(wl_resource* resource) { if (!wl_resource_instance_of(resource, &wl_surface_interface, &surface_impl)) return nullptr; - return static_cast<MockSurface*>(wl_resource_get_user_data(resource)); + return GetUserDataAs<MockSurface>(resource); } MockPointer::MockPointer(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &pointer_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &pointer_impl, this); } MockPointer::~MockPointer() {} MockKeyboard::MockKeyboard(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &keyboard_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &keyboard_impl, this); } MockKeyboard::~MockKeyboard() {} MockTouch::MockTouch(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &touch_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &touch_impl, this); } MockTouch::~MockTouch() {} @@ -451,14 +445,13 @@ void Global::Bind(wl_client* client, } if (!global->resource_) global->resource_ = resource; - wl_resource_set_implementation(resource, global->implementation_, global, - &Global::OnResourceDestroyed); + SetImplementation(resource, global->implementation_, global); global->OnBind(); } // static void Global::OnResourceDestroyed(wl_resource* resource) { - auto* global = static_cast<Global*>(wl_resource_get_user_data(resource)); + auto* global = GetUserDataAs<Global>(resource); if (global->resource_ == resource) global->resource_ = nullptr; } @@ -552,8 +545,8 @@ bool FakeServer::Start(uint32_t shell_version) { (void)server_fd.release(); base::Thread::Options options; - options.message_pump_factory = - base::Bind(&FakeServer::CreateMessagePump, base::Unretained(this)); + options.message_pump_factory = base::BindRepeating( + &FakeServer::CreateMessagePump, base::Unretained(this)); if (!base::Thread::StartWithOptions(options)) return false; @@ -564,7 +557,7 @@ bool FakeServer::Start(uint32_t shell_version) { void FakeServer::Pause() { task_runner()->PostTask( - FROM_HERE, base::Bind(&FakeServer::DoPause, base::Unretained(this))); + FROM_HERE, base::BindOnce(&FakeServer::DoPause, base::Unretained(this))); pause_event_.Wait(); } diff --git a/chromium/ui/ozone/platform/wayland/fake_server.h b/chromium/ui/ozone/platform/wayland/fake_server.h index 816f5815e6f..24e3863053d 100644 --- a/chromium/ui/ozone/platform/wayland/fake_server.h +++ b/chromium/ui/ozone/platform/wayland/fake_server.h @@ -25,7 +25,7 @@ namespace wl { // Base class for managing the life cycle of server objects. class ServerObject { public: - ServerObject(wl_resource* resource); + explicit ServerObject(wl_resource* resource); virtual ~ServerObject(); wl_resource* resource() { return resource_; } @@ -54,24 +54,29 @@ class MockXdgSurface : public ServerObject { MOCK_METHOD1(SetAppId, void(const char* app_id)); MOCK_METHOD1(AckConfigure, void(uint32_t serial)); MOCK_METHOD4(SetWindowGeometry, - void(int32_t x, int32_t y, int32_t widht, int32_t height)); + void(int32_t x, int32_t y, int32_t width, int32_t height)); MOCK_METHOD0(SetMaximized, void()); MOCK_METHOD0(UnsetMaximized, void()); MOCK_METHOD0(SetFullscreen, void()); MOCK_METHOD0(UnsetFullscreen, void()); MOCK_METHOD0(SetMinimized, void()); - // Used when xdg v6 is used. - std::unique_ptr<MockXdgTopLevel> xdg_toplevel; + void set_xdg_toplevel(std::unique_ptr<MockXdgTopLevel> xdg_toplevel) { + xdg_toplevel_ = std::move(xdg_toplevel); + } + MockXdgTopLevel* xdg_toplevel() { return xdg_toplevel_.get(); } private: + // Used when xdg v6 is used. + std::unique_ptr<MockXdgTopLevel> xdg_toplevel_; + DISALLOW_COPY_AND_ASSIGN(MockXdgSurface); }; // Manage zxdg_toplevel for providing desktop UI. class MockXdgTopLevel : public MockXdgSurface { public: - MockXdgTopLevel(wl_resource* resource); + explicit MockXdgTopLevel(wl_resource* resource); ~MockXdgTopLevel() override; // TODO(msisov): mock other zxdg_toplevel specific methods once implementation @@ -85,7 +90,7 @@ class MockXdgTopLevel : public MockXdgSurface { // Manage client surface class MockSurface : public ServerObject { public: - MockSurface(wl_resource* resource); + explicit MockSurface(wl_resource* resource); ~MockSurface() override; static MockSurface* FromResource(wl_resource* resource); @@ -95,15 +100,20 @@ class MockSurface : public ServerObject { void(int32_t x, int32_t y, int32_t width, int32_t height)); MOCK_METHOD0(Commit, void()); - std::unique_ptr<MockXdgSurface> xdg_surface; + void set_xdg_surface(std::unique_ptr<MockXdgSurface> xdg_surface) { + xdg_surface_ = std::move(xdg_surface); + } + MockXdgSurface* xdg_surface() { return xdg_surface_.get(); } private: + std::unique_ptr<MockXdgSurface> xdg_surface_; + DISALLOW_COPY_AND_ASSIGN(MockSurface); }; class MockPointer : public ServerObject { public: - MockPointer(wl_resource* resource); + explicit MockPointer(wl_resource* resource); ~MockPointer() override; private: @@ -112,7 +122,7 @@ class MockPointer : public ServerObject { class MockKeyboard : public ServerObject { public: - MockKeyboard(wl_resource* resource); + explicit MockKeyboard(wl_resource* resource); ~MockKeyboard() override; private: @@ -207,11 +217,26 @@ class MockSeat : public Global { MockSeat(); ~MockSeat() override; - std::unique_ptr<MockPointer> pointer; - std::unique_ptr<MockKeyboard> keyboard; - std::unique_ptr<MockTouch> touch; + void set_pointer(std::unique_ptr<MockPointer> pointer) { + pointer_ = std::move(pointer); + } + MockPointer* pointer() { return pointer_.get(); } + + void set_keyboard(std::unique_ptr<MockKeyboard> keyboard) { + keyboard_ = std::move(keyboard); + } + MockKeyboard* keyboard() { return keyboard_.get(); } + + void set_touch(std::unique_ptr<MockTouch> touch) { + touch_ = std::move(touch); + } + MockTouch* touch() { return touch_.get(); } private: + std::unique_ptr<MockPointer> pointer_; + std::unique_ptr<MockKeyboard> keyboard_; + std::unique_ptr<MockTouch> touch_; + DISALLOW_COPY_AND_ASSIGN(MockSeat); }; @@ -244,7 +269,7 @@ struct DisplayDeleter { void operator()(wl_display* display); }; -class FakeServer : public base::Thread, base::MessagePumpLibevent::Watcher { +class FakeServer : public base::Thread, base::MessagePumpLibevent::FdWatcher { public: FakeServer(); ~FakeServer() override; @@ -278,7 +303,7 @@ class FakeServer : public base::Thread, base::MessagePumpLibevent::Watcher { std::unique_ptr<base::MessagePump> CreateMessagePump(); - // base::MessagePumpLibevent::Watcher + // base::MessagePumpLibevent::FdWatcher void OnFileCanReadWithoutBlocking(int fd) override; void OnFileCanWriteWithoutBlocking(int fd) override; @@ -296,7 +321,7 @@ class FakeServer : public base::Thread, base::MessagePumpLibevent::Watcher { MockXdgShell xdg_shell_; MockXdgShellV6 zxdg_shell_v6_; - base::MessagePumpLibevent::FileDescriptorWatcher controller_; + base::MessagePumpLibevent::FdWatchController controller_; DISALLOW_COPY_AND_ASSIGN(FakeServer); }; diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc index 843d7c99fdf..f0774bf1211 100644 --- a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc +++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc @@ -4,7 +4,6 @@ #include "ui/ozone/platform/wayland/ozone_platform_wayland.h" -#include "base/memory/ptr_util.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/base/ui_features.h" #include "ui/display/manager/fake_display_delegate.h" diff --git a/chromium/ui/ozone/platform/wayland/wayland_connection.cc b/chromium/ui/ozone/platform/wayland/wayland_connection.cc index 89cf855b386..a90445be880 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_connection.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_connection.cc @@ -92,7 +92,8 @@ void WaylandConnection::ScheduleFlush() { return; DCHECK(base::MessageLoopForUI::IsCurrent()); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&WaylandConnection::Flush, base::Unretained(this))); + FROM_HERE, + base::BindOnce(&WaylandConnection::Flush, base::Unretained(this))); scheduled_flush_ = true; } @@ -253,8 +254,8 @@ void WaylandConnection::Capabilities(void* data, return; } connection->pointer_ = std::make_unique<WaylandPointer>( - pointer, base::Bind(&WaylandConnection::DispatchUiEvent, - base::Unretained(connection))); + pointer, base::BindRepeating(&WaylandConnection::DispatchUiEvent, + base::Unretained(connection))); connection->pointer_->set_connection(connection); } } else if (connection->pointer_) { @@ -268,8 +269,8 @@ void WaylandConnection::Capabilities(void* data, return; } connection->keyboard_ = std::make_unique<WaylandKeyboard>( - keyboard, base::Bind(&WaylandConnection::DispatchUiEvent, - base::Unretained(connection))); + keyboard, base::BindRepeating(&WaylandConnection::DispatchUiEvent, + base::Unretained(connection))); connection->keyboard_->set_connection(connection); } } else if (connection->keyboard_) { @@ -283,8 +284,8 @@ void WaylandConnection::Capabilities(void* data, return; } connection->touch_ = std::make_unique<WaylandTouch>( - touch, base::Bind(&WaylandConnection::DispatchUiEvent, - base::Unretained(connection))); + touch, base::BindRepeating(&WaylandConnection::DispatchUiEvent, + base::Unretained(connection))); connection->touch_->set_connection(connection); } } else if (connection->touch_) { diff --git a/chromium/ui/ozone/platform/wayland/wayland_connection.h b/chromium/ui/ozone/platform/wayland/wayland_connection.h index e745efd5b6b..747a11a465a 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_connection.h +++ b/chromium/ui/ozone/platform/wayland/wayland_connection.h @@ -21,7 +21,7 @@ namespace ui { class WaylandWindow; class WaylandConnection : public PlatformEventSource, - public base::MessagePumpLibevent::Watcher { + public base::MessagePumpLibevent::FdWatcher { public: WaylandConnection(); ~WaylandConnection() override; @@ -53,6 +53,9 @@ class WaylandConnection : public PlatformEventSource, int GetKeyboardModifiers(); + // Returns the current pointer, which may be null. + WaylandPointer* pointer() { return pointer_.get(); } + private: void Flush(); void DispatchUiEvent(Event* event); @@ -60,7 +63,7 @@ class WaylandConnection : public PlatformEventSource, // PlatformEventSource void OnDispatcherListChanged() override; - // base::MessagePumpLibevent::Watcher + // base::MessagePumpLibevent::FdWatcher void OnFileCanReadWithoutBlocking(int fd) override; void OnFileCanWriteWithoutBlocking(int fd) override; @@ -98,7 +101,7 @@ class WaylandConnection : public PlatformEventSource, bool scheduled_flush_ = false; bool watching_ = false; - base::MessagePumpLibevent::FileDescriptorWatcher controller_; + base::MessagePumpLibevent::FdWatchController controller_; uint32_t serial_ = 0; diff --git a/chromium/ui/ozone/platform/wayland/wayland_keyboard_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_keyboard_unittest.cc index 7ce077a7e97..492152b68b2 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_keyboard_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_keyboard_unittest.cc @@ -31,13 +31,13 @@ class WaylandKeyboardTest : public WaylandTest { void SetUp() override { WaylandTest::SetUp(); - wl_seat_send_capabilities(server.seat()->resource(), + wl_seat_send_capabilities(server_.seat()->resource(), WL_SEAT_CAPABILITY_KEYBOARD); Sync(); - keyboard = server.seat()->keyboard.get(); - ASSERT_TRUE(keyboard); + keyboard_ = server_.seat()->keyboard(); + ASSERT_TRUE(keyboard_); #if BUILDFLAG(USE_XKBCOMMON) // Set up XKB bits and set the keymap to the client. @@ -54,14 +54,14 @@ class WaylandKeyboardTest : public WaylandTest { bool rv = shared_keymap.CreateAndMapAnonymous(keymap_size); DCHECK(rv); memcpy(shared_keymap.memory(), keymap_string.get(), keymap_size); - wl_keyboard_send_keymap(keyboard->resource(), + wl_keyboard_send_keymap(keyboard_->resource(), WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, shared_keymap.handle().GetHandle(), keymap_size); #endif } protected: - wl::MockKeyboard* keyboard; + wl::MockKeyboard* keyboard_; private: #if BUILDFLAG(USE_XKBCOMMON) @@ -81,14 +81,15 @@ ACTION_P(CloneEvent, ptr) { TEST_P(WaylandKeyboardTest, Keypress) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); - wl_keyboard_send_key(keyboard->resource(), 2, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); ASSERT_TRUE(event); @@ -98,27 +99,28 @@ TEST_P(WaylandKeyboardTest, Keypress) { EXPECT_EQ(ui::VKEY_A, key_event->key_code()); EXPECT_EQ(ET_KEY_PRESSED, key_event->type()); - wl_keyboard_send_leave(keyboard->resource(), 3, surface->resource()); + wl_keyboard_send_leave(keyboard_->resource(), 3, surface_->resource()); Sync(); - wl_keyboard_send_key(keyboard->resource(), 3, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 3, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(0); + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(0); } TEST_P(WaylandKeyboardTest, AltModifierKeypress) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Alt - wl_keyboard_send_key(keyboard->resource(), 2, 0, 56 /* left Alt */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 56 /* left Alt */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); ASSERT_TRUE(event); @@ -134,15 +136,16 @@ TEST_P(WaylandKeyboardTest, AltModifierKeypress) { TEST_P(WaylandKeyboardTest, ControlModifierKeypress) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Control - wl_keyboard_send_key(keyboard->resource(), 2, 0, 29 /* left Control */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 29 /* left Control */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); ASSERT_TRUE(event); @@ -158,15 +161,16 @@ TEST_P(WaylandKeyboardTest, ControlModifierKeypress) { TEST_P(WaylandKeyboardTest, ShiftModifierKeypress) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Shift - wl_keyboard_send_key(keyboard->resource(), 2, 0, 42 /* left Shift */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 42 /* left Shift */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); ASSERT_TRUE(event); @@ -183,41 +187,42 @@ TEST_P(WaylandKeyboardTest, ControlShiftModifiers) { struct wl_array empty; wl_array_init(&empty); wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Pressing control. - wl_keyboard_send_key(keyboard->resource(), 2, 0, 29 /* Control */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 29 /* Control */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); - wl_keyboard_send_modifiers(keyboard->resource(), 3, 4 /* mods_depressed*/, + wl_keyboard_send_modifiers(keyboard_->resource(), 3, 4 /* mods_depressed*/, 0 /* mods_latched */, 0 /* mods_locked */, 0 /* group */); Sync(); // Pressing shift (with control key still held down). - wl_keyboard_send_key(keyboard->resource(), 4, 0, 42 /* Shift */, + wl_keyboard_send_key(keyboard_->resource(), 4, 0, 42 /* Shift */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event2; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); Sync(); - wl_keyboard_send_modifiers(keyboard->resource(), 5, 5 /* mods_depressed*/, + wl_keyboard_send_modifiers(keyboard_->resource(), 5, 5 /* mods_depressed*/, 0 /* mods_latched */, 0 /* mods_locked */, 0 /* group */); Sync(); // Sending a reguard keypress, eg 'a'. - wl_keyboard_send_key(keyboard->resource(), 6, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 6, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event3; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event3)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event3)); Sync(); ASSERT_TRUE(event3); @@ -234,15 +239,16 @@ TEST_P(WaylandKeyboardTest, CapsLockKeypress) { struct wl_array empty; wl_array_init(&empty); wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Capslock - wl_keyboard_send_key(keyboard->resource(), 2, 0, 58 /* Capslock */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 58 /* Capslock */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); ASSERT_TRUE(event); @@ -256,11 +262,11 @@ TEST_P(WaylandKeyboardTest, CapsLockKeypress) { Sync(); - wl_keyboard_send_key(keyboard->resource(), 2, 0, 58 /* Capslock */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 58 /* Capslock */, WL_KEYBOARD_KEY_STATE_RELEASED); std::unique_ptr<Event> event2; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); Sync(); ASSERT_TRUE(event2); @@ -278,41 +284,42 @@ TEST_P(WaylandKeyboardTest, CapsLockModifier) { struct wl_array empty; wl_array_init(&empty); wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Pressing capslock (led ON). - wl_keyboard_send_key(keyboard->resource(), 2, 0, 58 /* Capslock */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 58 /* Capslock */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); - wl_keyboard_send_modifiers(keyboard->resource(), 3, 2 /* mods_depressed*/, + wl_keyboard_send_modifiers(keyboard_->resource(), 3, 2 /* mods_depressed*/, 0 /* mods_latched */, 2 /* mods_locked */, 0 /* group */); Sync(); // Releasing capslock (led ON). - wl_keyboard_send_key(keyboard->resource(), 4, 0, 58 /* Capslock */, + wl_keyboard_send_key(keyboard_->resource(), 4, 0, 58 /* Capslock */, WL_KEYBOARD_KEY_STATE_RELEASED); std::unique_ptr<Event> event2; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); Sync(); - wl_keyboard_send_modifiers(keyboard->resource(), 5, 0 /* mods_depressed*/, + wl_keyboard_send_modifiers(keyboard_->resource(), 5, 0 /* mods_depressed*/, 0 /* mods_latched */, 2 /* mods_locked */, 0 /* group */); Sync(); // Sending a reguard keypress, eg 'a'. - wl_keyboard_send_key(keyboard->resource(), 6, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 6, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event3; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event3)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event3)); Sync(); ASSERT_TRUE(event3); @@ -330,20 +337,21 @@ TEST_P(WaylandKeyboardTest, EventAutoRepeat) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Auto repeat info in ms. uint32_t rate = 75; uint32_t delay = 25; - wl_keyboard_send_repeat_info(keyboard->resource(), rate, delay); + wl_keyboard_send_repeat_info(keyboard_->resource(), rate, delay); - wl_keyboard_send_key(keyboard->resource(), 2, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); @@ -361,9 +369,9 @@ TEST_P(WaylandKeyboardTest, EventAutoRepeat) { Sync(); std::unique_ptr<Event> event2; - EXPECT_CALL(delegate, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event2)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event2)); - wl_keyboard_send_key(keyboard->resource(), 3, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 3, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_RELEASED); Sync(); } @@ -372,20 +380,21 @@ TEST_P(WaylandKeyboardTest, NoEventAutoRepeatOnLeave) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Auto repeat info in ms. uint32_t rate = 75; uint32_t delay = 25; - wl_keyboard_send_repeat_info(keyboard->resource(), rate, delay); + wl_keyboard_send_repeat_info(keyboard_->resource(), rate, delay); - wl_keyboard_send_key(keyboard->resource(), 2, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); @@ -400,13 +409,13 @@ TEST_P(WaylandKeyboardTest, NoEventAutoRepeatOnLeave) { base::TimeDelta::FromMilliseconds(rate * 2)); } - wl_keyboard_send_leave(keyboard->resource(), 3, surface->resource()); + wl_keyboard_send_leave(keyboard_->resource(), 3, surface_->resource()); Sync(); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(0); + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(0); - wl_keyboard_send_key(keyboard->resource(), 4, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 4, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_RELEASED); Sync(); } @@ -415,20 +424,21 @@ TEST_P(WaylandKeyboardTest, NoEventAutoRepeatBeforeTimeout) { struct wl_array empty; wl_array_init(&empty); - wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); + wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(), + &empty); wl_array_release(&empty); // Auto repeat info in ms. uint32_t rate = 500; uint32_t delay = 50; - wl_keyboard_send_repeat_info(keyboard->resource(), rate, delay); + wl_keyboard_send_repeat_info(keyboard_->resource(), rate, delay); - wl_keyboard_send_key(keyboard->resource(), 2, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 2, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_PRESSED); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); @@ -444,11 +454,11 @@ TEST_P(WaylandKeyboardTest, NoEventAutoRepeatBeforeTimeout) { base::TimeDelta::FromMilliseconds(rate / 5)); } - wl_keyboard_send_key(keyboard->resource(), 4, 0, 30 /* a */, + wl_keyboard_send_key(keyboard_->resource(), 4, 0, 30 /* a */, WL_KEYBOARD_KEY_STATE_RELEASED); std::unique_ptr<Event> event2; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event2)); Sync(); ASSERT_TRUE(event2); diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer.cc b/chromium/ui/ozone/platform/wayland/wayland_pointer.cc index 9d6f4ae78e3..8d74daf9b73 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_pointer.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_pointer.cc @@ -23,6 +23,12 @@ bool VerifyFlagsAfterMasking(int flags, int original_flags, int modifiers) { return flags == original_flags; } +bool HasAnyButtonFlag(int flags) { + return (flags & (EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON | + EF_RIGHT_MOUSE_BUTTON | EF_BACK_MOUSE_BUTTON | + EF_FORWARD_MOUSE_BUTTON)) != 0; +} + } // namespace WaylandPointer::WaylandPointer(wl_pointer* pointer, @@ -38,7 +44,12 @@ WaylandPointer::WaylandPointer(wl_pointer* pointer, cursor_.reset(new WaylandCursor); } -WaylandPointer::~WaylandPointer() {} +WaylandPointer::~WaylandPointer() { + if (window_with_pointer_focus_) { + window_with_pointer_focus_->set_pointer_focus(false); + window_with_pointer_focus_->set_has_implicit_grab(false); + } +} // static void WaylandPointer::Enter(void* data, @@ -50,8 +61,11 @@ void WaylandPointer::Enter(void* data, WaylandPointer* pointer = static_cast<WaylandPointer*>(data); pointer->location_.SetPoint(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)); - if (surface) - WaylandWindow::FromSurface(surface)->set_pointer_focus(true); + if (surface) { + WaylandWindow* window = WaylandWindow::FromSurface(surface); + window->set_pointer_focus(true); + pointer->window_with_pointer_focus_ = window; + } } // static @@ -63,8 +77,11 @@ void WaylandPointer::Leave(void* data, MouseEvent event(ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), EventTimeForNow(), pointer->flags_, 0); pointer->callback_.Run(&event); - if (surface) - WaylandWindow::FromSurface(surface)->set_pointer_focus(false); + if (surface) { + WaylandWindow* window = WaylandWindow::FromSurface(surface); + window->set_pointer_focus(false); + pointer->window_with_pointer_focus_ = nullptr; + } } // static @@ -92,22 +109,22 @@ void WaylandPointer::Button(void* data, uint32_t button, uint32_t state) { WaylandPointer* pointer = static_cast<WaylandPointer*>(data); - int flag; + int changed_button; switch (button) { case BTN_LEFT: - flag = EF_LEFT_MOUSE_BUTTON; + changed_button = EF_LEFT_MOUSE_BUTTON; break; case BTN_MIDDLE: - flag = EF_MIDDLE_MOUSE_BUTTON; + changed_button = EF_MIDDLE_MOUSE_BUTTON; break; case BTN_RIGHT: - flag = EF_RIGHT_MOUSE_BUTTON; + changed_button = EF_RIGHT_MOUSE_BUTTON; break; case BTN_BACK: - flag = EF_BACK_MOUSE_BUTTON; + changed_button = EF_BACK_MOUSE_BUTTON; break; case BTN_FORWARD: - flag = EF_FORWARD_MOUSE_BUTTON; + changed_button = EF_FORWARD_MOUSE_BUTTON; break; default: return; @@ -116,17 +133,24 @@ void WaylandPointer::Button(void* data, EventType type; if (state == WL_POINTER_BUTTON_STATE_PRESSED) { type = ET_MOUSE_PRESSED; - pointer->flags_ |= flag; + pointer->flags_ |= changed_button; pointer->connection_->set_serial(serial); } else { type = ET_MOUSE_RELEASED; - pointer->flags_ &= ~flag; + pointer->flags_ &= ~changed_button; + } + + if (pointer->window_with_pointer_focus_) { + pointer->window_with_pointer_focus_->set_has_implicit_grab( + HasAnyButtonFlag(pointer->flags_)); } - int flags = pointer->GetFlagsWithKeyboardModifiers() | flag; + // MouseEvent's flags should contain the button that was released too. + const int flags = pointer->GetFlagsWithKeyboardModifiers() | changed_button; MouseEvent event(type, gfx::Point(), gfx::Point(), base::TimeTicks() + base::TimeDelta::FromMilliseconds(time), - flags, flag); + flags, changed_button); + event.set_location_f(pointer->location_); event.set_root_location_f(pointer->location_); pointer->callback_.Run(&event); diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer.h b/chromium/ui/ozone/platform/wayland/wayland_pointer.h index 9550da69334..9515dfccdac 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_pointer.h +++ b/chromium/ui/ozone/platform/wayland/wayland_pointer.h @@ -5,6 +5,7 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_POINTER_H_ #define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_POINTER_H_ +#include "base/macros.h" #include "ui/events/ozone/evdev/event_dispatch_callback.h" #include "ui/gfx/geometry/point_f.h" #include "ui/ozone/platform/wayland/wayland_cursor.h" @@ -12,6 +13,8 @@ namespace ui { +class WaylandWindow; + class WaylandPointer { public: WaylandPointer(wl_pointer* pointer, const EventDispatchCallback& callback); @@ -26,6 +29,10 @@ class WaylandPointer { WaylandCursor* cursor() { return cursor_.get(); } + void reset_window_with_pointer_focus() { + window_with_pointer_focus_ = nullptr; + } + private: // wl_pointer_listener static void Enter(void* data, @@ -60,11 +67,18 @@ class WaylandPointer { wl::Object<wl_pointer> obj_; EventDispatchCallback callback_; gfx::PointF location_; + // Flags is a bitmask of EventFlags corresponding to the pointer/keyboard + // state. int flags_ = 0; // Keeps track of current modifiers. These are needed in order to properly // update |flags_| with newest modifiers. int keyboard_modifiers_ = 0; + + // The window the mouse is over. + WaylandWindow* window_with_pointer_focus_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(WaylandPointer); }; } // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc index ab2a8085d69..5c0e98a78d7 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc @@ -25,17 +25,17 @@ class WaylandPointerTest : public WaylandTest { void SetUp() override { WaylandTest::SetUp(); - wl_seat_send_capabilities(server.seat()->resource(), + wl_seat_send_capabilities(server_.seat()->resource(), WL_SEAT_CAPABILITY_POINTER); Sync(); - pointer = server.seat()->pointer.get(); - ASSERT_TRUE(pointer); + pointer_ = server_.seat()->pointer(); + ASSERT_TRUE(pointer_); } protected: - wl::MockPointer* pointer; + wl::MockPointer* pointer_; private: DISALLOW_COPY_AND_ASSIGN(WaylandPointerTest); @@ -43,7 +43,7 @@ class WaylandPointerTest : public WaylandTest { TEST_P(WaylandPointerTest, Leave) { MockPlatformWindowDelegate other_delegate; - WaylandWindow other_window(&other_delegate, connection.get(), + WaylandWindow other_window(&other_delegate, connection_.get(), gfx::Rect(0, 0, 10, 10)); gfx::AcceleratedWidget other_widget = gfx::kNullAcceleratedWidget; EXPECT_CALL(other_delegate, OnAcceleratedWidgetAvailable(_, _)) @@ -54,16 +54,16 @@ TEST_P(WaylandPointerTest, Leave) { Sync(); wl::MockSurface* other_surface = - server.GetObject<wl::MockSurface>(other_widget); + server_.GetObject<wl::MockSurface>(other_widget); ASSERT_TRUE(other_surface); - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0); - wl_pointer_send_leave(pointer->resource(), 2, surface->resource()); - wl_pointer_send_enter(pointer->resource(), 3, other_surface->resource(), 0, + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), 0, 0); + wl_pointer_send_leave(pointer_->resource(), 2, surface_->resource()); + wl_pointer_send_enter(pointer_->resource(), 3, other_surface->resource(), 0, 0); - wl_pointer_send_button(pointer->resource(), 4, 1004, BTN_LEFT, + wl_pointer_send_button(pointer_->resource(), 4, 1004, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(1); + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(1); // Do an extra Sync() here so that we process the second enter event before we // destroy |other_window|. @@ -75,12 +75,13 @@ ACTION_P(CloneEvent, ptr) { } TEST_P(WaylandPointerTest, Motion) { - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0); - wl_pointer_send_motion(pointer->resource(), 1002, wl_fixed_from_double(10.75), + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), 0, 0); + wl_pointer_send_motion(pointer_->resource(), 1002, + wl_fixed_from_double(10.75), wl_fixed_from_double(20.375)); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); Sync(); @@ -95,15 +96,15 @@ TEST_P(WaylandPointerTest, Motion) { } TEST_P(WaylandPointerTest, MotionDragged) { - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0); - wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_MIDDLE, + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), 0, 0); + wl_pointer_send_button(pointer_->resource(), 2, 1002, BTN_MIDDLE, WL_POINTER_BUTTON_STATE_PRESSED); Sync(); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); - wl_pointer_send_motion(pointer->resource(), 1003, wl_fixed_from_int(400), + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + wl_pointer_send_motion(pointer_->resource(), 1003, wl_fixed_from_int(400), wl_fixed_from_int(500)); Sync(); @@ -119,44 +120,59 @@ TEST_P(WaylandPointerTest, MotionDragged) { } TEST_P(WaylandPointerTest, ButtonPress) { - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), wl_fixed_from_int(200), wl_fixed_from_int(150)); - wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_RIGHT, - WL_POINTER_BUTTON_STATE_PRESSED); - Sync(); - std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); - wl_pointer_send_button(pointer->resource(), 3, 1003, BTN_LEFT, + wl_pointer_send_button(pointer_->resource(), 2, 1002, BTN_RIGHT, + WL_POINTER_BUTTON_STATE_PRESSED); + std::unique_ptr<Event> right_press_event; + EXPECT_CALL(delegate_, DispatchEvent(_)) + .WillOnce(CloneEvent(&right_press_event)); + Sync(); + ASSERT_TRUE(right_press_event); + ASSERT_TRUE(right_press_event->IsMouseEvent()); + auto* right_press_mouse_event = right_press_event->AsMouseEvent(); + EXPECT_EQ(ET_MOUSE_PRESSED, right_press_mouse_event->type()); + EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, right_press_mouse_event->button_flags()); + EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, + right_press_mouse_event->changed_button_flags()); + + std::unique_ptr<Event> left_press_event; + EXPECT_CALL(delegate_, DispatchEvent(_)) + .WillOnce(CloneEvent(&left_press_event)); + wl_pointer_send_button(pointer_->resource(), 3, 1003, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); Sync(); - ASSERT_TRUE(event); - ASSERT_TRUE(event->IsMouseEvent()); - auto* mouse_event = event->AsMouseEvent(); - EXPECT_EQ(ET_MOUSE_PRESSED, mouse_event->type()); + ASSERT_TRUE(left_press_event); + ASSERT_TRUE(left_press_event->IsMouseEvent()); + auto* left_press_mouse_event = left_press_event->AsMouseEvent(); + EXPECT_EQ(ET_MOUSE_PRESSED, left_press_mouse_event->type()); EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON, - mouse_event->button_flags()); - EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, mouse_event->changed_button_flags()); - EXPECT_EQ(gfx::PointF(200, 150), mouse_event->location_f()); - EXPECT_EQ(gfx::PointF(200, 150), mouse_event->root_location_f()); + left_press_mouse_event->button_flags()); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, + left_press_mouse_event->changed_button_flags()); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, + left_press_mouse_event->changed_button_flags()); + EXPECT_EQ(gfx::PointF(200, 150), left_press_mouse_event->location_f()); + EXPECT_EQ(gfx::PointF(200, 150), left_press_mouse_event->root_location_f()); } TEST_P(WaylandPointerTest, ButtonRelease) { - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), wl_fixed_from_int(50), wl_fixed_from_int(50)); - wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_BACK, + wl_pointer_send_button(pointer_->resource(), 2, 1002, BTN_BACK, WL_POINTER_BUTTON_STATE_PRESSED); - wl_pointer_send_button(pointer->resource(), 3, 1003, BTN_LEFT, + wl_pointer_send_button(pointer_->resource(), 3, 1003, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); Sync(); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); - wl_pointer_send_button(pointer->resource(), 4, 1004, BTN_LEFT, + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + wl_pointer_send_button(pointer_->resource(), 4, 1004, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); Sync(); @@ -173,17 +189,17 @@ TEST_P(WaylandPointerTest, ButtonRelease) { } TEST_P(WaylandPointerTest, AxisVertical) { - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), wl_fixed_from_int(0), wl_fixed_from_int(0)); - wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_RIGHT, + wl_pointer_send_button(pointer_->resource(), 2, 1002, BTN_RIGHT, WL_POINTER_BUTTON_STATE_PRESSED); Sync(); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); // Wayland servers typically send a value of 10 per mouse wheel click. - wl_pointer_send_axis(pointer->resource(), 1003, + wl_pointer_send_axis(pointer_->resource(), 1003, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(20)); Sync(); @@ -200,17 +216,17 @@ TEST_P(WaylandPointerTest, AxisVertical) { } TEST_P(WaylandPointerTest, AxisHorizontal) { - wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), + wl_pointer_send_enter(pointer_->resource(), 1, surface_->resource(), wl_fixed_from_int(50), wl_fixed_from_int(75)); - wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_LEFT, + wl_pointer_send_button(pointer_->resource(), 2, 1002, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); Sync(); std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); // Wayland servers typically send a value of 10 per mouse wheel click. - wl_pointer_send_axis(pointer->resource(), 1003, + wl_pointer_send_axis(pointer_->resource(), 1003, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_int(10)); diff --git a/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc index 2ee97407685..ac537496dc7 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc @@ -19,13 +19,13 @@ namespace ui { class WaylandSurfaceFactoryTest : public WaylandTest { public: - WaylandSurfaceFactoryTest() : surface_factory(connection.get()) {} + WaylandSurfaceFactoryTest() : surface_factory(connection_.get()) {} ~WaylandSurfaceFactoryTest() override {} void SetUp() override { WaylandTest::SetUp(); - canvas = surface_factory.CreateCanvasForWidget(widget); + canvas = surface_factory.CreateCanvasForWidget(widget_); ASSERT_TRUE(canvas); } @@ -41,11 +41,11 @@ TEST_P(WaylandSurfaceFactoryTest, Canvas) { canvas->GetSurface(); canvas->PresentCanvas(gfx::Rect(5, 10, 20, 15)); - Expectation damage = EXPECT_CALL(*surface, Damage(5, 10, 20, 15)); + Expectation damage = EXPECT_CALL(*surface_, Damage(5, 10, 20, 15)); wl_resource* buffer_resource = nullptr; - Expectation attach = EXPECT_CALL(*surface, Attach(_, 0, 0)) + Expectation attach = EXPECT_CALL(*surface_, Attach(_, 0, 0)) .WillOnce(SaveArg<0>(&buffer_resource)); - EXPECT_CALL(*surface, Commit()).After(damage, attach); + EXPECT_CALL(*surface_, Commit()).After(damage, attach); Sync(); @@ -65,11 +65,11 @@ TEST_P(WaylandSurfaceFactoryTest, CanvasResize) { canvas->GetSurface(); canvas->PresentCanvas(gfx::Rect(0, 0, 100, 50)); - Expectation damage = EXPECT_CALL(*surface, Damage(0, 0, 100, 50)); + Expectation damage = EXPECT_CALL(*surface_, Damage(0, 0, 100, 50)); wl_resource* buffer_resource = nullptr; - Expectation attach = EXPECT_CALL(*surface, Attach(_, 0, 0)) + Expectation attach = EXPECT_CALL(*surface_, Attach(_, 0, 0)) .WillOnce(SaveArg<0>(&buffer_resource)); - EXPECT_CALL(*surface, Commit()).After(damage, attach); + EXPECT_CALL(*surface_, Commit()).After(damage, attach); Sync(); diff --git a/chromium/ui/ozone/platform/wayland/wayland_test.cc b/chromium/ui/ozone/platform/wayland/wayland_test.cc index 7bc6c91e462..a56cbcb8a4f 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_test.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_test.cc @@ -27,48 +27,48 @@ WaylandTest::WaylandTest() { KeyboardLayoutEngineManager::SetKeyboardLayoutEngine( std::make_unique<StubKeyboardLayoutEngine>()); #endif - connection.reset(new WaylandConnection); - window = std::make_unique<WaylandWindow>(&delegate, connection.get(), - gfx::Rect(0, 0, 800, 600)); + connection_.reset(new WaylandConnection); + window_ = std::make_unique<WaylandWindow>(&delegate_, connection_.get(), + gfx::Rect(0, 0, 800, 600)); } WaylandTest::~WaylandTest() {} void WaylandTest::SetUp() { - ASSERT_TRUE(server.Start(GetParam())); - ASSERT_TRUE(connection->Initialize()); - EXPECT_CALL(delegate, OnAcceleratedWidgetAvailable(_, _)) - .WillOnce(SaveArg<0>(&widget)); - ASSERT_TRUE(window->Initialize()); - ASSERT_NE(widget, gfx::kNullAcceleratedWidget); + ASSERT_TRUE(server_.Start(GetParam())); + ASSERT_TRUE(connection_->Initialize()); + EXPECT_CALL(delegate_, OnAcceleratedWidgetAvailable(_, _)) + .WillOnce(SaveArg<0>(&widget_)); + ASSERT_TRUE(window_->Initialize()); + ASSERT_NE(widget_, gfx::kNullAcceleratedWidget); // Wait for the client to flush all pending requests from initialization. base::RunLoop().RunUntilIdle(); // Pause the server after it has responded to all incoming events. - server.Pause(); + server_.Pause(); - surface = server.GetObject<wl::MockSurface>(widget); - ASSERT_TRUE(surface); + surface_ = server_.GetObject<wl::MockSurface>(widget_); + ASSERT_TRUE(surface_); - initialized = true; + initialized_ = true; } void WaylandTest::TearDown() { - if (initialized) + if (initialized_) Sync(); } void WaylandTest::Sync() { // Resume the server, flushing its pending events. - server.Resume(); + server_.Resume(); // Wait for the client to finish processing these events. base::RunLoop().RunUntilIdle(); // Pause the server, after it has finished processing any follow-up requests // from the client. - server.Pause(); + server_.Pause(); } } // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/wayland_test.h b/chromium/ui/ozone/platform/wayland/wayland_test.h index 80587745e1a..20f7dfa47ad 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_test.h +++ b/chromium/ui/ozone/platform/wayland/wayland_test.h @@ -35,17 +35,17 @@ class WaylandTest : public ::testing::TestWithParam<uint32_t> { void Sync(); private: - bool initialized = false; - base::MessageLoopForUI message_loop; + base::MessageLoopForUI message_loop_; + bool initialized_ = false; protected: - wl::FakeServer server; - wl::MockSurface* surface; + wl::FakeServer server_; + wl::MockSurface* surface_; - MockPlatformWindowDelegate delegate; - std::unique_ptr<WaylandConnection> connection; - std::unique_ptr<WaylandWindow> window; - gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget; + MockPlatformWindowDelegate delegate_; + std::unique_ptr<WaylandConnection> connection_; + std::unique_ptr<WaylandWindow> window_; + gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; private: #if BUILDFLAG(USE_XKBCOMMON) diff --git a/chromium/ui/ozone/platform/wayland/wayland_touch.cc b/chromium/ui/ozone/platform/wayland/wayland_touch.cc index b8dc5437f79..9052eaf09b3 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_touch.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_touch.cc @@ -8,7 +8,6 @@ #include <wayland-client.h> #include "base/files/scoped_file.h" -#include "base/memory/ptr_util.h" #include "ui/base/ui_features.h" #include "ui/events/event.h" #include "ui/ozone/platform/wayland/wayland_connection.h" diff --git a/chromium/ui/ozone/platform/wayland/wayland_touch_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_touch_unittest.cc index c9afacb6a22..13a830f4baf 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_touch_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_touch_unittest.cc @@ -33,13 +33,13 @@ class WaylandTouchTest : public WaylandTest { void SetUp() override { WaylandTest::SetUp(); - wl_seat_send_capabilities(server.seat()->resource(), + wl_seat_send_capabilities(server_.seat()->resource(), WL_SEAT_CAPABILITY_TOUCH); Sync(); - touch = server.seat()->touch.get(); - ASSERT_TRUE(touch); + touch_ = server_.seat()->touch(); + ASSERT_TRUE(touch_); } protected: @@ -51,7 +51,7 @@ class WaylandTouchTest : public WaylandTest { EXPECT_EQ(event_type, key_event->type()); } - wl::MockTouch* touch; + wl::MockTouch* touch_; private: DISALLOW_COPY_AND_ASSIGN(WaylandTouchTest); @@ -59,21 +59,21 @@ class WaylandTouchTest : public WaylandTest { TEST_P(WaylandTouchTest, KeypressAndMotion) { std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event)); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event)); - wl_touch_send_down(touch->resource(), 1, 0, surface->resource(), 0 /* id */, + wl_touch_send_down(touch_->resource(), 1, 0, surface_->resource(), 0 /* id */, wl_fixed_from_int(50), wl_fixed_from_int(100)); Sync(); CheckEventType(ui::ET_TOUCH_PRESSED, event.get()); - wl_touch_send_motion(touch->resource(), 500, 0 /* id */, + wl_touch_send_motion(touch_->resource(), 500, 0 /* id */, wl_fixed_from_int(100), wl_fixed_from_int(100)); Sync(); CheckEventType(ui::ET_TOUCH_MOVED, event.get()); - wl_touch_send_up(touch->resource(), 1, 1000, 0 /* id */); + wl_touch_send_up(touch_->resource(), 1, 1000, 0 /* id */); Sync(); CheckEventType(ui::ET_TOUCH_RELEASED, event.get()); diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.cc b/chromium/ui/ozone/platform/wayland/wayland_window.cc index bed831b995c..6ebe40755d8 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_window.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_window.cc @@ -7,11 +7,11 @@ #include <wayland-client.h> #include "base/bind.h" -#include "base/memory/ptr_util.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/events/event.h" #include "ui/events/ozone/events_ozone.h" #include "ui/ozone/platform/wayland/wayland_connection.h" +#include "ui/ozone/platform/wayland/wayland_pointer.h" #include "ui/ozone/platform/wayland/xdg_surface_wrapper_v5.h" #include "ui/ozone/platform/wayland/xdg_surface_wrapper_v6.h" @@ -55,6 +55,8 @@ WaylandWindow::~WaylandWindow() { PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); connection_->RemoveWindow(surface_.id()); } + if (has_pointer_focus_) + connection_->pointer()->reset_window_with_pointer_focus(); } // static @@ -134,13 +136,21 @@ void WaylandWindow::SetTitle(const base::string16& title) { } void WaylandWindow::SetCapture() { + // Wayland does implicit grabs, and doesn't allow for explicit grabs. The + // exception to that seems to be popups, which can do a grab during show. Need + // to evaluate under what circumstances we need this. NOTIMPLEMENTED(); } void WaylandWindow::ReleaseCapture() { + // See comment in SetCapture() for details on wayland and grabs. NOTIMPLEMENTED(); } +bool WaylandWindow::HasCapture() const { + return has_implicit_grab_; +} + void WaylandWindow::ToggleFullscreen() { DCHECK(xdg_surface_); @@ -234,8 +244,7 @@ PlatformImeController* WaylandWindow::GetPlatformImeController() { return nullptr; } -bool WaylandWindow::CanDispatchEvent(const PlatformEvent& native_event) { - Event* event = static_cast<Event*>(native_event); +bool WaylandWindow::CanDispatchEvent(const PlatformEvent& event) { if (event->IsMouseEvent()) return has_pointer_focus_; if (event->IsKeyEvent()) @@ -268,14 +277,21 @@ void WaylandWindow::HandleSurfaceConfigure(int32_t width, else state_ = PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL; - if (old_state != state_) - delegate_->OnWindowStateChanged(state_); + // Update state before notifying delegate. + const bool did_active_change = is_active_ != is_activated; + is_active_ = is_activated; // Rather than call SetBounds here for every configure event, just save the // most recent bounds, and have WaylandConnection call ApplyPendingBounds // when it has finished processing events. We may get many configure events // in a row during an interactive resize, and only the last one matters. SetPendingBounds(width, height); + + if (old_state != state_) + delegate_->OnWindowStateChanged(state_); + + if (did_active_change) + delegate_->OnActivationChanged(is_active_); } void WaylandWindow::OnCloseRequest() { diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.h b/chromium/ui/ozone/platform/wayland/wayland_window.h index 8d205fa48b4..b534566ea63 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_window.h +++ b/chromium/ui/ozone/platform/wayland/wayland_window.h @@ -43,6 +43,7 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { // Set whether this window has pointer focus and should dispatch mouse events. void set_pointer_focus(bool focus) { has_pointer_focus_ = focus; } + bool has_pointer_focus() const { return has_pointer_focus_; } // Set whether this window has keyboard focus and should dispatch key events. void set_keyboard_focus(bool focus) { has_keyboard_focus_ = focus; } @@ -50,6 +51,13 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { // Set whether this window has touch focus and should dispatch touch events. void set_touch_focus(bool focus) { has_touch_focus_ = focus; } + // Set whether this window has an implicit grab (often referred to as capture + // in Chrome code). Implicit grabs happen while a pointer is down. + void set_has_implicit_grab(bool value) { has_implicit_grab_ = value; } + bool has_implicit_grab() const { return has_implicit_grab_; } + + bool is_active() const { return is_active_; } + // PlatformWindow void Show() override; void Hide() override; @@ -60,6 +68,7 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { void SetTitle(const base::string16& title) override; void SetCapture() override; void ReleaseCapture() override; + bool HasCapture() const override; void ToggleFullscreen() override; void Maximize() override; void Minimize() override; @@ -113,10 +122,13 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { bool has_pointer_focus_ = false; bool has_keyboard_focus_ = false; bool has_touch_focus_ = false; + bool has_implicit_grab_ = false; // Stores current states of the window. ui::PlatformWindowState state_; + bool is_active_ = false; + DISALLOW_COPY_AND_ASSIGN(WaylandWindow); }; diff --git a/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc index 2c2e2679a2a..77c1084fac8 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/ozone/platform/wayland/wayland_window.h" + #include <wayland-server-core.h> #include <xdg-shell-unstable-v5-server-protocol.h> #include <xdg-shell-unstable-v6-server-protocol.h> @@ -14,7 +16,6 @@ #include "ui/events/event.h" #include "ui/ozone/platform/wayland/fake_server.h" #include "ui/ozone/platform/wayland/wayland_test.h" -#include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/test/mock_platform_window_delegate.h" using ::testing::Eq; @@ -28,18 +29,18 @@ namespace ui { class WaylandWindowTest : public WaylandTest { public: WaylandWindowTest() - : test_mouse_event(ET_MOUSE_PRESSED, - gfx::Point(10, 15), - gfx::Point(10, 15), - ui::EventTimeStampFromSeconds(123456), - EF_LEFT_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON, - EF_LEFT_MOUSE_BUTTON) {} + : test_mouse_event_(ET_MOUSE_PRESSED, + gfx::Point(10, 15), + gfx::Point(10, 15), + ui::EventTimeStampFromSeconds(123456), + EF_LEFT_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON, + EF_LEFT_MOUSE_BUTTON) {} void SetUp() override { WaylandTest::SetUp(); - xdg_surface = surface->xdg_surface.get(); - ASSERT_TRUE(xdg_surface); + xdg_surface_ = surface_->xdg_surface(); + ASSERT_TRUE(xdg_surface_); } protected: @@ -47,26 +48,26 @@ class WaylandWindowTest : public WaylandTest { int height, uint32_t serial, struct wl_array* states) { - if (!xdg_surface->xdg_toplevel) { - xdg_surface_send_configure(xdg_surface->resource(), width, height, states, - serial); + if (!xdg_surface_->xdg_toplevel()) { + xdg_surface_send_configure(xdg_surface_->resource(), width, height, + states, serial); return; } // In xdg_shell_v6, both surfaces send serial configure event and toplevel // surfaces send other data like states, heights and widths. - zxdg_surface_v6_send_configure(xdg_surface->resource(), serial); - ASSERT_TRUE(xdg_surface->xdg_toplevel); - zxdg_toplevel_v6_send_configure(xdg_surface->xdg_toplevel->resource(), + zxdg_surface_v6_send_configure(xdg_surface_->resource(), serial); + ASSERT_TRUE(xdg_surface_->xdg_toplevel()); + zxdg_toplevel_v6_send_configure(xdg_surface_->xdg_toplevel()->resource(), width, height, states); } - // Depending on a shell version, xdg_surface or xdg_toplevel surface should + // Depending on a shell version, xdg_surface_ or xdg_toplevel surface should // get the mock calls. This method decided, which surface to use. wl::MockXdgSurface* GetXdgSurface() { if (GetParam() == kXdgShellV5) - return xdg_surface; - return xdg_surface->xdg_toplevel.get(); + return xdg_surface_; + return xdg_surface_->xdg_toplevel(); } void SetWlArrayWithState(uint32_t state, wl_array* states) { @@ -80,9 +81,9 @@ class WaylandWindowTest : public WaylandTest { SetWlArrayWithState(XDG_SURFACE_STATE_ACTIVATED, states); } - wl::MockXdgSurface* xdg_surface; + wl::MockXdgSurface* xdg_surface_; - MouseEvent test_mouse_event; + MouseEvent test_mouse_event_; private: DISALLOW_COPY_AND_ASSIGN(WaylandWindowTest); @@ -90,25 +91,26 @@ class WaylandWindowTest : public WaylandTest { TEST_P(WaylandWindowTest, SetTitle) { EXPECT_CALL(*GetXdgSurface(), SetTitle(StrEq("hello"))); - window->SetTitle(base::ASCIIToUTF16("hello")); + window_->SetTitle(base::ASCIIToUTF16("hello")); } TEST_P(WaylandWindowTest, MaximizeAndRestore) { wl_array states; InitializeWlArrayWithActivatedState(&states); - EXPECT_CALL(delegate, + EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_MAXIMIZED))); SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states); EXPECT_CALL(*GetXdgSurface(), SetMaximized()); - window->Maximize(); + window_->Maximize(); SendConfigureEvent(0, 0, 1, &states); Sync(); - EXPECT_CALL(delegate, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); + EXPECT_CALL(delegate_, + OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); EXPECT_CALL(*GetXdgSurface(), UnsetMaximized()); - window->Restore(); + window_->Restore(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SendConfigureEvent(0, 0, 2, &states); @@ -120,7 +122,8 @@ TEST_P(WaylandWindowTest, Minimize) { wl_array_init(&states); // Initialize to normal first. - EXPECT_CALL(delegate, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); + EXPECT_CALL(delegate_, + OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); SendConfigureEvent(0, 0, 1, &states); Sync(); @@ -129,8 +132,8 @@ TEST_P(WaylandWindowTest, Minimize) { // notified about the state, because 1) minimized state was set manually // in WaylandWindow, and it has been confirmed in a back call from the server, // which resulted in the same state as before. - EXPECT_CALL(delegate, OnWindowStateChanged(_)).Times(0); - window->Minimize(); + EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0); + window_->Minimize(); // Reinitialize wl_array, which removes previous old states. wl_array_init(&states); SendConfigureEvent(0, 0, 2, &states); @@ -144,15 +147,16 @@ TEST_P(WaylandWindowTest, SetFullscreenAndRestore) { SetWlArrayWithState(XDG_SURFACE_STATE_FULLSCREEN, &states); EXPECT_CALL(*GetXdgSurface(), SetFullscreen()); - EXPECT_CALL(delegate, + EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_FULLSCREEN))); - window->ToggleFullscreen(); + window_->ToggleFullscreen(); SendConfigureEvent(0, 0, 1, &states); Sync(); EXPECT_CALL(*GetXdgSurface(), UnsetFullscreen()); - EXPECT_CALL(delegate, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); - window->Restore(); + EXPECT_CALL(delegate_, + OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); + window_->Restore(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SendConfigureEvent(0, 0, 2, &states); @@ -164,25 +168,26 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { InitializeWlArrayWithActivatedState(&states); EXPECT_CALL(*GetXdgSurface(), SetMaximized()); - EXPECT_CALL(delegate, + EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_MAXIMIZED))); - window->Maximize(); + window_->Maximize(); SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states); SendConfigureEvent(0, 0, 2, &states); Sync(); EXPECT_CALL(*GetXdgSurface(), SetFullscreen()); - EXPECT_CALL(delegate, + EXPECT_CALL(delegate_, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_FULLSCREEN))); - window->ToggleFullscreen(); + window_->ToggleFullscreen(); SetWlArrayWithState(XDG_SURFACE_STATE_FULLSCREEN, &states); SendConfigureEvent(0, 0, 3, &states); Sync(); EXPECT_CALL(*GetXdgSurface(), UnsetFullscreen()); EXPECT_CALL(*GetXdgSurface(), UnsetMaximized()); - EXPECT_CALL(delegate, OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); - window->Restore(); + EXPECT_CALL(delegate_, + OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_NORMAL))); + window_->Restore(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SendConfigureEvent(0, 0, 4, &states); @@ -190,26 +195,26 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { } TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximize) { - const gfx::Rect current_bounds = window->GetBounds(); + const gfx::Rect current_bounds = window_->GetBounds(); wl_array states; InitializeWlArrayWithActivatedState(&states); const gfx::Rect maximized_bounds = gfx::Rect(0, 0, 1024, 768); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(maximized_bounds))); - window->Maximize(); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(maximized_bounds))); + window_->Maximize(); SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states); SendConfigureEvent(maximized_bounds.width(), maximized_bounds.height(), 1, &states); Sync(); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(current_bounds))); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(current_bounds))); // Both in XdgV5 and XdgV6, surfaces implement SetWindowGeometry method. // Thus, using a toplevel object in XdgV6 case is not right thing. Use a // surface here instead. - EXPECT_CALL(*xdg_surface, SetWindowGeometry(0, 0, current_bounds.width(), - current_bounds.height())); - window->Restore(); + EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, current_bounds.width(), + current_bounds.height())); + window_->Restore(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SendConfigureEvent(0, 0, 2, &states); @@ -217,26 +222,26 @@ TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximize) { } TEST_P(WaylandWindowTest, RestoreBoundsAfterFullscreen) { - const gfx::Rect current_bounds = window->GetBounds(); + const gfx::Rect current_bounds = window_->GetBounds(); wl_array states; InitializeWlArrayWithActivatedState(&states); const gfx::Rect fullscreen_bounds = gfx::Rect(0, 0, 1280, 720); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(fullscreen_bounds))); - window->ToggleFullscreen(); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(fullscreen_bounds))); + window_->ToggleFullscreen(); SetWlArrayWithState(XDG_SURFACE_STATE_FULLSCREEN, &states); SendConfigureEvent(fullscreen_bounds.width(), fullscreen_bounds.height(), 1, &states); Sync(); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(current_bounds))); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(current_bounds))); // Both in XdgV5 and XdgV6, surfaces implement SetWindowGeometry method. // Thus, using a toplevel object in XdgV6 case is not right thing. Use a // surface here instead. - EXPECT_CALL(*xdg_surface, SetWindowGeometry(0, 0, current_bounds.width(), - current_bounds.height())); - window->Restore(); + EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, current_bounds.width(), + current_bounds.height())); + window_->Restore(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SendConfigureEvent(0, 0, 2, &states); @@ -244,29 +249,29 @@ TEST_P(WaylandWindowTest, RestoreBoundsAfterFullscreen) { } TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximizeAndFullscreen) { - const gfx::Rect current_bounds = window->GetBounds(); + const gfx::Rect current_bounds = window_->GetBounds(); wl_array states; InitializeWlArrayWithActivatedState(&states); const gfx::Rect maximized_bounds = gfx::Rect(0, 0, 1024, 768); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(maximized_bounds))); - window->Maximize(); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(maximized_bounds))); + window_->Maximize(); SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states); SendConfigureEvent(maximized_bounds.width(), maximized_bounds.height(), 1, &states); Sync(); const gfx::Rect fullscreen_bounds = gfx::Rect(0, 0, 1280, 720); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(fullscreen_bounds))); - window->ToggleFullscreen(); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(fullscreen_bounds))); + window_->ToggleFullscreen(); SetWlArrayWithState(XDG_SURFACE_STATE_FULLSCREEN, &states); SendConfigureEvent(fullscreen_bounds.width(), fullscreen_bounds.height(), 2, &states); Sync(); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(maximized_bounds))); - window->Maximize(); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(maximized_bounds))); + window_->Maximize(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SetWlArrayWithState(XDG_SURFACE_STATE_MAXIMIZED, &states); @@ -274,13 +279,13 @@ TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximizeAndFullscreen) { &states); Sync(); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(current_bounds))); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(current_bounds))); // Both in XdgV5 and XdgV6, surfaces implement SetWindowGeometry method. // Thus, using a toplevel object in XdgV6 case is not right thing. Use a // surface here instead. - EXPECT_CALL(*xdg_surface, SetWindowGeometry(0, 0, current_bounds.width(), - current_bounds.height())); - window->Restore(); + EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, current_bounds.width(), + current_bounds.height())); + window_->Restore(); // Reinitialize wl_array, which removes previous old states. InitializeWlArrayWithActivatedState(&states); SendConfigureEvent(0, 0, 4, &states); @@ -288,19 +293,19 @@ TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximizeAndFullscreen) { } TEST_P(WaylandWindowTest, SendsBoundsOnRequest) { - const gfx::Rect initial_bounds = window->GetBounds(); + const gfx::Rect initial_bounds = window_->GetBounds(); const gfx::Rect new_bounds = gfx::Rect(0, 0, initial_bounds.width() + 10, initial_bounds.height() + 10); - EXPECT_CALL(delegate, OnBoundsChanged(Eq(new_bounds))); - window->SetBounds(new_bounds); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(new_bounds))); + window_->SetBounds(new_bounds); wl_array states; InitializeWlArrayWithActivatedState(&states); // First case is when Wayland sends a configure event with 0,0 height and // widht. - EXPECT_CALL(*xdg_surface, + EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, new_bounds.width(), new_bounds.height())) .Times(2); SendConfigureEvent(0, 0, 2, &states); @@ -314,17 +319,22 @@ TEST_P(WaylandWindowTest, SendsBoundsOnRequest) { } TEST_P(WaylandWindowTest, CanDispatchMouseEventDefault) { - EXPECT_FALSE(window->CanDispatchEvent(&test_mouse_event)); + EXPECT_FALSE(window_->CanDispatchEvent(&test_mouse_event_)); } TEST_P(WaylandWindowTest, CanDispatchMouseEventFocus) { - window->set_pointer_focus(true); - EXPECT_TRUE(window->CanDispatchEvent(&test_mouse_event)); + // set_pointer_focus(true) requires a WaylandPointer. + wl_seat_send_capabilities(server_.seat()->resource(), + WL_SEAT_CAPABILITY_POINTER); + Sync(); + ASSERT_TRUE(connection_->pointer()); + window_->set_pointer_focus(true); + EXPECT_TRUE(window_->CanDispatchEvent(&test_mouse_event_)); } TEST_P(WaylandWindowTest, CanDispatchMouseEventUnfocus) { - window->set_pointer_focus(false); - EXPECT_FALSE(window->CanDispatchEvent(&test_mouse_event)); + EXPECT_FALSE(window_->has_pointer_focus()); + EXPECT_FALSE(window_->CanDispatchEvent(&test_mouse_event_)); } ACTION_P(CloneEvent, ptr) { @@ -333,17 +343,47 @@ ACTION_P(CloneEvent, ptr) { TEST_P(WaylandWindowTest, DispatchEvent) { std::unique_ptr<Event> event; - EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event)); - window->DispatchEvent(&test_mouse_event); + EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); + window_->DispatchEvent(&test_mouse_event_); ASSERT_TRUE(event); ASSERT_TRUE(event->IsMouseEvent()); auto* mouse_event = event->AsMouseEvent(); - EXPECT_EQ(mouse_event->location_f(), test_mouse_event.location_f()); - EXPECT_EQ(mouse_event->root_location_f(), test_mouse_event.root_location_f()); - EXPECT_EQ(mouse_event->time_stamp(), test_mouse_event.time_stamp()); - EXPECT_EQ(mouse_event->button_flags(), test_mouse_event.button_flags()); + EXPECT_EQ(mouse_event->location_f(), test_mouse_event_.location_f()); + EXPECT_EQ(mouse_event->root_location_f(), + test_mouse_event_.root_location_f()); + EXPECT_EQ(mouse_event->time_stamp(), test_mouse_event_.time_stamp()); + EXPECT_EQ(mouse_event->button_flags(), test_mouse_event_.button_flags()); EXPECT_EQ(mouse_event->changed_button_flags(), - test_mouse_event.changed_button_flags()); + test_mouse_event_.changed_button_flags()); +} + +TEST_P(WaylandWindowTest, HasCaptureUpdatedOnPointerEvents) { + wl_seat_send_capabilities(server_.seat()->resource(), + WL_SEAT_CAPABILITY_POINTER); + + Sync(); + + wl::MockPointer* pointer = server_.seat()->pointer(); + ASSERT_TRUE(pointer); + + wl_pointer_send_enter(pointer->resource(), 1, surface_->resource(), 0, 0); + Sync(); + EXPECT_FALSE(window_->HasCapture()); + + wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_LEFT, + WL_POINTER_BUTTON_STATE_PRESSED); + Sync(); + EXPECT_TRUE(window_->HasCapture()); + + wl_pointer_send_motion(pointer->resource(), 1003, wl_fixed_from_int(400), + wl_fixed_from_int(500)); + Sync(); + EXPECT_TRUE(window_->HasCapture()); + + wl_pointer_send_button(pointer->resource(), 4, 1004, BTN_LEFT, + WL_POINTER_BUTTON_STATE_RELEASED); + Sync(); + EXPECT_FALSE(window_->HasCapture()); } TEST_P(WaylandWindowTest, ConfigureEvent) { @@ -354,14 +394,14 @@ TEST_P(WaylandWindowTest, ConfigureEvent) { // Make sure that the implementation does not call OnBoundsChanged for each // configure event if it receives multiple in a row. - EXPECT_CALL(delegate, OnBoundsChanged(Eq(gfx::Rect(0, 0, 1500, 1000)))); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(gfx::Rect(0, 0, 1500, 1000)))); // Responding to a configure event, the window geometry in here must respect // the sizing negotiations specified by the configure event. - // |xdg_surface| must receive the following calls in both xdg_shell_v5 and + // |xdg_surface_| must receive the following calls in both xdg_shell_v5 and // xdg_shell_v6. Other calls like SetTitle or SetMaximized are recieved by - // xdg_toplevel in xdg_shell_v6 and by xdg_surface in xdg_shell_v5. - EXPECT_CALL(*xdg_surface, SetWindowGeometry(0, 0, 1500, 1000)).Times(1); - EXPECT_CALL(*xdg_surface, AckConfigure(13)); + // xdg_toplevel in xdg_shell_v6 and by xdg_surface_ in xdg_shell_v5. + EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, 1500, 1000)).Times(1); + EXPECT_CALL(*xdg_surface_, AckConfigure(13)); } TEST_P(WaylandWindowTest, ConfigureEventWithNulledSize) { @@ -372,11 +412,31 @@ TEST_P(WaylandWindowTest, ConfigureEventWithNulledSize) { // call back with desired sizes. In this case, that's the actual size of // the window. SendConfigureEvent(0, 0, 14, &states); - // |xdg_surface| must receive the following calls in both xdg_shell_v5 and + // |xdg_surface_| must receive the following calls in both xdg_shell_v5 and // xdg_shell_v6. Other calls like SetTitle or SetMaximized are recieved by - // xdg_toplevel in xdg_shell_v6 and by xdg_surface in xdg_shell_v5. - EXPECT_CALL(*xdg_surface, SetWindowGeometry(0, 0, 800, 600)); - EXPECT_CALL(*xdg_surface, AckConfigure(14)); + // xdg_toplevel in xdg_shell_v6 and by xdg_surface_ in xdg_shell_v5. + EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, 800, 600)); + EXPECT_CALL(*xdg_surface_, AckConfigure(14)); +} + +TEST_P(WaylandWindowTest, OnActivationChanged) { + EXPECT_FALSE(window_->is_active()); + + { + wl_array states; + InitializeWlArrayWithActivatedState(&states); + EXPECT_CALL(delegate_, OnActivationChanged(Eq(true))); + SendConfigureEvent(0, 0, 1, &states); + Sync(); + EXPECT_TRUE(window_->is_active()); + } + + wl_array states; + wl_array_init(&states); + EXPECT_CALL(delegate_, OnActivationChanged(Eq(false))); + SendConfigureEvent(0, 0, 2, &states); + Sync(); + EXPECT_FALSE(window_->is_active()); } INSTANTIATE_TEST_CASE_P(XdgVersionV5Test, |