OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "ash/mus/wm/window_manager_application.h" |
| 6 |
| 7 #include <stdint.h> |
| 8 #include <utility> |
| 9 |
| 10 #include "ash/desktop_background/desktop_background_controller.h" |
| 11 #include "ash/host/ash_window_tree_host.h" |
| 12 #include "ash/mus/wm/accelerator_registrar_impl.h" |
| 13 #include "ash/mus/wm/window_manager_impl.h" |
| 14 #include "ash/shell.h" |
| 15 #include "ash/shell/shell_delegate_impl.h" |
| 16 #include "ash/shell_init_params.h" |
| 17 #include "base/bind.h" |
| 18 #include "components/mus/public/cpp/event_matcher.h" |
| 19 #include "components/mus/public/cpp/window.h" |
| 20 #include "components/mus/public/cpp/window_tree_host_factory.h" |
| 21 #include "components/mus/public/interfaces/window_tree.mojom.h" |
| 22 #include "mojo/services/tracing/public/cpp/tracing_impl.h" |
| 23 #include "mojo/shell/public/cpp/application_connection.h" |
| 24 #include "mojo/shell/public/cpp/application_impl.h" |
| 25 #include "ui/aura/env.h" |
| 26 #include "ui/aura/window_tree_host.h" |
| 27 #include "ui/base/ime/input_method_initializer.h" |
| 28 #include "ui/base/resource/resource_bundle.h" |
| 29 #include "ui/base/ui_base_paths.h" |
| 30 #include "ui/message_center/message_center.h" |
| 31 #include "ui/views/mus/platform_window_mus.h" |
| 32 #include "ui/views/mus/surface_context_factory.h" |
| 33 #include "ui/views/test/test_views_delegate.h" |
| 34 |
| 35 #include "ash/host/ash_window_tree_host_ozone.cc" // puke |
| 36 |
| 37 namespace ash { |
| 38 namespace muswm { |
| 39 |
| 40 namespace { |
| 41 const uint32_t kWindowSwitchCmd = 1; |
| 42 |
| 43 void AssertTrue(bool success) { |
| 44 DCHECK(success); |
| 45 } |
| 46 |
| 47 class ShellViewsDelegate : public views::TestViewsDelegate { |
| 48 public: |
| 49 ShellViewsDelegate() {} |
| 50 ~ShellViewsDelegate() override {} |
| 51 |
| 52 // Overridden from views::TestViewsDelegate: |
| 53 views::NonClientFrameView* CreateDefaultNonClientFrameView( |
| 54 views::Widget* widget) override { |
| 55 return ash::Shell::GetInstance()->CreateDefaultNonClientFrameView(widget); |
| 56 } |
| 57 void OnBeforeWidgetInit( |
| 58 views::Widget::InitParams* params, |
| 59 views::internal::NativeWidgetDelegate* delegate) override { |
| 60 if (params->opacity == views::Widget::InitParams::INFER_OPACITY) |
| 61 params->opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
| 62 |
| 63 if (params->native_widget) |
| 64 return; |
| 65 |
| 66 if (!params->parent && !params->context && !params->child) |
| 67 params->context = ash::Shell::GetPrimaryRootWindow(); |
| 68 } |
| 69 |
| 70 private: |
| 71 DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegate); |
| 72 }; |
| 73 |
| 74 class AshWindowTreeHostMus : public AshWindowTreeHostOzone { |
| 75 public: |
| 76 AshWindowTreeHostMus(mojo::Shell* shell, |
| 77 mus::Window* window, |
| 78 const gfx::Rect& initial_bounds) |
| 79 : AshWindowTreeHostOzone(initial_bounds) { |
| 80 SetPlatformWindow( |
| 81 make_scoped_ptr(new views::PlatformWindowMus(this, shell, window))); |
| 82 SetBounds(initial_bounds); |
| 83 Show(); |
| 84 } |
| 85 |
| 86 ~AshWindowTreeHostMus() override {} |
| 87 }; |
| 88 |
| 89 AshWindowTreeHost* CreateWindowTreeHostMus( |
| 90 mojo::Shell* shell, |
| 91 mus::Window* window, |
| 92 const AshWindowTreeHostInitParams& init_params) { |
| 93 return new AshWindowTreeHostMus(shell, window, init_params.initial_bounds); |
| 94 } |
| 95 } |
| 96 |
| 97 class AshInit { |
| 98 public: |
| 99 AshInit() { |
| 100 aura::Env::CreateInstance(false); |
| 101 ui::InitializeInputMethodForTesting(); |
| 102 views_delegate_.reset(new ShellViewsDelegate); |
| 103 } |
| 104 ~AshInit() {} |
| 105 |
| 106 aura::Window* root() { return ash::Shell::GetPrimaryRootWindow(); } |
| 107 |
| 108 void Initialize(mojo::Shell* shell, mus::Window* window) { |
| 109 ash_delegate_ = new ash::shell::ShellDelegateImpl; |
| 110 |
| 111 message_center::MessageCenter::Initialize(); |
| 112 |
| 113 ash::AshWindowTreeHost::SetFactory( |
| 114 base::Bind(&CreateWindowTreeHostMus, shell, window)); |
| 115 |
| 116 ash::ShellInitParams init_params; |
| 117 init_params.delegate = ash_delegate_; |
| 118 init_params.context_factory = new views::SurfaceContextFactory( |
| 119 shell, window, mus::mojom::SurfaceType::DEFAULT); |
| 120 init_params.blocking_pool = nullptr; // XXX(sad): |
| 121 ash::Shell::CreateInstance(init_params); |
| 122 ash::Shell::GetInstance()->CreateShelf(); |
| 123 ash::Shell::GetInstance()->UpdateAfterLoginStatusChange( |
| 124 ash::user::LOGGED_IN_USER); |
| 125 |
| 126 ash::Shell::GetPrimaryRootWindow()->GetHost()->Show(); |
| 127 SetupWallpaper(); |
| 128 } |
| 129 |
| 130 void SetupWallpaper() { |
| 131 SkBitmap bitmap; |
| 132 bitmap.allocN32Pixels(16, 16); |
| 133 bitmap.eraseARGB(255, 0, 255, 0); |
| 134 #if !defined(NDEBUG) |
| 135 // In debug builds we generate a simple pattern that allows visually |
| 136 // notice if transparency is broken. |
| 137 { |
| 138 SkAutoLockPixels alp(bitmap); |
| 139 *bitmap.getAddr32(0, 0) = SkColorSetRGB(0, 0, 0); |
| 140 } |
| 141 #endif |
| 142 gfx::ImageSkia wallpaper = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); |
| 143 ash::Shell::GetInstance() |
| 144 ->desktop_background_controller() |
| 145 ->SetWallpaperImage(wallpaper, wallpaper::WALLPAPER_LAYOUT_TILE); |
| 146 } |
| 147 |
| 148 private: |
| 149 scoped_ptr<views::ViewsDelegate> views_delegate_; |
| 150 ash::shell::ShellDelegateImpl* ash_delegate_ = nullptr; |
| 151 |
| 152 DISALLOW_COPY_AND_ASSIGN(AshInit); |
| 153 }; |
| 154 |
| 155 WindowManagerApplication::WindowManagerApplication() |
| 156 : root_(nullptr), |
| 157 window_count_(0), |
| 158 app_(nullptr), |
| 159 host_client_binding_(this) {} |
| 160 |
| 161 WindowManagerApplication::~WindowManagerApplication() {} |
| 162 |
| 163 aura::Window* WindowManagerApplication::aura_root() { |
| 164 return ash_init_->root(); |
| 165 } |
| 166 |
| 167 void WindowManagerApplication::AddAccelerators() { |
| 168 window_tree_host_->AddAccelerator( |
| 169 kWindowSwitchCmd, |
| 170 mus::CreateKeyMatcher(mus::mojom::KeyboardCode::TAB, |
| 171 mus::mojom::kEventFlagControlDown), |
| 172 base::Bind(&AssertTrue)); |
| 173 } |
| 174 |
| 175 void WindowManagerApplication::OnAcceleratorRegistrarDestroyed( |
| 176 AcceleratorRegistrarImpl* registrar) { |
| 177 accelerator_registrars_.erase(registrar); |
| 178 } |
| 179 |
| 180 void WindowManagerApplication::Initialize(mojo::ApplicationImpl* app) { |
| 181 app_ = app; |
| 182 tracing_.Initialize(app); |
| 183 window_manager_.reset(new WindowManagerImpl()); |
| 184 // Don't bind to the WindowManager immediately. Wait for OnEmbed() first. |
| 185 mus::mojom::WindowManagerDeprecatedPtr window_manager; |
| 186 requests_.push_back( |
| 187 make_scoped_ptr(new |
| 188 mojo::InterfaceRequest<mus::mojom::WindowManagerDeprecated
>( |
| 189 mojo::GetProxy(&window_manager)))); |
| 190 mus::CreateSingleWindowTreeHost( |
| 191 app, host_client_binding_.CreateInterfacePtrAndBind(), this, |
| 192 &window_tree_host_, std::move(window_manager), window_manager_.get()); |
| 193 } |
| 194 |
| 195 bool WindowManagerApplication::ConfigureIncomingConnection( |
| 196 mojo::ApplicationConnection* connection) { |
| 197 connection->AddService<mus::mojom::AcceleratorRegistrar>(this); |
| 198 connection->AddService<mus::mojom::WindowManagerDeprecated>(this); |
| 199 return true; |
| 200 } |
| 201 |
| 202 void WindowManagerApplication::OnAccelerator(uint32_t id, |
| 203 mus::mojom::EventPtr event) { |
| 204 switch (id) { |
| 205 case kWindowSwitchCmd: |
| 206 window_tree_host_->ActivateNextWindow(); |
| 207 break; |
| 208 default: |
| 209 for (auto* registrar : accelerator_registrars_) { |
| 210 if (registrar->OwnsAccelerator(id)) { |
| 211 registrar->ProcessAccelerator(id, std::move(event)); |
| 212 break; |
| 213 } |
| 214 } |
| 215 } |
| 216 } |
| 217 |
| 218 void WindowManagerApplication::OnEmbed(mus::Window* root) { |
| 219 root_ = root; |
| 220 root_->AddObserver(this); |
| 221 window_tree_host_->AddActivationParent(root_->id()); |
| 222 window_tree_host_->SetTitle("Ash-Mash"); |
| 223 |
| 224 AddAccelerators(); |
| 225 |
| 226 ui::RegisterPathProvider(); |
| 227 ui::ResourceBundle::InitSharedInstanceWithLocale( |
| 228 "en-US", nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES); |
| 229 ash_init_.reset(new AshInit()); |
| 230 |
| 231 ash_init_->Initialize(app_->shell(), root_); |
| 232 window_manager_->Initialize(this); |
| 233 |
| 234 for (auto& request : requests_) |
| 235 window_manager_binding_.AddBinding(window_manager_.get(), |
| 236 std::move(*request)); |
| 237 requests_.clear(); |
| 238 } |
| 239 |
| 240 void WindowManagerApplication::OnConnectionLost( |
| 241 mus::WindowTreeConnection* connection) { |
| 242 // TODO(sky): shutdown. |
| 243 NOTIMPLEMENTED(); |
| 244 } |
| 245 |
| 246 void WindowManagerApplication::Create( |
| 247 mojo::ApplicationConnection* connection, |
| 248 mojo::InterfaceRequest<mus::mojom::AcceleratorRegistrar> request) { |
| 249 static int accelerator_registrar_count = 0; |
| 250 if (accelerator_registrar_count == std::numeric_limits<int>::max()) { |
| 251 // Restart from zero if we have reached the limit. It is technically |
| 252 // possible to end up with multiple active registrars with the same |
| 253 // namespace, but it is highly unlikely. In the event that multiple |
| 254 // registrars have the same namespace, this new registrar will be unable to |
| 255 // install accelerators. |
| 256 accelerator_registrar_count = 0; |
| 257 } |
| 258 accelerator_registrars_.insert(new AcceleratorRegistrarImpl( |
| 259 window_tree_host_.get(), ++accelerator_registrar_count, |
| 260 std::move(request), |
| 261 base::Bind(&WindowManagerApplication::OnAcceleratorRegistrarDestroyed, |
| 262 base::Unretained(this)))); |
| 263 } |
| 264 |
| 265 void WindowManagerApplication::Create( |
| 266 mojo::ApplicationConnection* connection, |
| 267 mojo::InterfaceRequest<mus::mojom::WindowManagerDeprecated> request) { |
| 268 if (root_) { |
| 269 window_manager_binding_.AddBinding(window_manager_.get(), |
| 270 std::move(request)); |
| 271 } else { |
| 272 requests_.push_back( |
| 273 make_scoped_ptr(new |
| 274 mojo::InterfaceRequest<mus::mojom::WindowManagerDeprecat
ed>( |
| 275 std::move(request)))); |
| 276 } |
| 277 } |
| 278 |
| 279 void WindowManagerApplication::OnWindowDestroyed(mus::Window* window) { |
| 280 DCHECK_EQ(window, root_); |
| 281 root_->RemoveObserver(this); |
| 282 // Delete the |window_manager_| here so that WindowManager doesn't have to |
| 283 // worry about the possibility of |root_| being null. |
| 284 window_manager_.reset(); |
| 285 root_ = nullptr; |
| 286 } |
| 287 |
| 288 } // namespace muswm |
| 289 } // namespace ash |
OLD | NEW |