summarylogtreecommitdiffstats
path: root/0010-ozone-wayland-Extract-window-management-methods-to-o.patch
diff options
context:
space:
mode:
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.patch810
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
+