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"
27 #include "ui/wm/core/focus_controller.h"
32 DEFINE_OWNED_WINDOW_PROPERTY_KEY(ScreenManager::ContainerParams
,
36 ScreenManager
* instance
= NULL
;
38 bool GrabsInput(aura::Window
* container
) {
39 ScreenManager::ContainerParams
* params
=
40 container
->GetProperty(kContainerParamsKey
);
41 return params
&& params
->grab_inputs
;
44 // Returns the container which contains |window|.
45 aura::Window
* GetContainer(aura::Window
* window
) {
46 // No containers for NULL or the root window itself.
47 if (!window
|| !window
->parent())
49 if (window
->parent()->IsRootWindow())
51 return GetContainer(window
->parent());
54 class AthenaFocusRules
: public wm::BaseFocusRules
{
57 virtual ~AthenaFocusRules() {}
59 // wm::BaseFocusRules:
60 virtual bool SupportsChildActivation(aura::Window
* window
) const OVERRIDE
{
61 ScreenManager::ContainerParams
* params
=
62 window
->GetProperty(kContainerParamsKey
);
63 return params
&& params
->can_activate_children
;
65 virtual bool CanActivateWindow(aura::Window
* window
) const OVERRIDE
{
66 // Check if containers of higher z-order than |window| have 'grab_inputs'
69 const aura::Window::Windows
& containers
=
70 window
->GetRootWindow()->children();
71 aura::Window::Windows::const_iterator iter
=
72 std::find(containers
.begin(), containers
.end(), GetContainer(window
));
73 DCHECK(iter
!= containers
.end());
74 for (++iter
; iter
!= containers
.end(); ++iter
) {
75 if (GrabsInput(*iter
))
79 return BaseFocusRules::CanActivateWindow(window
);
83 DISALLOW_COPY_AND_ASSIGN(AthenaFocusRules
);
86 class AthenaWindowTreeClient
: public aura::client::WindowTreeClient
{
88 explicit AthenaWindowTreeClient(aura::Window
* container
)
89 : container_(container
) {}
92 virtual ~AthenaWindowTreeClient() {}
94 // aura::client::WindowTreeClient:
95 virtual aura::Window
* GetDefaultParent(aura::Window
* context
,
97 const gfx::Rect
& bounds
) OVERRIDE
{
101 aura::Window
* container_
;
103 DISALLOW_COPY_AND_ASSIGN(AthenaWindowTreeClient
);
106 class AthenaScreenPositionClient
: public aura::client::ScreenPositionClient
{
108 AthenaScreenPositionClient() {
110 virtual ~AthenaScreenPositionClient() {
114 // aura::client::ScreenPositionClient:
115 virtual void ConvertPointToScreen(const aura::Window
* window
,
116 gfx::Point
* point
) OVERRIDE
{
117 const aura::Window
* root
= window
->GetRootWindow();
118 aura::Window::ConvertPointToTarget(window
, root
, point
);
121 virtual void ConvertPointFromScreen(const aura::Window
* window
,
122 gfx::Point
* point
) OVERRIDE
{
123 const aura::Window
* root
= window
->GetRootWindow();
124 aura::Window::ConvertPointToTarget(root
, window
, point
);
127 virtual void ConvertHostPointToScreen(aura::Window
* window
,
128 gfx::Point
* point
) OVERRIDE
{
129 // TODO(oshima): Implement this when adding multiple display support.
133 virtual void SetBounds(aura::Window
* window
,
134 const gfx::Rect
& bounds
,
135 const gfx::Display
& display
) OVERRIDE
{
136 window
->SetBounds(bounds
);
139 DISALLOW_COPY_AND_ASSIGN(AthenaScreenPositionClient
);
142 class AthenaEventTargeter
: public aura::WindowTargeter
,
143 public aura::WindowObserver
{
145 explicit AthenaEventTargeter(aura::Window
* container
)
146 : container_(container
) {
147 container_
->AddObserver(this);
150 virtual ~AthenaEventTargeter() {
151 // Removed before the container is removed.
153 container_
->RemoveObserver(this);
157 // aura::WindowTargeter:
158 virtual bool SubtreeCanAcceptEvent(
159 ui::EventTarget
* target
,
160 const ui::LocatedEvent
& event
) const OVERRIDE
{
161 aura::Window
* window
= static_cast<aura::Window
*>(target
);
162 const aura::Window::Windows
& containers
=
163 container_
->GetRootWindow()->children();
164 aura::Window::Windows::const_iterator iter
=
165 std::find(containers
.begin(), containers
.end(), container_
);
166 DCHECK(iter
!= containers
.end());
167 for (; iter
!= containers
.end(); ++iter
) {
168 if ((*iter
)->Contains(window
))
174 // aura::WindowObserver:
175 virtual void OnWindowDestroying(aura::Window
* window
) OVERRIDE
{
176 aura::Window
* root_window
= container_
->GetRootWindow();
177 DCHECK_EQ(window
, container_
);
179 this, static_cast<ui::EventTarget
*>(root_window
)->GetEventTargeter());
181 container_
->RemoveObserver(this);
184 // This will remove myself.
185 root_window
->SetEventTargeter(scoped_ptr
<ui::EventTargeter
>());
188 aura::Window
* container_
;
190 DISALLOW_COPY_AND_ASSIGN(AthenaEventTargeter
);
193 class ScreenManagerImpl
: public ScreenManager
{
195 ScreenManagerImpl(aura::Window
* root_window
);
196 virtual ~ScreenManagerImpl();
202 virtual aura::Window
* CreateDefaultContainer(
203 const ContainerParams
& params
) OVERRIDE
;
204 virtual aura::Window
* CreateContainer(const ContainerParams
& params
) OVERRIDE
;
205 virtual aura::Window
* GetContext() OVERRIDE
{ return root_window_
; }
206 virtual void SetBackgroundImage(const gfx::ImageSkia
& image
) OVERRIDE
;
207 virtual void SetRotation(gfx::Display::Rotation rotation
) OVERRIDE
;
208 virtual ui::LayerAnimator
* GetScreenAnimator() OVERRIDE
;
211 aura::Window
* root_window_
;
212 aura::Window
* background_window_
;
214 scoped_ptr
<aura::client::FocusClient
> focus_client_
;
215 scoped_ptr
<BackgroundController
> background_controller_
;
216 scoped_ptr
<aura::client::WindowTreeClient
> window_tree_client_
;
217 scoped_ptr
<AcceleratorHandler
> accelerator_handler_
;
218 scoped_ptr
< ::wm::ScopedCaptureClient
> capture_client_
;
219 scoped_ptr
<aura::client::ScreenPositionClient
> screen_position_client_
;
221 DISALLOW_COPY_AND_ASSIGN(ScreenManagerImpl
);
224 ScreenManagerImpl::ScreenManagerImpl(aura::Window
* root_window
)
225 : root_window_(root_window
) {
226 DCHECK(root_window_
);
231 ScreenManagerImpl::~ScreenManagerImpl() {
232 aura::client::SetScreenPositionClient(root_window_
, NULL
);
233 aura::client::SetWindowTreeClient(root_window_
, NULL
);
234 wm::FocusController
* focus_controller
=
235 static_cast<wm::FocusController
*>(focus_client_
.get());
236 root_window_
->RemovePreTargetHandler(focus_controller
);
237 aura::client::SetActivationClient(root_window_
, NULL
);
238 aura::client::SetFocusClient(root_window_
, NULL
);
242 void ScreenManagerImpl::Init() {
243 wm::FocusController
* focus_controller
=
244 new wm::FocusController(new AthenaFocusRules());
246 aura::client::SetFocusClient(root_window_
, focus_controller
);
247 root_window_
->AddPreTargetHandler(focus_controller
);
248 aura::client::SetActivationClient(root_window_
, focus_controller
);
249 focus_client_
.reset(focus_controller
);
251 // TODO(oshima): Move the background out from ScreenManager.
252 root_window_
->SetLayoutManager(new FillLayoutManager(root_window_
));
254 CreateContainer(ContainerParams("AthenaBackground", CP_BACKGROUND
));
256 background_window_
->SetLayoutManager(
257 new FillLayoutManager(background_window_
));
258 background_controller_
.reset(new BackgroundController(background_window_
));
260 capture_client_
.reset(new ::wm::ScopedCaptureClient(root_window_
));
261 accelerator_handler_
.reset(new ScreenAcceleratorHandler(root_window_
));
264 aura::Window
* ScreenManagerImpl::CreateDefaultContainer(
265 const ContainerParams
& params
) {
266 aura::Window
* container
= CreateContainer(params
);
267 window_tree_client_
.reset(new AthenaWindowTreeClient(container
));
268 aura::client::SetWindowTreeClient(root_window_
, window_tree_client_
.get());
270 screen_position_client_
.reset(new AthenaScreenPositionClient());
271 aura::client::SetScreenPositionClient(root_window_
,
272 screen_position_client_
.get());
277 // A functor to find a container that has the higher priority.
278 struct HigherPriorityFinder
{
279 HigherPriorityFinder(int p
) : priority(p
) {}
280 bool operator()(aura::Window
* window
) {
281 return window
->GetProperty(kContainerParamsKey
)->z_order_priority
>
288 struct PriorityMatcher
{
289 PriorityMatcher(int p
) : priority(p
) {}
290 bool operator()(aura::Window
* window
) {
291 return window
->GetProperty(kContainerParamsKey
)->z_order_priority
==
298 aura::Window
* ScreenManagerImpl::CreateContainer(
299 const ContainerParams
& params
) {
300 aura::Window
* container
= new aura::Window(NULL
);
301 CHECK_GE(params
.z_order_priority
, 0);
302 container
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
303 container
->SetName(params
.name
);
305 const aura::Window::Windows
& children
= root_window_
->children();
308 DCHECK(std::find_if(children
.begin(),
310 PriorityMatcher(params
.z_order_priority
))
312 << "The container with the priority "
313 << params
.z_order_priority
<< " already exists.";
316 container
->SetProperty(kContainerParamsKey
, new ContainerParams(params
));
318 // If another container is already grabbing the input, SetEventTargeter
319 // implicitly release the grabbing and remove the EventTargeter instance.
320 // TODO(mukai|oshima): think about the ideal behavior of multiple grabbing
322 if (params
.grab_inputs
) {
323 DCHECK(std::find_if(children
.begin(), children
.end(), &GrabsInput
)
325 << "input has already been grabbed by another container";
326 root_window_
->SetEventTargeter(
327 scoped_ptr
<ui::EventTargeter
>(new AthenaEventTargeter(container
)));
330 root_window_
->AddChild(container
);
332 aura::Window::Windows::const_iterator iter
=
333 std::find_if(children
.begin(),
335 HigherPriorityFinder(params
.z_order_priority
));
336 if (iter
!= children
.end())
337 root_window_
->StackChildBelow(container
, *iter
);
343 void ScreenManagerImpl::SetBackgroundImage(const gfx::ImageSkia
& image
) {
344 background_controller_
->SetImage(image
);
347 void ScreenManagerImpl::SetRotation(gfx::Display::Rotation rotation
) {
349 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().rotation()) {
353 // TODO(flackr): Use display manager to update display rotation:
354 // http://crbug.com/401044.
355 static_cast<aura::TestScreen
*>(gfx::Screen::GetNativeScreen())->
356 SetDisplayRotation(rotation
);
359 ui::LayerAnimator
* ScreenManagerImpl::GetScreenAnimator() {
360 return root_window_
->layer()->GetAnimator();
365 ScreenManager::ContainerParams::ContainerParams(const std::string
& n
,
368 can_activate_children(false),
370 z_order_priority(priority
) {
374 ScreenManager
* ScreenManager::Create(aura::Window
* root_window
) {
375 (new ScreenManagerImpl(root_window
))->Init();
381 ScreenManager
* ScreenManager::Get() {
387 void ScreenManager::Shutdown() {
393 } // namespace athena