diff options
Diffstat (limited to '0010-ozone-wayland-Extract-window-management-methods-to-o.patch')
-rw-r--r-- | 0010-ozone-wayland-Extract-window-management-methods-to-o.patch | 810 |
1 files changed, 810 insertions, 0 deletions
diff --git a/0010-ozone-wayland-Extract-window-management-methods-to-o.patch b/0010-ozone-wayland-Extract-window-management-methods-to-o.patch new file mode 100644 index 000000000000..c784acd8e0f1 --- /dev/null +++ b/0010-ozone-wayland-Extract-window-management-methods-to-o.patch @@ -0,0 +1,810 @@ +From 1cac377724089974aef3dd66b215301bfd6c3dbd Mon Sep 17 00:00:00 2001 +From: Maksim Sisov <msisov@igalia.com> +Date: Fri, 26 Jul 2019 04:56:22 +0000 +Subject: [PATCH 10/11] [ozone/wayland]: Extract window management methods to + own class + +WaylandConnection still has been overloaded with different tasks. + +Thus, to make code cleaner, extract window management methods into +a separate class called WaylandWindowManager, which is responsible +for managing windows. + +Bug: 987239 +Change-Id: Ic74291842e24e919dae7335ebb7c89b08a81a61c +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1715193 +Commit-Queue: Maksim Sisov <msisov@igalia.com> +Reviewed-by: Antonio Gomes <tonikitoo@igalia.com> +Cr-Commit-Position: refs/heads/master@{#681191} +--- + ui/ozone/platform/wayland/BUILD.gn | 3 + + .../wayland/gpu/wayland_surface_factory.cc | 4 +- + .../wayland/host/wayland_connection.cc | 69 +----- + .../wayland/host/wayland_connection.h | 23 +- + .../wayland/host/wayland_data_device.cc | 4 +- + .../wayland/host/wayland_data_source.cc | 3 +- + .../host/wayland_input_method_context.cc | 3 +- + .../platform/wayland/host/wayland_screen.cc | 13 +- + .../platform/wayland/host/wayland_window.cc | 18 +- + .../wayland/host/wayland_window_manager.cc | 90 +++++++ + .../wayland/host/wayland_window_manager.h | 60 +++++ + .../host/wayland_window_manager_unittests.cc | 222 ++++++++++++++++++ + 12 files changed, 424 insertions(+), 88 deletions(-) + create mode 100644 ui/ozone/platform/wayland/host/wayland_window_manager.cc + create mode 100644 ui/ozone/platform/wayland/host/wayland_window_manager.h + create mode 100644 ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc + +diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn +index a1560a20fe23..157d1beea880 100644 +--- a/ui/ozone/platform/wayland/BUILD.gn ++++ b/ui/ozone/platform/wayland/BUILD.gn +@@ -74,6 +74,8 @@ source_set("wayland") { + "host/wayland_touch.h", + "host/wayland_window.cc", + "host/wayland_window.h", ++ "host/wayland_window_manager.cc", ++ "host/wayland_window_manager.h", + "host/wayland_zwp_linux_dmabuf.cc", + "host/wayland_zwp_linux_dmabuf.h", + "host/xdg_popup_wrapper.h", +@@ -250,6 +252,7 @@ source_set("wayland_unittests") { + "host/wayland_pointer_unittest.cc", + "host/wayland_screen_unittest.cc", + "host/wayland_touch_unittest.cc", ++ "host/wayland_window_manager_unittests.cc", + "host/wayland_window_unittest.cc", + "test/wayland_test.cc", + "test/wayland_test.h", +diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc +index b5dba5fd525b..a5db42ef1b18 100644 +--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc ++++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc +@@ -16,6 +16,7 @@ + #include "ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h" + #include "ui/ozone/platform/wayland/host/wayland_connection.h" + #include "ui/ozone/platform/wayland/host/wayland_window.h" ++#include "ui/ozone/platform/wayland/host/wayland_window_manager.h" + + #if defined(WAYLAND_GBM) + #include "ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h" +@@ -61,7 +62,8 @@ scoped_refptr<gl::GLSurface> GLOzoneEGLWayland::CreateViewGLSurface( + !connection_) + return nullptr; + +- WaylandWindow* window = connection_->GetWindow(widget); ++ WaylandWindow* window = ++ connection_->wayland_window_manager()->GetWindow(widget); + if (!window) + return nullptr; + +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc +index a949baf5a934..bf6d12717861 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.cc ++++ b/ui/ozone/platform/wayland/host/wayland_connection.cc +@@ -45,7 +45,8 @@ constexpr uint32_t kMaxTextInputManagerVersion = 1; + constexpr uint32_t kMinWlOutputVersion = 2; + } // namespace + +-WaylandConnection::WaylandConnection() : controller_(FROM_HERE) {} ++WaylandConnection::WaylandConnection() ++ : wayland_window_manager_(this), controller_(FROM_HERE) {} + + WaylandConnection::~WaylandConnection() = default; + +@@ -122,70 +123,17 @@ void WaylandConnection::ScheduleFlush() { + scheduled_flush_ = true; + } + +-WaylandWindow* WaylandConnection::GetWindow( +- gfx::AcceleratedWidget widget) const { +- auto it = window_map_.find(widget); +- return it == window_map_.end() ? nullptr : it->second; +-} +- +-WaylandWindow* WaylandConnection::GetWindowWithLargestBounds() const { +- WaylandWindow* window_with_largest_bounds = nullptr; +- for (auto entry : window_map_) { +- if (!window_with_largest_bounds) { +- window_with_largest_bounds = entry.second; +- continue; +- } +- WaylandWindow* window = entry.second; +- if (window_with_largest_bounds->GetBounds() < window->GetBounds()) +- window_with_largest_bounds = window; +- } +- return window_with_largest_bounds; +-} +- +-WaylandWindow* WaylandConnection::GetCurrentFocusedWindow() const { +- for (auto entry : window_map_) { +- WaylandWindow* window = entry.second; +- if (window->has_pointer_focus()) +- return window; +- } +- return nullptr; +-} +- +-WaylandWindow* WaylandConnection::GetCurrentKeyboardFocusedWindow() const { +- for (auto entry : window_map_) { +- WaylandWindow* window = entry.second; +- if (window->has_keyboard_focus()) +- return window; +- } +- return nullptr; +-} +- +-std::vector<WaylandWindow*> WaylandConnection::GetWindowsOnOutput( +- uint32_t output_id) { +- std::vector<WaylandWindow*> result; +- for (auto entry : window_map_) { +- if (entry.second->entered_outputs_ids().count(output_id) > 0) +- result.push_back(entry.second); +- } +- return result; +-} +- +-void WaylandConnection::AddWindow(gfx::AcceleratedWidget widget, +- WaylandWindow* window) { ++void WaylandConnection::OnWindowAdded(WaylandWindow* window) { + DCHECK(buffer_manager_host_); + buffer_manager_host_->OnWindowAdded(window); +- +- window_map_[widget] = window; + } + +-void WaylandConnection::RemoveWindow(gfx::AcceleratedWidget widget) { ++void WaylandConnection::OnWindowRemoved(WaylandWindow* window) { + if (touch_) +- touch_->RemoveTouchPoints(window_map_[widget]); ++ touch_->RemoveTouchPoints(window); + + DCHECK(buffer_manager_host_); +- buffer_manager_host_->OnWindowRemoved(window_map_[widget]); +- +- window_map_.erase(widget); ++ buffer_manager_host_->OnWindowRemoved(window); + } + + void WaylandConnection::SetCursorBitmap(const std::vector<SkBitmap>& bitmaps, +@@ -260,8 +208,9 @@ void WaylandConnection::DispatchUiEvent(Event* event) { + + void WaylandConnection::OnFileCanReadWithoutBlocking(int fd) { + wl_display_dispatch(display_.get()); +- for (const auto& window : window_map_) +- window.second->ApplyPendingBounds(); ++ std::vector<WaylandWindow*> windows = wayland_window_manager_.GetAllWindows(); ++ for (auto* window : windows) ++ window->ApplyPendingBounds(); + } + + void WaylandConnection::OnFileCanWriteWithoutBlocking(int fd) {} +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h +index 9ae6527337c6..8a56ebc6b921 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.h ++++ b/ui/ozone/platform/wayland/host/wayland_connection.h +@@ -25,6 +25,7 @@ + #include "ui/ozone/platform/wayland/host/wayland_output.h" + #include "ui/ozone/platform/wayland/host/wayland_pointer.h" + #include "ui/ozone/platform/wayland/host/wayland_touch.h" ++#include "ui/ozone/platform/wayland/host/wayland_window_manager.h" + + namespace ui { + +@@ -46,6 +47,9 @@ class WaylandConnection : public PlatformEventSource, + // Schedules a flush of the Wayland connection. + void ScheduleFlush(); + ++ void OnWindowAdded(WaylandWindow* window); ++ void OnWindowRemoved(WaylandWindow* window); ++ + wl_display* display() const { return display_.get(); } + wl_compositor* compositor() const { return compositor_.get(); } + wl_subcompositor* subcompositor() const { return subcompositor_.get(); } +@@ -58,16 +62,6 @@ class WaylandConnection : public PlatformEventSource, + return text_input_manager_v1_.get(); + } + +- WaylandWindow* GetWindow(gfx::AcceleratedWidget widget) const; +- WaylandWindow* GetWindowWithLargestBounds() const; +- WaylandWindow* GetCurrentFocusedWindow() const; +- WaylandWindow* GetCurrentKeyboardFocusedWindow() const; +- // TODO(crbug.com/971525): remove this in favor of targeted subscription of +- // windows to their outputs. +- std::vector<WaylandWindow*> GetWindowsOnOutput(uint32_t output_id); +- void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window); +- void RemoveWindow(gfx::AcceleratedWidget widget); +- + void set_serial(uint32_t serial) { serial_ = serial; } + uint32_t serial() const { return serial_; } + +@@ -102,6 +96,10 @@ class WaylandConnection : public PlatformEventSource, + + WaylandShm* shm() const { return shm_.get(); } + ++ WaylandWindowManager* wayland_window_manager() { ++ return &wayland_window_manager_; ++ } ++ + std::vector<gfx::BufferFormat> GetSupportedBufferFormats(); + + // Starts drag with |data| to be delivered, |operation| supported by the +@@ -166,8 +164,6 @@ class WaylandConnection : public PlatformEventSource, + // xdg_shell_listener + static void Ping(void* data, xdg_shell* shell, uint32_t serial); + +- base::flat_map<gfx::AcceleratedWidget, WaylandWindow*> window_map_; +- + wl::Object<wl_display> display_; + wl::Object<wl_registry> registry_; + wl::Object<wl_compositor> compositor_; +@@ -191,6 +187,9 @@ class WaylandConnection : public PlatformEventSource, + std::unique_ptr<WaylandShm> shm_; + std::unique_ptr<WaylandBufferManagerHost> buffer_manager_host_; + ++ // Manages Wayland windows. ++ WaylandWindowManager wayland_window_manager_; ++ + bool scheduled_flush_ = false; + bool watching_ = false; + base::MessagePumpLibevent::FdWatchController controller_; +diff --git a/ui/ozone/platform/wayland/host/wayland_data_device.cc b/ui/ozone/platform/wayland/host/wayland_data_device.cc +index f258e8ddba2d..a36cd3b7a888 100644 +--- a/ui/ozone/platform/wayland/host/wayland_data_device.cc ++++ b/ui/ozone/platform/wayland/host/wayland_data_device.cc +@@ -146,7 +146,9 @@ void WaylandDataDevice::DeliverDragData(const std::string& mime_type, + void WaylandDataDevice::StartDrag(wl_data_source* data_source, + const ui::OSExchangeData& data) { + DCHECK(data_source); +- WaylandWindow* window = connection_->GetCurrentFocusedWindow(); ++ ++ WaylandWindow* window = ++ connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + if (!window) { + LOG(ERROR) << "Failed to get focused window."; + return; +diff --git a/ui/ozone/platform/wayland/host/wayland_data_source.cc b/ui/ozone/platform/wayland/host/wayland_data_source.cc +index f8ba38a0fa51..dcd6b75aa299 100644 +--- a/ui/ozone/platform/wayland/host/wayland_data_source.cc ++++ b/ui/ozone/platform/wayland/host/wayland_data_source.cc +@@ -50,7 +50,8 @@ void WaylandDataSource::Offer(const ui::OSExchangeData& data) { + mime_types.push_back(kTextMimeType); + mime_types.push_back(kTextMimeTypeUtf8); + +- source_window_ = connection_->GetCurrentFocusedWindow(); ++ source_window_ = ++ connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + for (auto& mime_type : mime_types) + wl_data_source_offer(data_source_.get(), mime_type.data()); + } +diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc +index 700232b9b36e..37feebecc9dc 100644 +--- a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc ++++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc +@@ -103,7 +103,8 @@ void WaylandInputMethodContext::Reset() { + } + + void WaylandInputMethodContext::Focus() { +- WaylandWindow* window = connection_->GetCurrentKeyboardFocusedWindow(); ++ WaylandWindow* window = ++ connection_->wayland_window_manager()->GetCurrentKeyboardFocusedWindow(); + if (!text_input_ || !window) + return; + +diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc +index ef372ad794d3..126b252624ab 100644 +--- a/ui/ozone/platform/wayland/host/wayland_screen.cc ++++ b/ui/ozone/platform/wayland/host/wayland_screen.cc +@@ -81,7 +81,8 @@ void WaylandScreen::OnOutputMetricsChanged(uint32_t output_id, + changed_display, is_primary ? display::DisplayList::Type::PRIMARY + : display::DisplayList::Type::NOT_PRIMARY); + +- for (auto* window : connection_->GetWindowsOnOutput(output_id)) ++ auto* wayland_window_manager = connection_->wayland_window_manager(); ++ for (auto* window : wayland_window_manager->GetWindowsOnOutput(output_id)) + window->UpdateBufferScale(true); + } + +@@ -101,7 +102,7 @@ display::Display WaylandScreen::GetPrimaryDisplay() const { + + display::Display WaylandScreen::GetDisplayForAcceleratedWidget( + gfx::AcceleratedWidget widget) const { +- auto* window = connection_->GetWindow(widget); ++ auto* window = connection_->wayland_window_manager()->GetWindow(widget); + // A window might be destroyed by this time on shutting down the browser. + if (!window) + return GetPrimaryDisplay(); +@@ -139,6 +140,7 @@ display::Display WaylandScreen::GetDisplayForAcceleratedWidget( + } + + gfx::Point WaylandScreen::GetCursorScreenPoint() const { ++ auto* wayland_window_manager = connection_->wayland_window_manager(); + // Wayland does not provide either location of surfaces in global space + // coordinate system or location of a pointer. Instead, only locations of + // mouse/touch events are known. Given that Chromium assumes top-level windows +@@ -149,10 +151,10 @@ gfx::Point WaylandScreen::GetCursorScreenPoint() const { + // last known cursor position. Otherwise, return such a point, which is not + // contained by any of the windows. + auto* cursor_position = connection_->wayland_cursor_position(); +- if (connection_->GetCurrentFocusedWindow() && cursor_position) ++ if (wayland_window_manager->GetCurrentFocusedWindow() && cursor_position) + return cursor_position->GetCursorSurfacePoint(); + +- WaylandWindow* window = connection_->GetWindowWithLargestBounds(); ++ auto* window = wayland_window_manager->GetWindowWithLargestBounds(); + DCHECK(window); + const gfx::Rect bounds = window->GetBounds(); + return gfx::Point(bounds.width() + 10, bounds.height() + 10); +@@ -162,7 +164,8 @@ gfx::AcceleratedWidget WaylandScreen::GetAcceleratedWidgetAtScreenPoint( + const gfx::Point& point) const { + // It is safe to check only for focused windows and test if they contain the + // point or not. +- auto* window = connection_->GetCurrentFocusedWindow(); ++ auto* window = ++ connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + if (window && window->GetBounds().Contains(point)) + return window->GetWidget(); + return gfx::kNullAcceleratedWidget; +diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc +index 9afed0cc87fb..12b3661985a6 100644 +--- a/ui/ozone/platform/wayland/host/wayland_window.cc ++++ b/ui/ozone/platform/wayland/host/wayland_window.cc +@@ -105,7 +105,7 @@ WaylandWindow::~WaylandWindow() { + } + + PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); +- connection_->RemoveWindow(GetWidget()); ++ connection_->wayland_window_manager()->RemoveWindow(GetWidget()); + + if (parent_window_) + parent_window_->set_child_window(nullptr); +@@ -165,7 +165,7 @@ bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) { + + connection_->ScheduleFlush(); + +- connection_->AddWindow(GetWidget(), this); ++ connection_->wayland_window_manager()->AddWindow(GetWidget(), this); + PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); + delegate_->OnAcceleratedWidgetAvailable(GetWidget()); + +@@ -249,7 +249,8 @@ void WaylandWindow::CreateXdgSurface() { + void WaylandWindow::CreateAndShowTooltipSubSurface() { + // Since Aura does not not provide a reference parent window, needed by + // Wayland, we get the current focused window to place and show the tooltips. +- parent_window_ = connection_->GetCurrentFocusedWindow(); ++ parent_window_ = ++ connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + + // Tooltip creation is an async operation. By the time Aura actually creates + // the tooltip, it is possible that the user has already moved the +@@ -563,7 +564,8 @@ uint32_t WaylandWindow::DispatchEvent(const PlatformEvent& native_event) { + // Parent window of the main menu window is not a popup, but rather an + // xdg surface. + DCHECK(!parent_window_->xdg_popup() && parent_window_->xdg_surface()); +- WaylandWindow* window = connection_->GetCurrentFocusedWindow(); ++ auto* window = ++ connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + if (window) { + ConvertEventLocationToTargetWindowLocation(GetBounds().origin(), + window->GetBounds().origin(), +@@ -802,7 +804,8 @@ void WaylandWindow::MaybeTriggerPendingStateChange() { + + WaylandWindow* WaylandWindow::GetParentWindow( + gfx::AcceleratedWidget parent_widget) { +- WaylandWindow* parent_window = connection_->GetWindow(parent_widget); ++ auto* parent_window = ++ connection_->wayland_window_manager()->GetWindow(parent_widget); + + // If propagated parent has already had a child, it means that |this| is a + // submenu of a 3-dot menu. In aura, the parent of a 3-dot menu and its +@@ -816,7 +819,7 @@ WaylandWindow* WaylandWindow::GetParentWindow( + if (parent_window && parent_window->child_window_) + return parent_window->child_window_; + if (!parent_window) +- return connection_->GetCurrentFocusedWindow(); ++ return connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + return parent_window; + } + +@@ -873,7 +876,8 @@ void WaylandWindow::RemoveEnteredOutputId(struct wl_output* output) { + void WaylandWindow::UpdateCursorPositionFromEvent( + std::unique_ptr<Event> event) { + DCHECK(event->IsLocatedEvent()); +- auto* window = connection_->GetCurrentFocusedWindow(); ++ auto* window = ++ connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + // This is a tricky part. Initially, Wayland sends events to surfaces the + // events are targeted for. But, in order to fulfill Chromium's assumptions + // about event targets, some of the events are rerouted and their locations +diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager.cc b/ui/ozone/platform/wayland/host/wayland_window_manager.cc +new file mode 100644 +index 000000000000..c7cae0c9f937 +--- /dev/null ++++ b/ui/ozone/platform/wayland/host/wayland_window_manager.cc +@@ -0,0 +1,90 @@ ++// Copyright 2019 The Chromium Authors. All rights reserved. ++// 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/host/wayland_window_manager.h" ++ ++#include "ui/ozone/platform/wayland/host/wayland_connection.h" ++#include "ui/ozone/platform/wayland/host/wayland_window.h" ++ ++namespace ui { ++ ++WaylandWindowManager::WaylandWindowManager(WaylandConnection* connection) ++ : connection_(connection) {} ++ ++WaylandWindowManager::~WaylandWindowManager() = default; ++ ++WaylandWindow* WaylandWindowManager::GetWindow( ++ gfx::AcceleratedWidget widget) const { ++ auto it = window_map_.find(widget); ++ return it == window_map_.end() ? nullptr : it->second; ++} ++ ++WaylandWindow* WaylandWindowManager::GetWindowWithLargestBounds() const { ++ WaylandWindow* window_with_largest_bounds = nullptr; ++ for (auto entry : window_map_) { ++ if (!window_with_largest_bounds) { ++ window_with_largest_bounds = entry.second; ++ continue; ++ } ++ WaylandWindow* window = entry.second; ++ if (window_with_largest_bounds->GetBounds() < window->GetBounds()) ++ window_with_largest_bounds = window; ++ } ++ return window_with_largest_bounds; ++} ++ ++WaylandWindow* WaylandWindowManager::GetCurrentFocusedWindow() const { ++ for (auto entry : window_map_) { ++ WaylandWindow* window = entry.second; ++ if (window->has_pointer_focus()) ++ return window; ++ } ++ return nullptr; ++} ++ ++WaylandWindow* WaylandWindowManager::GetCurrentKeyboardFocusedWindow() const { ++ for (auto entry : window_map_) { ++ WaylandWindow* window = entry.second; ++ if (window->has_keyboard_focus()) ++ return window; ++ } ++ return nullptr; ++} ++ ++std::vector<WaylandWindow*> WaylandWindowManager::GetWindowsOnOutput( ++ uint32_t output_id) { ++ std::vector<WaylandWindow*> result; ++ for (auto entry : window_map_) { ++ if (entry.second->entered_outputs_ids().count(output_id) > 0) ++ result.push_back(entry.second); ++ } ++ return result; ++} ++ ++void WaylandWindowManager::AddWindow(gfx::AcceleratedWidget widget, ++ WaylandWindow* window) { ++ window_map_[widget] = window; ++ ++ // TODO(msisov): use observers instead. ++ connection_->OnWindowAdded(window); ++} ++ ++void WaylandWindowManager::RemoveWindow(gfx::AcceleratedWidget widget) { ++ auto* window = window_map_[widget]; ++ DCHECK(window); ++ ++ window_map_.erase(widget); ++ ++ // TODO(msisov): use observers instead. ++ connection_->OnWindowRemoved(window); ++} ++ ++std::vector<WaylandWindow*> WaylandWindowManager::GetAllWindows() const { ++ std::vector<WaylandWindow*> result; ++ for (auto entry : window_map_) ++ result.push_back(entry.second); ++ return result; ++} ++ ++} // namespace ui +diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager.h b/ui/ozone/platform/wayland/host/wayland_window_manager.h +new file mode 100644 +index 000000000000..d149bda262d9 +--- /dev/null ++++ b/ui/ozone/platform/wayland/host/wayland_window_manager.h +@@ -0,0 +1,60 @@ ++// Copyright 2019 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_WINDOW_MANAGER_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_WINDOW_MANAGER_H_ ++ ++#include <memory> ++ ++#include "base/containers/flat_map.h" ++#include "base/macros.h" ++#include "ui/gfx/native_widget_types.h" ++ ++namespace ui { ++ ++class WaylandConnection; ++class WaylandWindow; ++ ++// Stores and returns WaylandWindows. Clients that are interested in knowing ++// when a new window is added or removed, but set self as an observer. ++class WaylandWindowManager { ++ public: ++ // TODO(msisov): Do not pass WaylandConnection here. Instead, add support for ++ // observers. ++ explicit WaylandWindowManager(WaylandConnection* connection); ++ ~WaylandWindowManager(); ++ ++ // Returns a window found by |widget|. ++ WaylandWindow* GetWindow(gfx::AcceleratedWidget widget) const; ++ ++ // Returns a window with largests bounds. ++ WaylandWindow* GetWindowWithLargestBounds() const; ++ ++ // Returns a current focused window by pointer. ++ WaylandWindow* GetCurrentFocusedWindow() const; ++ ++ // Returns a current focused window by keyboard. ++ WaylandWindow* GetCurrentKeyboardFocusedWindow() const; ++ ++ // TODO(crbug.com/971525): remove this in favor of targeted subscription of ++ // windows to their outputs. ++ std::vector<WaylandWindow*> GetWindowsOnOutput(uint32_t output_id); ++ ++ // Returns all stored windows. ++ std::vector<WaylandWindow*> GetAllWindows() const; ++ ++ void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window); ++ void RemoveWindow(gfx::AcceleratedWidget widget); ++ ++ private: ++ WaylandConnection* const connection_; ++ ++ base::flat_map<gfx::AcceleratedWidget, WaylandWindow*> window_map_; ++ ++ DISALLOW_COPY_AND_ASSIGN(WaylandWindowManager); ++}; ++ ++} // namespace ui ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_WINDOW_MANAGER_H_ +diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc b/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc +new file mode 100644 +index 000000000000..a38267564a0d +--- /dev/null ++++ b/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc +@@ -0,0 +1,222 @@ ++// Copyright 2019 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "testing/gtest/include/gtest/gtest.h" ++#include "ui/ozone/platform/wayland/test/mock_pointer.h" ++#include "ui/ozone/platform/wayland/test/mock_surface.h" ++#include "ui/ozone/platform/wayland/test/test_keyboard.h" ++#include "ui/ozone/platform/wayland/test/wayland_test.h" ++#include "ui/ozone/test/mock_platform_window_delegate.h" ++ ++namespace ui { ++ ++namespace { ++ ++constexpr gfx::Rect kDefaultBounds(0, 0, 100, 100); ++ ++} // namespace ++ ++class WaylandWindowManagerTest : public WaylandTest { ++ public: ++ WaylandWindowManagerTest() {} ++ ++ void SetUp() override { ++ WaylandTest::SetUp(); ++ ++ manager_ = connection_->wayland_window_manager(); ++ DCHECK(manager_); ++ } ++ ++ protected: ++ std::unique_ptr<WaylandWindow> CreateWaylandWindowWithParams( ++ PlatformWindowType type, ++ const gfx::Rect bounds, ++ MockPlatformWindowDelegate* delegate) { ++ PlatformWindowInitProperties properties; ++ properties.bounds = bounds; ++ properties.type = type; ++ ++ std::unique_ptr<WaylandWindow> window = ++ std::make_unique<WaylandWindow>(delegate, connection_.get()); ++ ++ EXPECT_TRUE(window->Initialize(std::move(properties))); ++ return window; ++ } ++ ++ WaylandWindowManager* manager_ = nullptr; ++ ++ private: ++ DISALLOW_COPY_AND_ASSIGN(WaylandWindowManagerTest); ++}; ++ ++TEST_P(WaylandWindowManagerTest, GetWindow) { ++ MockPlatformWindowDelegate delegate; ++ ++ auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ gfx::AcceleratedWidget window1_widget = window1->GetWidget(); ++ ++ auto window2 = CreateWaylandWindowWithParams( ++ PlatformWindowType::kWindow, gfx::Rect(0, 0, 300, 300), &delegate); ++ ++ EXPECT_TRUE(window1.get() == manager_->GetWindow(window1->GetWidget())); ++ EXPECT_TRUE(window2.get() == manager_->GetWindow(window2->GetWidget())); ++ ++ window1.reset(); ++ ++ EXPECT_FALSE(manager_->GetWindow(window1_widget)); ++} ++ ++TEST_P(WaylandWindowManagerTest, GetWindowWithLargestBounds) { ++ MockPlatformWindowDelegate delegate; ++ ++ auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ // There is also default window create by the WaylandTest. Thus, make bounds ++ // of this window large enough. ++ auto window2 = CreateWaylandWindowWithParams( ++ PlatformWindowType::kWindow, gfx::Rect(0, 0, 3000, 3000), &delegate); ++ ++ EXPECT_TRUE(window2.get() == manager_->GetWindowWithLargestBounds()); ++} ++ ++TEST_P(WaylandWindowManagerTest, GetCurrentFocusedWindow) { ++ MockPlatformWindowDelegate delegate; ++ ++ wl_seat_send_capabilities(server_.seat()->resource(), ++ WL_SEAT_CAPABILITY_POINTER); ++ ++ Sync(); ++ ++ auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ ++ Sync(); ++ ++ EXPECT_FALSE(manager_->GetCurrentFocusedWindow()); ++ ++ auto* pointer = server_.seat()->pointer(); ++ ASSERT_TRUE(pointer); ++ ++ wl::MockSurface* surface = ++ server_.GetObject<wl::MockSurface>(window1->GetWidget()); ++ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0); ++ ++ Sync(); ++ ++ EXPECT_FALSE(manager_->GetCurrentKeyboardFocusedWindow()); ++ EXPECT_TRUE(window1.get() == manager_->GetCurrentFocusedWindow()); ++ ++ wl_pointer_send_leave(pointer->resource(), 2, surface->resource()); ++ ++ Sync(); ++ ++ EXPECT_FALSE(manager_->GetCurrentFocusedWindow()); ++} ++ ++TEST_P(WaylandWindowManagerTest, GetCurrentKeyboardFocusedWindow) { ++ MockPlatformWindowDelegate delegate; ++ ++ wl_seat_send_capabilities(server_.seat()->resource(), ++ WL_SEAT_CAPABILITY_KEYBOARD); ++ ++ Sync(); ++ ++ auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ ++ Sync(); ++ ++ EXPECT_FALSE(manager_->GetCurrentKeyboardFocusedWindow()); ++ ++ auto* keyboard = server_.seat()->keyboard(); ++ ASSERT_TRUE(keyboard); ++ ++ wl::MockSurface* surface = ++ server_.GetObject<wl::MockSurface>(window1->GetWidget()); ++ ++ struct wl_array empty; ++ wl_array_init(&empty); ++ wl_keyboard_send_enter(keyboard->resource(), 1, surface->resource(), &empty); ++ ++ Sync(); ++ ++ EXPECT_FALSE(manager_->GetCurrentFocusedWindow()); ++ EXPECT_TRUE(window1.get() == manager_->GetCurrentKeyboardFocusedWindow()); ++ ++ wl_keyboard_send_leave(keyboard->resource(), 2, surface->resource()); ++ ++ Sync(); ++ ++ EXPECT_FALSE(manager_->GetCurrentKeyboardFocusedWindow()); ++} ++ ++TEST_P(WaylandWindowManagerTest, GetWindowsOnOutput) { ++ MockPlatformWindowDelegate delegate; ++ ++ wl::TestOutput* output = server_.CreateAndInitializeOutput(); ++ ++ auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ ++ auto window2 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ ++ Sync(); ++ ++ wl::MockSurface* surface = ++ server_.GetObject<wl::MockSurface>(window1->GetWidget()); ++ ASSERT_TRUE(surface); ++ wl_surface_send_enter(surface->resource(), output->resource()); ++ ++ Sync(); ++ ++ auto entered_outputs_window1 = window1->entered_outputs_ids(); ++ EXPECT_EQ(1u, entered_outputs_window1.size()); ++ ++ uint32_t output_id = *entered_outputs_window1.begin(); ++ ++ auto windows_on_output = manager_->GetWindowsOnOutput(output_id); ++ EXPECT_EQ(1u, windows_on_output.size()); ++ ++ EXPECT_TRUE(window1.get() == *windows_on_output.begin()); ++ ++ surface = server_.GetObject<wl::MockSurface>(window2->GetWidget()); ++ ASSERT_TRUE(surface); ++ wl_surface_send_enter(surface->resource(), output->resource()); ++ ++ Sync(); ++ ++ windows_on_output = manager_->GetWindowsOnOutput(output_id); ++ EXPECT_EQ(2u, windows_on_output.size()); ++} ++ ++TEST_P(WaylandWindowManagerTest, GetAllWindows) { ++ MockPlatformWindowDelegate delegate; ++ ++ // There is a default window created by WaylandTest. ++ auto windows = manager_->GetAllWindows(); ++ EXPECT_EQ(1u, windows.size()); ++ ++ window_.reset(); ++ ++ auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ ++ auto window2 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, ++ kDefaultBounds, &delegate); ++ ++ windows = manager_->GetAllWindows(); ++ EXPECT_EQ(2u, windows.size()); ++} ++ ++INSTANTIATE_TEST_SUITE_P(XdgVersionV5Test, ++ WaylandWindowManagerTest, ++ ::testing::Values(kXdgShellV5)); ++ ++INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test, ++ WaylandWindowManagerTest, ++ ::testing::Values(kXdgShellV6)); ++ ++} // namespace ui +-- +2.22.0 + |