1 // Copyright 2014 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.
5 #include "extensions/shell/browser/shell_desktop_controller.h"
10 #include "base/command_line.h"
11 #include "extensions/browser/app_window/app_window.h"
12 #include "extensions/browser/app_window/native_app_window.h"
13 #include "extensions/shell/browser/shell_app_delegate.h"
14 #include "extensions/shell/browser/shell_app_window_client.h"
15 #include "extensions/shell/common/switches.h"
16 #include "ui/aura/client/cursor_client.h"
17 #include "ui/aura/client/default_capture_client.h"
18 #include "ui/aura/layout_manager.h"
19 #include "ui/aura/test/test_screen.h"
20 #include "ui/aura/window.h"
21 #include "ui/aura/window_event_dispatcher.h"
22 #include "ui/aura/window_tree_host.h"
23 #include "ui/base/cursor/cursor.h"
24 #include "ui/base/cursor/image_cursors.h"
25 #include "ui/base/ime/input_method_initializer.h"
26 #include "ui/gfx/native_widget_types.h"
27 #include "ui/gfx/screen.h"
28 #include "ui/wm/core/base_focus_rules.h"
29 #include "ui/wm/core/compound_event_filter.h"
30 #include "ui/wm/core/cursor_manager.h"
31 #include "ui/wm/core/focus_controller.h"
32 #include "ui/wm/core/input_method_event_filter.h"
33 #include "ui/wm/core/native_cursor_manager.h"
34 #include "ui/wm/core/native_cursor_manager_delegate.h"
35 #include "ui/wm/core/user_activity_detector.h"
37 #if defined(OS_CHROMEOS)
38 #include "chromeos/dbus/dbus_thread_manager.h"
39 #include "ui/chromeos/user_activity_power_manager_notifier.h"
40 #include "ui/display/types/display_mode.h"
41 #include "ui/display/types/display_snapshot.h"
44 namespace extensions {
47 // A simple layout manager that makes each new window fill its parent.
48 class FillLayout : public aura::LayoutManager {
51 virtual ~FillLayout() {}
54 // aura::LayoutManager:
55 virtual void OnWindowResized() OVERRIDE {}
57 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
61 // Create a rect at 0,0 with the size of the parent.
62 gfx::Size parent_size = child->parent()->bounds().size();
63 child->SetBounds(gfx::Rect(parent_size));
66 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
68 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
70 virtual void OnChildWindowVisibilityChanged(aura::Window* child,
71 bool visible) OVERRIDE {}
73 virtual void SetChildBounds(aura::Window* child,
74 const gfx::Rect& requested_bounds) OVERRIDE {
75 SetChildBoundsDirect(child, requested_bounds);
78 DISALLOW_COPY_AND_ASSIGN(FillLayout);
81 // A class that bridges the gap between CursorManager and Aura. It borrows
82 // heavily from AshNativeCursorManager.
83 class ShellNativeCursorManager : public wm::NativeCursorManager {
85 explicit ShellNativeCursorManager(aura::WindowTreeHost* host)
86 : host_(host), image_cursors_(new ui::ImageCursors) {}
87 virtual ~ShellNativeCursorManager() {}
89 // wm::NativeCursorManager overrides.
90 virtual void SetDisplay(const gfx::Display& display,
91 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
92 if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
93 SetCursor(delegate->GetCursor(), delegate);
96 virtual void SetCursor(gfx::NativeCursor cursor,
97 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
98 image_cursors_->SetPlatformCursor(&cursor);
99 cursor.set_device_scale_factor(image_cursors_->GetScale());
100 delegate->CommitCursor(cursor);
102 if (delegate->IsCursorVisible())
106 virtual void SetVisibility(
108 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
109 delegate->CommitVisibility(visible);
112 SetCursor(delegate->GetCursor(), delegate);
114 gfx::NativeCursor invisible_cursor(ui::kCursorNone);
115 image_cursors_->SetPlatformCursor(&invisible_cursor);
116 ApplyCursor(invisible_cursor);
120 virtual void SetCursorSet(
121 ui::CursorSetType cursor_set,
122 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
123 image_cursors_->SetCursorSet(cursor_set);
124 delegate->CommitCursorSet(cursor_set);
125 if (delegate->IsCursorVisible())
126 SetCursor(delegate->GetCursor(), delegate);
129 virtual void SetMouseEventsEnabled(
131 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
132 delegate->CommitMouseEventsEnabled(enabled);
133 SetVisibility(delegate->IsCursorVisible(), delegate);
137 // Sets |cursor| as the active cursor within Aura.
138 void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); }
140 aura::WindowTreeHost* host_; // Not owned.
142 scoped_ptr<ui::ImageCursors> image_cursors_;
144 DISALLOW_COPY_AND_ASSIGN(ShellNativeCursorManager);
147 class AppsFocusRules : public wm::BaseFocusRules {
150 virtual ~AppsFocusRules() {}
152 virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE {
157 DISALLOW_COPY_AND_ASSIGN(AppsFocusRules);
162 ShellDesktopController::ShellDesktopController()
163 : app_window_client_(new ShellAppWindowClient), app_window_(NULL) {
164 extensions::AppWindowClient::Set(app_window_client_.get());
166 #if defined(OS_CHROMEOS)
167 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
169 display_configurator_.reset(new ui::DisplayConfigurator);
170 display_configurator_->Init(false);
171 display_configurator_->ForceInitialConfigure(0);
172 display_configurator_->AddObserver(this);
177 ShellDesktopController::~ShellDesktopController() {
180 #if defined(OS_CHROMEOS)
181 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
182 RemoveObserver(this);
184 extensions::AppWindowClient::Set(NULL);
187 aura::WindowTreeHost* ShellDesktopController::GetHost() {
191 AppWindow* ShellDesktopController::CreateAppWindow(
192 content::BrowserContext* context,
193 const Extension* extension) {
194 app_window_ = new AppWindow(context, new ShellAppDelegate, extension);
198 void ShellDesktopController::AddAppWindow(aura::Window* window) {
199 aura::Window* root_window = GetHost()->window();
200 root_window->AddChild(window);
203 void ShellDesktopController::CloseAppWindows() {
205 app_window_->GetBaseWindow()->Close(); // Close() deletes |app_window_|.
210 aura::Window* ShellDesktopController::GetDefaultParent(
211 aura::Window* context,
212 aura::Window* window,
213 const gfx::Rect& bounds) {
214 return host_->window();
217 #if defined(OS_CHROMEOS)
218 void ShellDesktopController::PowerButtonEventReceived(
220 const base::TimeTicks& timestamp) {
222 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
227 void ShellDesktopController::OnDisplayModeChanged(
228 const std::vector<ui::DisplayConfigurator::DisplayState>& displays) {
229 gfx::Size size = GetPrimaryDisplaySize();
231 host_->UpdateRootWindowSize(size);
235 void ShellDesktopController::OnHostCloseRequested(
236 const aura::WindowTreeHost* host) {
237 DCHECK_EQ(host_.get(), host);
239 base::MessageLoop::current()->PostTask(FROM_HERE,
240 base::MessageLoop::QuitClosure());
243 void ShellDesktopController::InitWindowManager() {
244 wm::FocusController* focus_controller =
245 new wm::FocusController(new AppsFocusRules());
246 aura::client::SetFocusClient(host_->window(), focus_controller);
247 host_->window()->AddPreTargetHandler(focus_controller);
248 aura::client::SetActivationClient(host_->window(), focus_controller);
249 focus_client_.reset(focus_controller);
251 input_method_filter_.reset(
252 new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
253 input_method_filter_->SetInputMethodPropertyInRootWindow(host_->window());
254 root_window_event_filter_->AddHandler(input_method_filter_.get());
256 capture_client_.reset(
257 new aura::client::DefaultCaptureClient(host_->window()));
259 // Ensure new windows fill the display.
260 host_->window()->SetLayoutManager(new FillLayout);
262 cursor_manager_.reset(
263 new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>(
264 new ShellNativeCursorManager(host_.get()))));
265 cursor_manager_->SetDisplay(
266 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay());
267 cursor_manager_->SetCursor(ui::kCursorPointer);
268 aura::client::SetCursorClient(host_->window(), cursor_manager_.get());
270 user_activity_detector_.reset(new wm::UserActivityDetector);
271 host_->event_processor()->GetRootTarget()->AddPreTargetHandler(
272 user_activity_detector_.get());
273 #if defined(OS_CHROMEOS)
274 user_activity_notifier_.reset(
275 new ui::UserActivityPowerManagerNotifier(user_activity_detector_.get()));
279 void ShellDesktopController::CreateRootWindow() {
280 // Set up basic pieces of ui::wm.
282 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
283 if (command_line->HasSwitch(switches::kAppShellHostWindowBounds)) {
284 const std::string size_str =
285 command_line->GetSwitchValueASCII(switches::kAppShellHostWindowBounds);
287 CHECK_EQ(2, sscanf(size_str.c_str(), "%dx%d", &width, &height));
288 size = gfx::Size(width, height);
290 size = GetPrimaryDisplaySize();
293 size = gfx::Size(1280, 720);
295 test_screen_.reset(aura::TestScreen::Create(size));
296 // TODO(jamescook): Replace this with a real Screen implementation.
297 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
298 // TODO(mukai): Set up input method.
300 host_.reset(test_screen_->CreateHostForPrimaryDisplay());
302 aura::client::SetWindowTreeClient(host_->window(), this);
303 root_window_event_filter_.reset(new wm::CompoundEventFilter);
304 host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
307 host_->AddObserver(this);
309 // Ensure the X window gets mapped.
313 void ShellDesktopController::DestroyRootWindow() {
314 host_->RemoveObserver(this);
315 if (input_method_filter_)
316 root_window_event_filter_->RemoveHandler(input_method_filter_.get());
317 if (user_activity_detector_) {
318 host_->event_processor()->GetRootTarget()->RemovePreTargetHandler(
319 user_activity_detector_.get());
321 wm::FocusController* focus_controller =
322 static_cast<wm::FocusController*>(focus_client_.get());
323 if (focus_controller) {
324 host_->window()->RemovePreTargetHandler(focus_controller);
325 aura::client::SetActivationClient(host_->window(), NULL);
327 root_window_event_filter_.reset();
328 capture_client_.reset();
329 input_method_filter_.reset();
330 focus_client_.reset();
331 cursor_manager_.reset();
332 #if defined(OS_CHROMEOS)
333 user_activity_notifier_.reset();
335 user_activity_detector_.reset();
339 gfx::Size ShellDesktopController::GetPrimaryDisplaySize() {
340 #if defined(OS_CHROMEOS)
341 const std::vector<ui::DisplayConfigurator::DisplayState>& displays =
342 display_configurator_->cached_displays();
343 if (displays.empty())
345 const ui::DisplayMode* mode = displays[0].display->current_mode();
346 return mode ? mode->size() : gfx::Size();
352 } // namespace extensions