| 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 |