OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "mash/wm/root_window_controller.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <map> | |
10 #include <sstream> | |
11 | |
12 #include "ash/common/shell_window_ids.h" | |
13 #include "ash/common/wm/always_on_top_controller.h" | |
14 #include "ash/common/wm/dock/docked_window_layout_manager.h" | |
15 #include "ash/common/wm/panels/panel_layout_manager.h" | |
16 #include "ash/common/wm/workspace/workspace_layout_manager.h" | |
17 #include "ash/common/wm/workspace/workspace_layout_manager_delegate.h" | |
18 #include "base/bind.h" | |
19 #include "base/command_line.h" | |
20 #include "base/memory/ptr_util.h" | |
21 #include "components/mus/common/event_matcher_util.h" | |
22 #include "components/mus/common/switches.h" | |
23 #include "components/mus/common/util.h" | |
24 #include "components/mus/public/cpp/property_type_converters.h" | |
25 #include "components/mus/public/cpp/window.h" | |
26 #include "components/mus/public/cpp/window_tree_client.h" | |
27 #include "components/mus/public/cpp/window_tree_host_factory.h" | |
28 #include "components/mus/public/interfaces/window_manager.mojom.h" | |
29 #include "mash/session/public/interfaces/session.mojom.h" | |
30 #include "mash/wm/background_layout.h" | |
31 #include "mash/wm/bridge/wm_globals_mus.h" | |
32 #include "mash/wm/bridge/wm_root_window_controller_mus.h" | |
33 #include "mash/wm/bridge/wm_shelf_mus.h" | |
34 #include "mash/wm/bridge/wm_window_mus.h" | |
35 #include "mash/wm/container_ids.h" | |
36 #include "mash/wm/fill_layout.h" | |
37 #include "mash/wm/screenlock_layout.h" | |
38 #include "mash/wm/shadow_controller.h" | |
39 #include "mash/wm/shelf_layout_manager.h" | |
40 #include "mash/wm/status_layout_manager.h" | |
41 #include "mash/wm/window_manager.h" | |
42 #include "mash/wm/window_manager_application.h" | |
43 #include "mojo/public/cpp/bindings/type_converter.h" | |
44 #include "services/shell/public/cpp/connector.h" | |
45 #include "ui/display/mojo/display_type_converters.h" | |
46 | |
47 using ash::mojom::Container; | |
48 | |
49 namespace mash { | |
50 namespace wm { | |
51 namespace { | |
52 | |
53 const uint32_t kWindowSwitchAccelerator = 1; | |
54 | |
55 void AssertTrue(bool success) { | |
56 DCHECK(success); | |
57 } | |
58 | |
59 int ContainerToLocalId(Container container) { | |
60 return static_cast<int>(container); | |
61 } | |
62 | |
63 class WorkspaceLayoutManagerDelegateImpl | |
64 : public ash::wm::WorkspaceLayoutManagerDelegate { | |
65 public: | |
66 explicit WorkspaceLayoutManagerDelegateImpl( | |
67 WmRootWindowControllerMus* root_window_controller) | |
68 : root_window_controller_(root_window_controller) {} | |
69 ~WorkspaceLayoutManagerDelegateImpl() override = default; | |
70 | |
71 // WorkspaceLayoutManagerDelegate: | |
72 void UpdateShelfVisibility() override { NOTIMPLEMENTED(); } | |
73 void OnFullscreenStateChanged(bool is_fullscreen) override { | |
74 // TODO(sky): this should only do something if there is a shelf, see | |
75 // implementation in ash/shell.cc. | |
76 NOTIMPLEMENTED(); | |
77 root_window_controller_->NotifyFullscreenStateChange(is_fullscreen); | |
78 } | |
79 | |
80 private: | |
81 WmRootWindowControllerMus* root_window_controller_; | |
82 | |
83 DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerDelegateImpl); | |
84 }; | |
85 | |
86 } // namespace | |
87 | |
88 // static | |
89 RootWindowController* RootWindowController::CreateFromDisplay( | |
90 WindowManagerApplication* app, | |
91 mus::mojom::DisplayPtr display, | |
92 mus::mojom::WindowTreeClientRequest client_request) { | |
93 RootWindowController* controller = new RootWindowController(app); | |
94 controller->display_ = display.To<display::Display>(); | |
95 new mus::WindowTreeClient(controller, controller->window_manager_.get(), | |
96 std::move(client_request)); | |
97 return controller; | |
98 } | |
99 | |
100 void RootWindowController::Destroy() { | |
101 // See class description for details on lifetime. | |
102 if (root_) { | |
103 delete root_->window_tree(); | |
104 } else { | |
105 // This case only happens if we're destroyed before OnEmbed(). | |
106 delete this; | |
107 } | |
108 } | |
109 | |
110 shell::Connector* RootWindowController::GetConnector() { | |
111 return app_->connector(); | |
112 } | |
113 | |
114 mus::Window* RootWindowController::GetWindowForContainer(Container container) { | |
115 return root_->GetChildByLocalId(ContainerToLocalId(container)); | |
116 } | |
117 | |
118 bool RootWindowController::WindowIsContainer(const mus::Window* window) const { | |
119 return window && window->local_id() > ContainerToLocalId(Container::ROOT) && | |
120 window->local_id() < ContainerToLocalId(Container::COUNT); | |
121 } | |
122 | |
123 mus::WindowManagerClient* RootWindowController::window_manager_client() { | |
124 return window_manager_->window_manager_client(); | |
125 } | |
126 | |
127 void RootWindowController::OnAccelerator(uint32_t id, const ui::Event& event) { | |
128 switch (id) { | |
129 case kWindowSwitchAccelerator: | |
130 window_manager_client()->ActivateNextWindow(); | |
131 break; | |
132 default: | |
133 app_->OnAccelerator(id, event); | |
134 break; | |
135 } | |
136 } | |
137 | |
138 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() { | |
139 return static_cast<ShelfLayoutManager*>( | |
140 layout_managers_[GetWindowForContainer(Container::USER_PRIVATE_SHELF)] | |
141 .get()); | |
142 } | |
143 | |
144 StatusLayoutManager* RootWindowController::GetStatusLayoutManager() { | |
145 return static_cast<StatusLayoutManager*>( | |
146 layout_managers_[GetWindowForContainer(Container::STATUS)].get()); | |
147 } | |
148 | |
149 RootWindowController::RootWindowController(WindowManagerApplication* app) | |
150 : app_(app), root_(nullptr), window_count_(0) { | |
151 window_manager_.reset(new WindowManager); | |
152 } | |
153 | |
154 RootWindowController::~RootWindowController() {} | |
155 | |
156 void RootWindowController::AddAccelerators() { | |
157 window_manager_client()->AddAccelerator( | |
158 kWindowSwitchAccelerator, | |
159 mus::CreateKeyMatcher(mus::mojom::KeyboardCode::TAB, | |
160 mus::mojom::kEventFlagControlDown), | |
161 base::Bind(&AssertTrue)); | |
162 } | |
163 | |
164 void RootWindowController::OnEmbed(mus::Window* root) { | |
165 root_ = root; | |
166 root_->set_local_id(ContainerToLocalId(Container::ROOT)); | |
167 root_->AddObserver(this); | |
168 layout_managers_[root_].reset(new FillLayout(root_)); | |
169 | |
170 app_->OnRootWindowControllerGotRoot(this); | |
171 | |
172 wm_root_window_controller_.reset( | |
173 new WmRootWindowControllerMus(app_->globals(), this)); | |
174 | |
175 CreateContainers(); | |
176 | |
177 for (size_t i = 0; i < kNumActivationContainers; ++i) { | |
178 window_manager_client()->AddActivationParent( | |
179 GetWindowForContainer(kActivationContainers[i])); | |
180 } | |
181 | |
182 ash::wm::WmWindow* always_on_top_container = | |
183 wm::WmWindowMus::Get(root)->GetChildByShellWindowId( | |
184 ash::kShellWindowId_AlwaysOnTopContainer); | |
185 always_on_top_controller_.reset( | |
186 new ash::AlwaysOnTopController(always_on_top_container)); | |
187 | |
188 AddAccelerators(); | |
189 | |
190 window_manager_->Initialize(this, app_->session()); | |
191 | |
192 shadow_controller_.reset(new ShadowController(root->window_tree())); | |
193 | |
194 app_->OnRootWindowControllerDoneInit(this); | |
195 } | |
196 | |
197 void RootWindowController::OnWindowTreeClientDestroyed( | |
198 mus::WindowTreeClient* client) { | |
199 shadow_controller_.reset(); | |
200 delete this; | |
201 } | |
202 | |
203 void RootWindowController::OnEventObserved(const ui::Event& event, | |
204 mus::Window* target) { | |
205 // Does not use EventObservers. | |
206 } | |
207 | |
208 void RootWindowController::OnWindowDestroyed(mus::Window* window) { | |
209 DCHECK_EQ(window, root_); | |
210 app_->OnRootWindowDestroyed(this); | |
211 root_->RemoveObserver(this); | |
212 // Delete the |window_manager_| here so that WindowManager doesn't have to | |
213 // worry about the possibility of |root_| being null. | |
214 window_manager_.reset(); | |
215 root_ = nullptr; | |
216 } | |
217 | |
218 void RootWindowController::OnShelfWindowAvailable() { | |
219 ash::DockedWindowLayoutManager::Get(WmWindowMus::Get(root_)) | |
220 ->SetShelf(wm_shelf_.get()); | |
221 | |
222 ash::PanelLayoutManager::Get(WmWindowMus::Get(root_)) | |
223 ->SetShelf(wm_shelf_.get()); | |
224 | |
225 // TODO: http://crbug.com/614182 Ash's ShelfLayoutManager implements | |
226 // DockedWindowLayoutManagerObserver so that it can inset by the docked | |
227 // windows. | |
228 // docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager()); | |
229 } | |
230 | |
231 void RootWindowController::CreateContainer(Container container, | |
232 Container parent_container) { | |
233 // Set the window's name to the container name (e.g. "Container::LOGIN"), | |
234 // which makes the window hierarchy easier to read. | |
235 std::map<std::string, std::vector<uint8_t>> properties; | |
236 std::ostringstream container_name; | |
237 container_name << container; | |
238 properties[mus::mojom::WindowManager::kName_Property] = | |
239 mojo::ConvertTo<std::vector<uint8_t>>(container_name.str()); | |
240 | |
241 mus::Window* window = root_->window_tree()->NewWindow(&properties); | |
242 window->set_local_id(ContainerToLocalId(container)); | |
243 layout_managers_[window].reset(new FillLayout(window)); | |
244 WmWindowMus::Get(window)->SetShellWindowId( | |
245 MashContainerToAshContainer(container)); | |
246 | |
247 // User private windows are hidden by default until the window manager learns | |
248 // the lock state, so their contents are never accidentally revealed. Tests, | |
249 // however, usually assume the screen is unlocked. | |
250 const bool is_test = base::CommandLine::ForCurrentProcess()->HasSwitch( | |
251 mus::switches::kUseTestConfig); | |
252 window->SetVisible(container != Container::USER_PRIVATE || is_test); | |
253 | |
254 mus::Window* parent = | |
255 root_->GetChildByLocalId(ContainerToLocalId(parent_container)); | |
256 parent->AddChild(window); | |
257 } | |
258 | |
259 void RootWindowController::CreateContainers() { | |
260 CreateContainer(Container::ALL_USER_BACKGROUND, Container::ROOT); | |
261 CreateContainer(Container::USER, Container::ROOT); | |
262 CreateContainer(Container::USER_BACKGROUND, Container::USER); | |
263 CreateContainer(Container::USER_PRIVATE, Container::USER); | |
264 CreateContainer(Container::USER_PRIVATE_WINDOWS, Container::USER_PRIVATE); | |
265 CreateContainer(Container::USER_PRIVATE_ALWAYS_ON_TOP_WINDOWS, | |
266 Container::USER_PRIVATE); | |
267 CreateContainer(Container::USER_PRIVATE_DOCKED_WINDOWS, | |
268 Container::USER_PRIVATE); | |
269 CreateContainer(Container::USER_PRIVATE_PRESENTATION_WINDOWS, | |
270 Container::USER_PRIVATE); | |
271 CreateContainer(Container::USER_PRIVATE_SHELF, Container::USER_PRIVATE); | |
272 CreateContainer(Container::USER_PRIVATE_PANELS, Container::USER_PRIVATE); | |
273 CreateContainer(Container::USER_PRIVATE_APP_LIST, Container::USER_PRIVATE); | |
274 CreateContainer(Container::USER_PRIVATE_SYSTEM_MODAL, | |
275 Container::USER_PRIVATE); | |
276 CreateContainer(Container::LOGIN, Container::ROOT); | |
277 CreateContainer(Container::LOGIN_WINDOWS, Container::LOGIN); | |
278 CreateContainer(Container::LOGIN_APP, Container::LOGIN); | |
279 CreateContainer(Container::LOGIN_SHELF, Container::LOGIN); | |
280 CreateContainer(Container::STATUS, Container::ROOT); | |
281 CreateContainer(Container::BUBBLES, Container::ROOT); | |
282 CreateContainer(Container::SYSTEM_MODAL_WINDOWS, Container::ROOT); | |
283 CreateContainer(Container::KEYBOARD, Container::ROOT); | |
284 CreateContainer(Container::MENUS, Container::ROOT); | |
285 CreateContainer(Container::DRAG_AND_TOOLTIPS, Container::ROOT); | |
286 | |
287 // Override the default layout managers for certain containers. | |
288 mus::Window* user_background = | |
289 GetWindowForContainer(Container::USER_BACKGROUND); | |
290 layout_managers_[user_background].reset( | |
291 new BackgroundLayout(user_background)); | |
292 | |
293 mus::Window* login_app = GetWindowForContainer(Container::LOGIN_APP); | |
294 layout_managers_[login_app].reset(new ScreenlockLayout(login_app)); | |
295 | |
296 mus::Window* user_shelf = | |
297 GetWindowForContainer(Container::USER_PRIVATE_SHELF); | |
298 ShelfLayoutManager* shelf_layout_manager = | |
299 new ShelfLayoutManager(user_shelf, this); | |
300 layout_managers_[user_shelf].reset(shelf_layout_manager); | |
301 | |
302 wm_shelf_.reset(new WmShelfMus(shelf_layout_manager)); | |
303 | |
304 mus::Window* status = GetWindowForContainer(Container::STATUS); | |
305 layout_managers_[status].reset(new StatusLayoutManager(status)); | |
306 | |
307 mus::Window* user_private_windows = | |
308 GetWindowForContainer(Container::USER_PRIVATE_WINDOWS); | |
309 // WorkspaceLayoutManager is not a mash::wm::LayoutManager (it's an | |
310 // ash::wm::LayoutManager), so it can't be in |layout_managers_|. | |
311 layout_managers_.erase(user_private_windows); | |
312 std::unique_ptr<WorkspaceLayoutManagerDelegateImpl> | |
313 workspace_layout_manager_delegate(new WorkspaceLayoutManagerDelegateImpl( | |
314 wm_root_window_controller_.get())); | |
315 WmWindowMus* user_private_windows_wm = WmWindowMus::Get(user_private_windows); | |
316 user_private_windows_wm->SetSnapsChildrenToPhysicalPixelBoundary(); | |
317 user_private_windows_wm->SetChildrenUseExtendedHitRegion(); | |
318 user_private_windows_wm->SetLayoutManager( | |
319 base::WrapUnique(new ash::WorkspaceLayoutManager( | |
320 user_private_windows_wm, | |
321 std::move(workspace_layout_manager_delegate)))); | |
322 | |
323 mus::Window* user_private_docked_windows = | |
324 GetWindowForContainer(Container::USER_PRIVATE_DOCKED_WINDOWS); | |
325 WmWindowMus* user_private_docked_windows_wm = | |
326 WmWindowMus::Get(user_private_docked_windows); | |
327 user_private_docked_windows_wm->SetSnapsChildrenToPhysicalPixelBoundary(); | |
328 layout_managers_.erase(user_private_docked_windows); | |
329 user_private_docked_windows_wm->SetChildrenUseExtendedHitRegion(); | |
330 user_private_docked_windows_wm->SetLayoutManager(base::WrapUnique( | |
331 new ash::DockedWindowLayoutManager(user_private_docked_windows_wm))); | |
332 | |
333 mus::Window* user_private_panels = | |
334 GetWindowForContainer(Container::USER_PRIVATE_PANELS); | |
335 WmWindowMus* user_private_panels_wm = WmWindowMus::Get(user_private_panels); | |
336 user_private_panels_wm->SetSnapsChildrenToPhysicalPixelBoundary(); | |
337 layout_managers_.erase(user_private_panels); | |
338 user_private_panels_wm->SetChildrenUseExtendedHitRegion(); | |
339 user_private_panels_wm->SetLayoutManager( | |
340 base::WrapUnique(new ash::PanelLayoutManager(user_private_panels_wm))); | |
341 | |
342 mus::Window* user_private_always_on_top = | |
343 GetWindowForContainer(Container::USER_PRIVATE_ALWAYS_ON_TOP_WINDOWS); | |
344 WmWindowMus* user_private_always_on_top_wm = | |
345 WmWindowMus::Get(user_private_always_on_top); | |
346 user_private_always_on_top_wm->SetChildrenUseExtendedHitRegion(); | |
347 user_private_always_on_top_wm->SetSnapsChildrenToPhysicalPixelBoundary(); | |
348 } | |
349 | |
350 } // namespace wm | |
351 } // namespace mash | |
OLD | NEW |