Index: ash/mus/wm/window_manager_application.cc |
diff --git a/ash/mus/wm/window_manager_application.cc b/ash/mus/wm/window_manager_application.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9d73975b4d5a9183e736d76a1c27e12cb14aa0c6 |
--- /dev/null |
+++ b/ash/mus/wm/window_manager_application.cc |
@@ -0,0 +1,289 @@ |
+// Copyright 2015 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 "ash/mus/wm/window_manager_application.h" |
+ |
+#include <stdint.h> |
+#include <utility> |
+ |
+#include "ash/desktop_background/desktop_background_controller.h" |
+#include "ash/host/ash_window_tree_host.h" |
+#include "ash/mus/wm/accelerator_registrar_impl.h" |
+#include "ash/mus/wm/window_manager_impl.h" |
+#include "ash/shell.h" |
+#include "ash/shell/shell_delegate_impl.h" |
+#include "ash/shell_init_params.h" |
+#include "base/bind.h" |
+#include "components/mus/public/cpp/event_matcher.h" |
+#include "components/mus/public/cpp/window.h" |
+#include "components/mus/public/cpp/window_tree_host_factory.h" |
+#include "components/mus/public/interfaces/window_tree.mojom.h" |
+#include "mojo/services/tracing/public/cpp/tracing_impl.h" |
+#include "mojo/shell/public/cpp/application_connection.h" |
+#include "mojo/shell/public/cpp/application_impl.h" |
+#include "ui/aura/env.h" |
+#include "ui/aura/window_tree_host.h" |
+#include "ui/base/ime/input_method_initializer.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/base/ui_base_paths.h" |
+#include "ui/message_center/message_center.h" |
+#include "ui/views/mus/platform_window_mus.h" |
+#include "ui/views/mus/surface_context_factory.h" |
+#include "ui/views/test/test_views_delegate.h" |
+ |
+#include "ash/host/ash_window_tree_host_ozone.cc" // puke |
+ |
+namespace ash { |
+namespace muswm { |
+ |
+namespace { |
+const uint32_t kWindowSwitchCmd = 1; |
+ |
+void AssertTrue(bool success) { |
+ DCHECK(success); |
+} |
+ |
+class ShellViewsDelegate : public views::TestViewsDelegate { |
+ public: |
+ ShellViewsDelegate() {} |
+ ~ShellViewsDelegate() override {} |
+ |
+ // Overridden from views::TestViewsDelegate: |
+ views::NonClientFrameView* CreateDefaultNonClientFrameView( |
+ views::Widget* widget) override { |
+ return ash::Shell::GetInstance()->CreateDefaultNonClientFrameView(widget); |
+ } |
+ void OnBeforeWidgetInit( |
+ views::Widget::InitParams* params, |
+ views::internal::NativeWidgetDelegate* delegate) override { |
+ if (params->opacity == views::Widget::InitParams::INFER_OPACITY) |
+ params->opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
+ |
+ if (params->native_widget) |
+ return; |
+ |
+ if (!params->parent && !params->context && !params->child) |
+ params->context = ash::Shell::GetPrimaryRootWindow(); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegate); |
+}; |
+ |
+class AshWindowTreeHostMus : public AshWindowTreeHostOzone { |
+ public: |
+ AshWindowTreeHostMus(mojo::Shell* shell, |
+ mus::Window* window, |
+ const gfx::Rect& initial_bounds) |
+ : AshWindowTreeHostOzone(initial_bounds) { |
+ SetPlatformWindow( |
+ make_scoped_ptr(new views::PlatformWindowMus(this, shell, window))); |
+ SetBounds(initial_bounds); |
+ Show(); |
+ } |
+ |
+ ~AshWindowTreeHostMus() override {} |
+}; |
+ |
+AshWindowTreeHost* CreateWindowTreeHostMus( |
+ mojo::Shell* shell, |
+ mus::Window* window, |
+ const AshWindowTreeHostInitParams& init_params) { |
+ return new AshWindowTreeHostMus(shell, window, init_params.initial_bounds); |
+} |
+} |
+ |
+class AshInit { |
+ public: |
+ AshInit() { |
+ aura::Env::CreateInstance(false); |
+ ui::InitializeInputMethodForTesting(); |
+ views_delegate_.reset(new ShellViewsDelegate); |
+ } |
+ ~AshInit() {} |
+ |
+ aura::Window* root() { return ash::Shell::GetPrimaryRootWindow(); } |
+ |
+ void Initialize(mojo::Shell* shell, mus::Window* window) { |
+ ash_delegate_ = new ash::shell::ShellDelegateImpl; |
+ |
+ message_center::MessageCenter::Initialize(); |
+ |
+ ash::AshWindowTreeHost::SetFactory( |
+ base::Bind(&CreateWindowTreeHostMus, shell, window)); |
+ |
+ ash::ShellInitParams init_params; |
+ init_params.delegate = ash_delegate_; |
+ init_params.context_factory = new views::SurfaceContextFactory( |
+ shell, window, mus::mojom::SurfaceType::DEFAULT); |
+ init_params.blocking_pool = nullptr; // XXX(sad): |
+ ash::Shell::CreateInstance(init_params); |
+ ash::Shell::GetInstance()->CreateShelf(); |
+ ash::Shell::GetInstance()->UpdateAfterLoginStatusChange( |
+ ash::user::LOGGED_IN_USER); |
+ |
+ ash::Shell::GetPrimaryRootWindow()->GetHost()->Show(); |
+ SetupWallpaper(); |
+ } |
+ |
+ void SetupWallpaper() { |
+ SkBitmap bitmap; |
+ bitmap.allocN32Pixels(16, 16); |
+ bitmap.eraseARGB(255, 0, 255, 0); |
+#if !defined(NDEBUG) |
+ // In debug builds we generate a simple pattern that allows visually |
+ // notice if transparency is broken. |
+ { |
+ SkAutoLockPixels alp(bitmap); |
+ *bitmap.getAddr32(0, 0) = SkColorSetRGB(0, 0, 0); |
+ } |
+#endif |
+ gfx::ImageSkia wallpaper = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); |
+ ash::Shell::GetInstance() |
+ ->desktop_background_controller() |
+ ->SetWallpaperImage(wallpaper, wallpaper::WALLPAPER_LAYOUT_TILE); |
+ } |
+ |
+ private: |
+ scoped_ptr<views::ViewsDelegate> views_delegate_; |
+ ash::shell::ShellDelegateImpl* ash_delegate_ = nullptr; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AshInit); |
+}; |
+ |
+WindowManagerApplication::WindowManagerApplication() |
+ : root_(nullptr), |
+ window_count_(0), |
+ app_(nullptr), |
+ host_client_binding_(this) {} |
+ |
+WindowManagerApplication::~WindowManagerApplication() {} |
+ |
+aura::Window* WindowManagerApplication::aura_root() { |
+ return ash_init_->root(); |
+} |
+ |
+void WindowManagerApplication::AddAccelerators() { |
+ window_tree_host_->AddAccelerator( |
+ kWindowSwitchCmd, |
+ mus::CreateKeyMatcher(mus::mojom::KeyboardCode::TAB, |
+ mus::mojom::kEventFlagControlDown), |
+ base::Bind(&AssertTrue)); |
+} |
+ |
+void WindowManagerApplication::OnAcceleratorRegistrarDestroyed( |
+ AcceleratorRegistrarImpl* registrar) { |
+ accelerator_registrars_.erase(registrar); |
+} |
+ |
+void WindowManagerApplication::Initialize(mojo::ApplicationImpl* app) { |
+ app_ = app; |
+ tracing_.Initialize(app); |
+ window_manager_.reset(new WindowManagerImpl()); |
+ // Don't bind to the WindowManager immediately. Wait for OnEmbed() first. |
+ mus::mojom::WindowManagerDeprecatedPtr window_manager; |
+ requests_.push_back( |
+ make_scoped_ptr(new |
+ mojo::InterfaceRequest<mus::mojom::WindowManagerDeprecated>( |
+ mojo::GetProxy(&window_manager)))); |
+ mus::CreateSingleWindowTreeHost( |
+ app, host_client_binding_.CreateInterfacePtrAndBind(), this, |
+ &window_tree_host_, std::move(window_manager), window_manager_.get()); |
+} |
+ |
+bool WindowManagerApplication::ConfigureIncomingConnection( |
+ mojo::ApplicationConnection* connection) { |
+ connection->AddService<mus::mojom::AcceleratorRegistrar>(this); |
+ connection->AddService<mus::mojom::WindowManagerDeprecated>(this); |
+ return true; |
+} |
+ |
+void WindowManagerApplication::OnAccelerator(uint32_t id, |
+ mus::mojom::EventPtr event) { |
+ switch (id) { |
+ case kWindowSwitchCmd: |
+ window_tree_host_->ActivateNextWindow(); |
+ break; |
+ default: |
+ for (auto* registrar : accelerator_registrars_) { |
+ if (registrar->OwnsAccelerator(id)) { |
+ registrar->ProcessAccelerator(id, std::move(event)); |
+ break; |
+ } |
+ } |
+ } |
+} |
+ |
+void WindowManagerApplication::OnEmbed(mus::Window* root) { |
+ root_ = root; |
+ root_->AddObserver(this); |
+ window_tree_host_->AddActivationParent(root_->id()); |
+ window_tree_host_->SetTitle("Ash-Mash"); |
+ |
+ AddAccelerators(); |
+ |
+ ui::RegisterPathProvider(); |
+ ui::ResourceBundle::InitSharedInstanceWithLocale( |
+ "en-US", nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES); |
+ ash_init_.reset(new AshInit()); |
+ |
+ ash_init_->Initialize(app_->shell(), root_); |
+ window_manager_->Initialize(this); |
+ |
+ for (auto& request : requests_) |
+ window_manager_binding_.AddBinding(window_manager_.get(), |
+ std::move(*request)); |
+ requests_.clear(); |
+} |
+ |
+void WindowManagerApplication::OnConnectionLost( |
+ mus::WindowTreeConnection* connection) { |
+ // TODO(sky): shutdown. |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void WindowManagerApplication::Create( |
+ mojo::ApplicationConnection* connection, |
+ mojo::InterfaceRequest<mus::mojom::AcceleratorRegistrar> request) { |
+ static int accelerator_registrar_count = 0; |
+ if (accelerator_registrar_count == std::numeric_limits<int>::max()) { |
+ // Restart from zero if we have reached the limit. It is technically |
+ // possible to end up with multiple active registrars with the same |
+ // namespace, but it is highly unlikely. In the event that multiple |
+ // registrars have the same namespace, this new registrar will be unable to |
+ // install accelerators. |
+ accelerator_registrar_count = 0; |
+ } |
+ accelerator_registrars_.insert(new AcceleratorRegistrarImpl( |
+ window_tree_host_.get(), ++accelerator_registrar_count, |
+ std::move(request), |
+ base::Bind(&WindowManagerApplication::OnAcceleratorRegistrarDestroyed, |
+ base::Unretained(this)))); |
+} |
+ |
+void WindowManagerApplication::Create( |
+ mojo::ApplicationConnection* connection, |
+ mojo::InterfaceRequest<mus::mojom::WindowManagerDeprecated> request) { |
+ if (root_) { |
+ window_manager_binding_.AddBinding(window_manager_.get(), |
+ std::move(request)); |
+ } else { |
+ requests_.push_back( |
+ make_scoped_ptr(new |
+ mojo::InterfaceRequest<mus::mojom::WindowManagerDeprecated>( |
+ std::move(request)))); |
+ } |
+} |
+ |
+void WindowManagerApplication::OnWindowDestroyed(mus::Window* window) { |
+ DCHECK_EQ(window, root_); |
+ root_->RemoveObserver(this); |
+ // Delete the |window_manager_| here so that WindowManager doesn't have to |
+ // worry about the possibility of |root_| being null. |
+ window_manager_.reset(); |
+ root_ = nullptr; |
+} |
+ |
+} // namespace muswm |
+} // namespace ash |