Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / athena / screen / screen_manager_impl.cc
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.
4
5 #include "athena/screen/public/screen_manager.h"
6
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
28 namespace athena {
29 namespace {
30
31 DEFINE_OWNED_WINDOW_PROPERTY_KEY(ScreenManager::ContainerParams,
32                                  kContainerParamsKey,
33                                  NULL);
34
35 ScreenManager* instance = NULL;
36
37 bool GrabsInput(aura::Window* container) {
38   ScreenManager::ContainerParams* params =
39       container->GetProperty(kContainerParamsKey);
40   return params && params->grab_inputs;
41 }
42
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())
47     return NULL;
48   if (window->parent()->IsRootWindow())
49     return window;
50   return GetContainer(window->parent());
51 }
52
53 class AthenaFocusRules : public wm::BaseFocusRules {
54  public:
55   AthenaFocusRules() {}
56   virtual ~AthenaFocusRules() {}
57
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;
63   }
64   virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE {
65     // Check if containers of higher z-order than |window| have 'grab_inputs'
66     // fields.
67     if (window) {
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))
75           return false;
76       }
77     }
78     return BaseFocusRules::CanActivateWindow(window);
79   }
80
81  private:
82   DISALLOW_COPY_AND_ASSIGN(AthenaFocusRules);
83 };
84
85 class AthenaWindowTreeClient : public aura::client::WindowTreeClient {
86  public:
87   explicit AthenaWindowTreeClient(aura::Window* container)
88       : container_(container) {}
89
90  private:
91   virtual ~AthenaWindowTreeClient() {}
92
93   // aura::client::WindowTreeClient:
94   virtual aura::Window* GetDefaultParent(aura::Window* context,
95                                          aura::Window* window,
96                                          const gfx::Rect& bounds) OVERRIDE {
97     return container_;
98   }
99
100   aura::Window* container_;
101
102   DISALLOW_COPY_AND_ASSIGN(AthenaWindowTreeClient);
103 };
104
105 class AthenaScreenPositionClient : public aura::client::ScreenPositionClient {
106  public:
107   AthenaScreenPositionClient() {
108   }
109   virtual ~AthenaScreenPositionClient() {
110   }
111
112  private:
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);
118   }
119
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);
124   }
125
126   virtual void ConvertHostPointToScreen(aura::Window* window,
127                                         gfx::Point* point) OVERRIDE {
128     // TODO(oshima): Implement this when adding multiple display support.
129     NOTREACHED();
130   }
131
132   virtual void SetBounds(aura::Window* window,
133                          const gfx::Rect& bounds,
134                          const gfx::Display& display) OVERRIDE {
135     window->SetBounds(bounds);
136   }
137
138   DISALLOW_COPY_AND_ASSIGN(AthenaScreenPositionClient);
139 };
140
141 class AthenaEventTargeter : public aura::WindowTargeter,
142                             public aura::WindowObserver {
143  public:
144   explicit AthenaEventTargeter(aura::Window* container)
145       : container_(container) {
146     container_->AddObserver(this);
147   }
148
149   virtual ~AthenaEventTargeter() {
150     // Removed before the container is removed.
151     if (container_)
152       container_->RemoveObserver(this);
153   }
154
155  private:
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))
168         return true;
169     }
170     return false;
171   }
172
173   // aura::WindowObserver:
174   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
175     aura::Window* root_window = container_->GetRootWindow();
176     DCHECK_EQ(window, container_);
177     DCHECK_EQ(
178         this, static_cast<ui::EventTarget*>(root_window)->GetEventTargeter());
179
180     container_->RemoveObserver(this);
181     container_ = NULL;
182
183     // This will remove myself.
184     root_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>());
185   }
186
187   aura::Window* container_;
188
189   DISALLOW_COPY_AND_ASSIGN(AthenaEventTargeter);
190 };
191
192 class ScreenManagerImpl : public ScreenManager {
193  public:
194   explicit ScreenManagerImpl(aura::Window* root_window);
195   virtual ~ScreenManagerImpl();
196
197   void Init();
198
199  private:
200   // ScreenManager:
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;
208
209   aura::Window* root_window_;
210   aura::Window* background_window_;
211
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_;
217
218   DISALLOW_COPY_AND_ASSIGN(ScreenManagerImpl);
219 };
220
221 ScreenManagerImpl::ScreenManagerImpl(aura::Window* root_window)
222     : root_window_(root_window) {
223   DCHECK(root_window_);
224   DCHECK(!instance);
225   instance = this;
226 }
227
228 ScreenManagerImpl::~ScreenManagerImpl() {
229   aura::client::SetScreenPositionClient(root_window_, NULL);
230   aura::client::SetWindowTreeClient(root_window_, NULL);
231   instance = NULL;
232 }
233
234 void ScreenManagerImpl::Init() {
235   // TODO(oshima): Move the background out from ScreenManager.
236   root_window_->SetLayoutManager(new FillLayoutManager(root_window_));
237   background_window_ =
238       CreateContainer(ContainerParams("AthenaBackground", CP_BACKGROUND));
239
240   background_window_->SetLayoutManager(
241       new FillLayoutManager(background_window_));
242   background_controller_.reset(new BackgroundController(background_window_));
243
244   capture_client_.reset(new ::wm::ScopedCaptureClient(root_window_));
245   accelerator_handler_.reset(new ScreenAcceleratorHandler(root_window_));
246 }
247
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());
253
254   screen_position_client_.reset(new AthenaScreenPositionClient());
255   aura::client::SetScreenPositionClient(root_window_,
256                                         screen_position_client_.get());
257
258   return container;
259 }
260
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 >
266            priority;
267   }
268   int priority;
269 };
270
271 #if !defined(NDEBUG)
272 struct PriorityMatcher {
273   PriorityMatcher(int p) : priority(p) {}
274   bool operator()(aura::Window* window) {
275     return window->GetProperty(kContainerParamsKey)->z_order_priority ==
276            priority;
277   }
278   int priority;
279 };
280 #endif
281
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);
288
289   const aura::Window::Windows& children = root_window_->children();
290
291 #if !defined(NDEBUG)
292   DCHECK(std::find_if(children.begin(),
293                       children.end(),
294                       PriorityMatcher(params.z_order_priority))
295          == children.end())
296       << "The container with the priority "
297       << params.z_order_priority << " already exists.";
298 #endif
299
300   container->SetProperty(kContainerParamsKey, new ContainerParams(params));
301
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
305   // and implement it.
306   if (params.grab_inputs) {
307     DCHECK(std::find_if(children.begin(), children.end(), &GrabsInput)
308            == children.end())
309         << "input has already been grabbed by another container";
310     root_window_->SetEventTargeter(
311         scoped_ptr<ui::EventTargeter>(new AthenaEventTargeter(container)));
312   }
313
314   root_window_->AddChild(container);
315
316   aura::Window::Windows::const_iterator iter =
317       std::find_if(children.begin(),
318                    children.end(),
319                    HigherPriorityFinder(params.z_order_priority));
320   if (iter != children.end())
321     root_window_->StackChildBelow(container, *iter);
322
323   container->Show();
324   return container;
325 }
326
327 void ScreenManagerImpl::SetBackgroundImage(const gfx::ImageSkia& image) {
328   background_controller_->SetImage(image);
329 }
330
331 void ScreenManagerImpl::SetRotation(gfx::Display::Rotation rotation) {
332   if (rotation ==
333       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().rotation()) {
334     return;
335   }
336
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);
341 }
342
343 ui::LayerAnimator* ScreenManagerImpl::GetScreenAnimator() {
344   return root_window_->layer()->GetAnimator();
345 }
346
347 }  // namespace
348
349 ScreenManager::ContainerParams::ContainerParams(const std::string& n,
350                                                 int priority)
351     : name(n),
352       can_activate_children(false),
353       grab_inputs(false),
354       z_order_priority(priority) {
355 }
356
357 // static
358 ScreenManager* ScreenManager::Create(aura::Window* root_window) {
359   (new ScreenManagerImpl(root_window))->Init();
360   DCHECK(instance);
361   return instance;
362 }
363
364 // static
365 ScreenManager* ScreenManager::Get() {
366   DCHECK(instance);
367   return instance;
368 }
369
370 // static
371 void ScreenManager::Shutdown() {
372   DCHECK(instance);
373   delete instance;
374   DCHECK(!instance);
375 }
376
377 // static
378 wm::FocusRules* ScreenManager::CreateFocusRules() {
379   return new AthenaFocusRules();
380 }
381
382 }  // namespace athena