1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
6
7 #include "ui/ozone/platform/wayland/host/wayland_window.h"
8
9 namespace ui {
10
11 WaylandWindowManager::WaylandWindowManager() = default;
12
13 WaylandWindowManager::~WaylandWindowManager() = default;
14
AddObserver(WaylandWindowObserver * observer)15 void WaylandWindowManager::AddObserver(WaylandWindowObserver* observer) {
16 observers_.AddObserver(observer);
17 }
18
RemoveObserver(WaylandWindowObserver * observer)19 void WaylandWindowManager::RemoveObserver(WaylandWindowObserver* observer) {
20 observers_.RemoveObserver(observer);
21 }
22
NotifyWindowConfigured(WaylandWindow * window)23 void WaylandWindowManager::NotifyWindowConfigured(WaylandWindow* window) {
24 for (WaylandWindowObserver& observer : observers_)
25 observer.OnWindowConfigured(window);
26 }
27
GrabLocatedEvents(WaylandWindow * window)28 void WaylandWindowManager::GrabLocatedEvents(WaylandWindow* window) {
29 DCHECK_NE(located_events_grabber_, window);
30
31 // Wayland doesn't allow to grab the mouse. However, we start forwarding all
32 // mouse events received by WaylandWindow to the aura::WindowEventDispatcher
33 // which has capture.
34 auto* old_grabber = located_events_grabber_;
35 located_events_grabber_ = window;
36 if (old_grabber)
37 old_grabber->OnWindowLostCapture();
38 }
39
UngrabLocatedEvents(WaylandWindow * window)40 void WaylandWindowManager::UngrabLocatedEvents(WaylandWindow* window) {
41 DCHECK_EQ(located_events_grabber_, window);
42 auto* old_grabber = located_events_grabber_;
43 located_events_grabber_ = nullptr;
44 old_grabber->OnWindowLostCapture();
45 }
46
GetWindow(gfx::AcceleratedWidget widget) const47 WaylandWindow* WaylandWindowManager::GetWindow(
48 gfx::AcceleratedWidget widget) const {
49 auto it = window_map_.find(widget);
50 return it == window_map_.end() ? nullptr : it->second;
51 }
52
GetWindowWithLargestBounds() const53 WaylandWindow* WaylandWindowManager::GetWindowWithLargestBounds() const {
54 WaylandWindow* window_with_largest_bounds = nullptr;
55 for (auto entry : window_map_) {
56 if (!window_with_largest_bounds) {
57 window_with_largest_bounds = entry.second;
58 continue;
59 }
60 WaylandWindow* window = entry.second;
61 if (window_with_largest_bounds->GetBounds() < window->GetBounds())
62 window_with_largest_bounds = window;
63 }
64 return window_with_largest_bounds;
65 }
66
GetCurrentFocusedWindow() const67 WaylandWindow* WaylandWindowManager::GetCurrentFocusedWindow() const {
68 for (auto entry : window_map_) {
69 WaylandWindow* window = entry.second;
70 if (window->has_pointer_focus() || window->has_touch_focus())
71 return window;
72 }
73 return nullptr;
74 }
75
GetCurrentKeyboardFocusedWindow() const76 WaylandWindow* WaylandWindowManager::GetCurrentKeyboardFocusedWindow() const {
77 for (auto entry : window_map_) {
78 WaylandWindow* window = entry.second;
79 if (window->has_keyboard_focus())
80 return window;
81 }
82 return nullptr;
83 }
84
FindParentForNewWindow(gfx::AcceleratedWidget parent_widget) const85 WaylandWindow* WaylandWindowManager::FindParentForNewWindow(
86 gfx::AcceleratedWidget parent_widget) const {
87 auto* parent_window = GetWindow(parent_widget);
88
89 // If propagated parent has already had a child, it means that |this| is a
90 // submenu of a 3-dot menu. In aura, the parent of a 3-dot menu and its
91 // submenu is the main native widget, which is the main window. In contrast,
92 // Wayland requires a menu window to be a parent of a submenu window. Thus,
93 // check if the suggested parent has a child. If yes, take its child as a
94 // parent of |this|.
95 // Another case is a notification window or a drop down window, which does not
96 // have a parent in aura. In this case, take the current focused window as a
97 // parent.
98 if (!parent_window)
99 parent_window = GetCurrentFocusedWindow();
100
101 // If there is no current focused window, figure out the current active window
102 // set by the Wayland server. Only one window at a time can be set as active.
103 if (!parent_window) {
104 auto windows = GetAllWindows();
105 for (auto* window : windows) {
106 if (window->IsActive()) {
107 parent_window = window;
108 break;
109 }
110 }
111 }
112
113 return parent_window ? parent_window->GetTopMostChildWindow() : nullptr;
114 }
115
GetWindowsOnOutput(uint32_t output_id)116 std::vector<WaylandWindow*> WaylandWindowManager::GetWindowsOnOutput(
117 uint32_t output_id) {
118 std::vector<WaylandWindow*> result;
119 for (auto entry : window_map_) {
120 if (entry.second->entered_outputs_ids().count(output_id) > 0)
121 result.push_back(entry.second);
122 }
123 return result;
124 }
125
AddWindow(gfx::AcceleratedWidget widget,WaylandWindow * window)126 void WaylandWindowManager::AddWindow(gfx::AcceleratedWidget widget,
127 WaylandWindow* window) {
128 window_map_[widget] = window;
129
130 for (WaylandWindowObserver& observer : observers_)
131 observer.OnWindowAdded(window);
132 }
133
RemoveWindow(gfx::AcceleratedWidget widget)134 void WaylandWindowManager::RemoveWindow(gfx::AcceleratedWidget widget) {
135 auto* window = window_map_[widget];
136 DCHECK(window);
137
138 window_map_.erase(widget);
139
140 for (WaylandWindowObserver& observer : observers_)
141 observer.OnWindowRemoved(window);
142 }
143
AddSubsurface(gfx::AcceleratedWidget widget,WaylandSubsurface * subsurface)144 void WaylandWindowManager::AddSubsurface(gfx::AcceleratedWidget widget,
145 WaylandSubsurface* subsurface) {
146 auto* window = window_map_[widget];
147 DCHECK(window);
148
149 for (WaylandWindowObserver& observer : observers_)
150 observer.OnSubsurfaceAdded(window, subsurface);
151 }
152
RemoveSubsurface(gfx::AcceleratedWidget widget,WaylandSubsurface * subsurface)153 void WaylandWindowManager::RemoveSubsurface(gfx::AcceleratedWidget widget,
154 WaylandSubsurface* subsurface) {
155 auto* window = window_map_[widget];
156 DCHECK(window);
157
158 for (WaylandWindowObserver& observer : observers_)
159 observer.OnSubsurfaceRemoved(window, subsurface);
160 }
161
AllocateAcceleratedWidget()162 gfx::AcceleratedWidget WaylandWindowManager::AllocateAcceleratedWidget() {
163 return ++last_accelerated_widget_;
164 }
165
GetAllWindows() const166 std::vector<WaylandWindow*> WaylandWindowManager::GetAllWindows() const {
167 std::vector<WaylandWindow*> result;
168 for (auto entry : window_map_)
169 result.push_back(entry.second);
170 return result;
171 }
172
173 } // namespace ui
174