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 "athena/screen/public/screen_manager.h"
7 #include "athena/common/container_priorities.h"
8 #include "athena/common/fill_layout_manager.h"
9 #include "athena/input/public/accelerator_manager.h"
10 #include "athena/screen/background_controller.h"
11 #include "athena/screen/screen_accelerator_handler.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "ui/aura/client/screen_position_client.h"
15 #include "ui/aura/client/window_tree_client.h"
16 #include "ui/aura/layout_manager.h"
17 #include "ui/aura/test/test_screen.h"
18 #include "ui/aura/window.h"
19 #include "ui/aura/window_property.h"
20 #include "ui/aura/window_targeter.h"
21 #include "ui/aura/window_tree_host.h"
22 #include "ui/compositor/layer.h"
23 #include "ui/gfx/display.h"
24 #include "ui/gfx/screen.h"
25 #include "ui/wm/core/base_focus_rules.h"
26 #include "ui/wm/core/capture_controller.h"
31 DEFINE_OWNED_WINDOW_PROPERTY_KEY(ScreenManager::ContainerParams,
35 ScreenManager* instance = NULL;
37 bool GrabsInput(aura::Window* container) {
38 ScreenManager::ContainerParams* params =
39 container->GetProperty(kContainerParamsKey);
40 return params && params->grab_inputs;
43 // Returns the container which contains |window|.
44 aura::Window* GetContainer(aura::Window* window) {
45 // No containers for NULL or the root window itself.
46 if (!window || !window->parent())
48 if (window->parent()->IsRootWindow())
50 return GetContainer(window->parent());
53 class AthenaFocusRules : public wm::BaseFocusRules {
56 virtual ~AthenaFocusRules() {}
58 // wm::BaseFocusRules:
59 virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE {
60 ScreenManager::ContainerParams* params =
61 window->GetProperty(kContainerParamsKey);
62 return params && params->can_activate_children;
64 virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE {
65 // Check if containers of higher z-order than |window| have 'grab_inputs'
68 const aura::Window::Windows& containers =
69 window->GetRootWindow()->children();
70 aura::Window::Windows::const_iterator iter =
71 std::find(containers.begin(), containers.end(), GetContainer(window));
72 DCHECK(iter != containers.end());
73 for (++iter; iter != containers.end(); ++iter) {
74 if (GrabsInput(*iter))
78 return BaseFocusRules::CanActivateWindow(window);
82 DISALLOW_COPY_AND_ASSIGN(AthenaFocusRules);
85 class AthenaWindowTreeClient : public aura::client::WindowTreeClient {
87 explicit AthenaWindowTreeClient(aura::Window* container)
88 : container_(container) {}
91 virtual ~AthenaWindowTreeClient() {}
93 // aura::client::WindowTreeClient:
94 virtual aura::Window* GetDefaultParent(aura::Window* context,
96 const gfx::Rect& bounds) OVERRIDE {
100 aura::Window* container_;
102 DISALLOW_COPY_AND_ASSIGN(AthenaWindowTreeClient);
105 class AthenaScreenPositionClient : public aura::client::ScreenPositionClient {
107 AthenaScreenPositionClient() {
109 virtual ~AthenaScreenPositionClient() {
113 // aura::client::ScreenPositionClient:
114 virtual void ConvertPointToScreen(const aura::Window* window,
115 gfx::Point* point) OVERRIDE {
116 const aura::Window* root = window->GetRootWindow();
117 aura::Window::ConvertPointToTarget(window, root, point);
120 virtual void ConvertPointFromScreen(const aura::Window* window,
121 gfx::Point* point) OVERRIDE {
122 const aura::Window* root = window->GetRootWindow();
123 aura::Window::ConvertPointToTarget(root, window, point);
126 virtual void ConvertHostPointToScreen(aura::Window* window,
127 gfx::Point* point) OVERRIDE {
128 // TODO(oshima): Implement this when adding multiple display support.
132 virtual void SetBounds(aura::Window* window,
133 const gfx::Rect& bounds,
134 const gfx::Display& display) OVERRIDE {
135 window->SetBounds(bounds);
138 DISALLOW_COPY_AND_ASSIGN(AthenaScreenPositionClient);
141 class AthenaEventTargeter : public aura::WindowTargeter,
142 public aura::WindowObserver {
144 explicit AthenaEventTargeter(aura::Window* container)
145 : container_(container) {
146 container_->AddObserver(this);
149 virtual ~AthenaEventTargeter() {
150 // Removed before the container is removed.
152 container_->RemoveObserver(this);
156 // aura::WindowTargeter:
157 virtual bool SubtreeCanAcceptEvent(
158 ui::EventTarget* target,
159 const ui::LocatedEvent& event) const OVERRIDE {
160 aura::Window* window = static_cast<aura::Window*>(target);
161 const aura::Window::Windows& containers =
162 container_->GetRootWindow()->children();
163 aura::Window::Windows::const_iterator iter =
164 std::find(containers.begin(), containers.end(), container_);
165 DCHECK(iter != containers.end());
166 for (; iter != containers.end(); ++iter) {
167 if ((*iter)->Contains(window))
173 // aura::WindowObserver:
174 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
175 aura::Window* root_window = container_->GetRootWindow();
176 DCHECK_EQ(window, container_);
178 this, static_cast<ui::EventTarget*>(root_window)->GetEventTargeter());
180 container_->RemoveObserver(this);
183 // This will remove myself.
184 root_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>());
187 aura::Window* container_;
189 DISALLOW_COPY_AND_ASSIGN(AthenaEventTargeter);
192 class ScreenManagerImpl : public ScreenManager {
194 explicit ScreenManagerImpl(aura::Window* root_window);
195 virtual ~ScreenManagerImpl();
201 virtual aura::Window* CreateDefaultContainer(
202 const ContainerParams& params) OVERRIDE;
203 virtual aura::Window* CreateContainer(const ContainerParams& params) OVERRIDE;
204 virtual aura::Window* GetContext() OVERRIDE { return root_window_; }
205 virtual void SetBackgroundImage(const gfx::ImageSkia& image) OVERRIDE;
206 virtual void SetRotation(gfx::Display::Rotation rotation) OVERRIDE;
207 virtual ui::LayerAnimator* GetScreenAnimator() OVERRIDE;
209 aura::Window* root_window_;
210 aura::Window* background_window_;
212 scoped_ptr<BackgroundController> background_controller_;
213 scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
214 scoped_ptr<AcceleratorHandler> accelerator_handler_;
215 scoped_ptr< ::wm::ScopedCaptureClient> capture_client_;
216 scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_;
218 DISALLOW_COPY_AND_ASSIGN(ScreenManagerImpl);
221 ScreenManagerImpl::ScreenManagerImpl(aura::Window* root_window)
222 : root_window_(root_window) {
223 DCHECK(root_window_);
228 ScreenManagerImpl::~ScreenManagerImpl() {
229 aura::client::SetScreenPositionClient(root_window_, NULL);
230 aura::client::SetWindowTreeClient(root_window_, NULL);
234 void ScreenManagerImpl::Init() {
235 // TODO(oshima): Move the background out from ScreenManager.
236 root_window_->SetLayoutManager(new FillLayoutManager(root_window_));
238 CreateContainer(ContainerParams("AthenaBackground", CP_BACKGROUND));
240 background_window_->SetLayoutManager(
241 new FillLayoutManager(background_window_));
242 background_controller_.reset(new BackgroundController(background_window_));
244 capture_client_.reset(new ::wm::ScopedCaptureClient(root_window_));
245 accelerator_handler_.reset(new ScreenAcceleratorHandler(root_window_));
248 aura::Window* ScreenManagerImpl::CreateDefaultContainer(
249 const ContainerParams& params) {
250 aura::Window* container = CreateContainer(params);
251 window_tree_client_.reset(new AthenaWindowTreeClient(container));
252 aura::client::SetWindowTreeClient(root_window_, window_tree_client_.get());
254 screen_position_client_.reset(new AthenaScreenPositionClient());
255 aura::client::SetScreenPositionClient(root_window_,
256 screen_position_client_.get());
261 // A functor to find a container that has the higher priority.
262 struct HigherPriorityFinder {
263 HigherPriorityFinder(int p) : priority(p) {}
264 bool operator()(aura::Window* window) {
265 return window->GetProperty(kContainerParamsKey)->z_order_priority >
272 struct PriorityMatcher {
273 PriorityMatcher(int p) : priority(p) {}
274 bool operator()(aura::Window* window) {
275 return window->GetProperty(kContainerParamsKey)->z_order_priority ==
282 aura::Window* ScreenManagerImpl::CreateContainer(
283 const ContainerParams& params) {
284 aura::Window* container = new aura::Window(NULL);
285 CHECK_GE(params.z_order_priority, 0);
286 container->Init(aura::WINDOW_LAYER_NOT_DRAWN);
287 container->SetName(params.name);
289 const aura::Window::Windows& children = root_window_->children();
292 DCHECK(std::find_if(children.begin(),
294 PriorityMatcher(params.z_order_priority))
296 << "The container with the priority "
297 << params.z_order_priority << " already exists.";
300 container->SetProperty(kContainerParamsKey, new ContainerParams(params));
302 // If another container is already grabbing the input, SetEventTargeter
303 // implicitly release the grabbing and remove the EventTargeter instance.
304 // TODO(mukai|oshima): think about the ideal behavior of multiple grabbing
306 if (params.grab_inputs) {
307 DCHECK(std::find_if(children.begin(), children.end(), &GrabsInput)
309 << "input has already been grabbed by another container";
310 root_window_->SetEventTargeter(
311 scoped_ptr<ui::EventTargeter>(new AthenaEventTargeter(container)));
314 root_window_->AddChild(container);
316 aura::Window::Windows::const_iterator iter =
317 std::find_if(children.begin(),
319 HigherPriorityFinder(params.z_order_priority));
320 if (iter != children.end())
321 root_window_->StackChildBelow(container, *iter);
327 void ScreenManagerImpl::SetBackgroundImage(const gfx::ImageSkia& image) {
328 background_controller_->SetImage(image);
331 void ScreenManagerImpl::SetRotation(gfx::Display::Rotation rotation) {
333 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().rotation()) {
337 // TODO(flackr): Use display manager to update display rotation:
338 // http://crbug.com/401044.
339 static_cast<aura::TestScreen*>(gfx::Screen::GetNativeScreen())->
340 SetDisplayRotation(rotation);
343 ui::LayerAnimator* ScreenManagerImpl::GetScreenAnimator() {
344 return root_window_->layer()->GetAnimator();
349 ScreenManager::ContainerParams::ContainerParams(const std::string& n,
352 can_activate_children(false),
354 z_order_priority(priority) {
358 ScreenManager* ScreenManager::Create(aura::Window* root_window) {
359 (new ScreenManagerImpl(root_window))->Init();
365 ScreenManager* ScreenManager::Get() {
371 void ScreenManager::Shutdown() {
378 wm::FocusRules* ScreenManager::CreateFocusRules() {
379 return new AthenaFocusRules();
382 } // namespace athena