| Index: athena/screen/screen_manager_impl.cc
|
| diff --git a/athena/screen/screen_manager_impl.cc b/athena/screen/screen_manager_impl.cc
|
| index 3ece1988ed8bf8cf220f19b8871dd4609f06ddab..5182b7e8e622f84c220584281958aa18d808e9e7 100644
|
| --- a/athena/screen/screen_manager_impl.cc
|
| +++ b/athena/screen/screen_manager_impl.cc
|
| @@ -2,23 +2,22 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "athena/screen/public/screen_manager.h"
|
| +#include "athena/screen/screen_manager_impl.h"
|
|
|
| #include "athena/input/public/accelerator_manager.h"
|
| +#include "athena/screen/modal_window_controller.h"
|
| #include "athena/screen/screen_accelerator_handler.h"
|
| #include "athena/util/container_priorities.h"
|
| #include "athena/util/fill_layout_manager.h"
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "ui/aura/client/aura_constants.h"
|
| #include "ui/aura/client/screen_position_client.h"
|
| -#include "ui/aura/client/window_tree_client.h"
|
| -#include "ui/aura/layout_manager.h"
|
| #include "ui/aura/test/test_screen.h"
|
| #include "ui/aura/window.h"
|
| #include "ui/aura/window_property.h"
|
| #include "ui/aura/window_targeter.h"
|
| #include "ui/aura/window_tree_host.h"
|
| -#include "ui/compositor/layer.h"
|
| #include "ui/gfx/display.h"
|
| #include "ui/gfx/screen.h"
|
| #include "ui/wm/core/base_focus_rules.h"
|
| @@ -26,6 +25,9 @@
|
| #include "ui/wm/core/focus_controller.h"
|
| #include "ui/wm/core/window_util.h"
|
|
|
| +// This is to avoid creating type definitoin for kAlwaysOnTopKey.
|
| +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ATHENA_EXPORT, bool);
|
| +
|
| namespace athena {
|
| namespace {
|
|
|
| @@ -33,12 +35,38 @@ DEFINE_OWNED_WINDOW_PROPERTY_KEY(ScreenManager::ContainerParams,
|
| kContainerParamsKey,
|
| NULL);
|
|
|
| -ScreenManager* instance = NULL;
|
| +ScreenManagerImpl* instance = NULL;
|
| +
|
| +// A functor to find a container that has the higher priority.
|
| +struct HigherPriorityFinder {
|
| + HigherPriorityFinder(int p) : priority(p) {}
|
| + bool operator()(aura::Window* window) {
|
| + return window->GetProperty(kContainerParamsKey)->z_order_priority >
|
| + priority;
|
| + }
|
| + int priority;
|
| +};
|
|
|
| -bool GrabsInput(aura::Window* container) {
|
| +bool BlockEvents(aura::Window* container) {
|
| ScreenManager::ContainerParams* params =
|
| container->GetProperty(kContainerParamsKey);
|
| - return params && params->grab_inputs;
|
| + return params && params->block_events;
|
| +}
|
| +
|
| +bool DefaultContainer(aura::Window* container) {
|
| + ScreenManager::ContainerParams* params =
|
| + container->GetProperty(kContainerParamsKey);
|
| + return params && params->default_parent;
|
| +}
|
| +
|
| +bool HasModalContainerPriority(aura::Window* container) {
|
| + ScreenManager::ContainerParams* params =
|
| + container->GetProperty(kContainerParamsKey);
|
| + return params && params->modal_container_priority != -1;
|
| +}
|
| +
|
| +bool IsSystemModal(aura::Window* window) {
|
| + return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM;
|
| }
|
|
|
| // Returns the container which contains |window|.
|
| @@ -61,47 +89,34 @@ class AthenaFocusRules : public wm::BaseFocusRules {
|
| return params && params->can_activate_children;
|
| }
|
| virtual bool CanActivateWindow(aura::Window* window) const override {
|
| - // Check if containers of higher z-order than |window| have 'grab_inputs'
|
| + if (!window)
|
| + return true;
|
| +
|
| + // Check if containers of higher z-order than |window| have 'block_events'
|
| // fields.
|
| - if (window) {
|
| + if (window->GetRootWindow()) {
|
| const aura::Window::Windows& containers =
|
| window->GetRootWindow()->children();
|
| aura::Window::Windows::const_iterator iter =
|
| std::find(containers.begin(), containers.end(), GetContainer(window));
|
| DCHECK(iter != containers.end());
|
| for (++iter; iter != containers.end(); ++iter) {
|
| - if (GrabsInput(*iter))
|
| + if (BlockEvents(*iter))
|
| return false;
|
| }
|
| }
|
| return BaseFocusRules::CanActivateWindow(window);
|
| }
|
|
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(AthenaFocusRules);
|
| -};
|
| -
|
| -class AthenaWindowTreeClient : public aura::client::WindowTreeClient {
|
| - public:
|
| - explicit AthenaWindowTreeClient(aura::Window* container)
|
| - : container_(container) {}
|
| -
|
| - private:
|
| - virtual ~AthenaWindowTreeClient() {}
|
| -
|
| - // aura::client::WindowTreeClient:
|
| - virtual aura::Window* GetDefaultParent(aura::Window* context,
|
| - aura::Window* window,
|
| - const gfx::Rect& bounds) override {
|
| - aura::Window* transient_parent = wm::GetTransientParent(window);
|
| - if (transient_parent)
|
| - return GetContainer(transient_parent);
|
| - return container_;
|
| + virtual aura::Window* GetNextActivatableWindow(
|
| + aura::Window* ignore) const override {
|
| + aura::Window* next = wm::BaseFocusRules::GetNextActivatableWindow(ignore);
|
| + // TODO(oshima): Search from activatable containers if |next| is NULL.
|
| + return next;
|
| }
|
|
|
| - aura::Window* container_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(AthenaWindowTreeClient);
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(AthenaFocusRules);
|
| };
|
|
|
| class AthenaScreenPositionClient : public aura::client::ScreenPositionClient {
|
| @@ -140,93 +155,56 @@ class AthenaScreenPositionClient : public aura::client::ScreenPositionClient {
|
| DISALLOW_COPY_AND_ASSIGN(AthenaScreenPositionClient);
|
| };
|
|
|
| -class AthenaEventTargeter : public aura::WindowTargeter,
|
| - public aura::WindowObserver {
|
| +class AthenaWindowTargeter : public aura::WindowTargeter {
|
| public:
|
| - explicit AthenaEventTargeter(aura::Window* container)
|
| - : container_(container) {
|
| - container_->AddObserver(this);
|
| - }
|
| + explicit AthenaWindowTargeter(aura::Window* root_window)
|
| + : root_window_(root_window) {}
|
|
|
| - virtual ~AthenaEventTargeter() {
|
| - // Removed before the container is removed.
|
| - if (container_)
|
| - container_->RemoveObserver(this);
|
| - }
|
| -
|
| - void SetPreviousEventTargeter(scoped_ptr<ui::EventTargeter> targeter) {
|
| - previous_root_event_targeter_ = targeter.Pass();
|
| - }
|
| + virtual ~AthenaWindowTargeter() {}
|
|
|
| private:
|
| // aura::WindowTargeter:
|
| virtual bool SubtreeCanAcceptEvent(
|
| ui::EventTarget* target,
|
| const ui::LocatedEvent& event) const override {
|
| + const aura::Window::Windows& containers = root_window_->children();
|
| + auto r_iter =
|
| + std::find_if(containers.rbegin(), containers.rend(), &BlockEvents);
|
| + if (r_iter == containers.rend())
|
| + return aura::WindowTargeter::SubtreeCanAcceptEvent(target, event);
|
| +
|
| aura::Window* window = static_cast<aura::Window*>(target);
|
| - const aura::Window::Windows& containers =
|
| - container_->GetRootWindow()->children();
|
| - aura::Window::Windows::const_iterator iter =
|
| - std::find(containers.begin(), containers.end(), container_);
|
| - DCHECK(iter != containers.end());
|
| - for (; iter != containers.end(); ++iter) {
|
| - if ((*iter)->Contains(window))
|
| - return true;
|
| + for (;; --r_iter) {
|
| + if ((*r_iter)->Contains(window))
|
| + return aura::WindowTargeter::SubtreeCanAcceptEvent(target, event);
|
| + if (r_iter == containers.rbegin())
|
| + break;
|
| }
|
| return false;
|
| }
|
|
|
| - // aura::WindowObserver:
|
| - virtual void OnWindowDestroying(aura::Window* window) override {
|
| - aura::Window* root_window = container_->GetRootWindow();
|
| - DCHECK_EQ(window, container_);
|
| - DCHECK_EQ(
|
| - this, static_cast<ui::EventTarget*>(root_window)->GetEventTargeter());
|
| -
|
| - container_->RemoveObserver(this);
|
| - container_ = NULL;
|
| -
|
| - // This will remove myself.
|
| - root_window->SetEventTargeter(previous_root_event_targeter_.Pass());
|
| + virtual ui::EventTarget* FindTargetForLocatedEvent(
|
| + ui::EventTarget* root,
|
| + ui::LocatedEvent* event) override {
|
| + ui::EventTarget* target =
|
| + aura::WindowTargeter::FindTargetForLocatedEvent(root, event);
|
| + if (target)
|
| + return target;
|
| + // If the root target is blocking the event, return the container even if
|
| + // there is no target found so that windows behind it will not be searched.
|
| + const ScreenManager::ContainerParams* params =
|
| + static_cast<aura::Window*>(root)->GetProperty(kContainerParamsKey);
|
| + return (params && params->block_events) ? root : NULL;
|
| }
|
|
|
| - aura::Window* container_;
|
| - scoped_ptr<ui::EventTargeter> previous_root_event_targeter_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(AthenaEventTargeter);
|
| -};
|
| -
|
| -class ScreenManagerImpl : public ScreenManager {
|
| - public:
|
| - explicit ScreenManagerImpl(aura::Window* root_window);
|
| - virtual ~ScreenManagerImpl();
|
| -
|
| - void Init();
|
| -
|
| - private:
|
| - // ScreenManager:
|
| - virtual aura::Window* CreateDefaultContainer(
|
| - const ContainerParams& params) override;
|
| - virtual aura::Window* CreateContainer(const ContainerParams& params) override;
|
| - virtual aura::Window* GetContext() override { return root_window_; }
|
| - virtual void SetRotation(gfx::Display::Rotation rotation) override;
|
| - virtual void SetRotationLocked(bool rotation_locked) override;
|
| -
|
| // Not owned.
|
| aura::Window* root_window_;
|
|
|
| - scoped_ptr<aura::client::FocusClient> focus_client_;
|
| - scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
|
| - scoped_ptr<AcceleratorHandler> accelerator_handler_;
|
| - scoped_ptr< ::wm::ScopedCaptureClient> capture_client_;
|
| - scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_;
|
| -
|
| - gfx::Display::Rotation last_requested_rotation_;
|
| - bool rotation_locked_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ScreenManagerImpl);
|
| + DISALLOW_COPY_AND_ASSIGN(AthenaWindowTargeter);
|
| };
|
|
|
| +} // namespace
|
| +
|
| ScreenManagerImpl::ScreenManagerImpl(aura::Window* root_window)
|
| : root_window_(root_window),
|
| last_requested_rotation_(gfx::Display::ROTATE_0),
|
| @@ -266,77 +244,49 @@ void ScreenManagerImpl::Init() {
|
| root_window_->SetLayoutManager(new FillLayoutManager(root_window_));
|
| capture_client_.reset(new ::wm::ScopedCaptureClient(root_window_));
|
| accelerator_handler_.reset(new ScreenAcceleratorHandler(root_window_));
|
| -}
|
|
|
| -aura::Window* ScreenManagerImpl::CreateDefaultContainer(
|
| - const ContainerParams& params) {
|
| - aura::Window* container = CreateContainer(params);
|
| - window_tree_client_.reset(new AthenaWindowTreeClient(container));
|
| - aura::client::SetWindowTreeClient(root_window_, window_tree_client_.get());
|
| + aura::client::SetWindowTreeClient(root_window_, this);
|
|
|
| screen_position_client_.reset(new AthenaScreenPositionClient());
|
| aura::client::SetScreenPositionClient(root_window_,
|
| screen_position_client_.get());
|
| -
|
| - return container;
|
| + root_window_->SetEventTargeter(
|
| + make_scoped_ptr(new AthenaWindowTargeter(root_window_)));
|
| }
|
|
|
| -// A functor to find a container that has the higher priority.
|
| -struct HigherPriorityFinder {
|
| - HigherPriorityFinder(int p) : priority(p) {}
|
| - bool operator()(aura::Window* window) {
|
| - return window->GetProperty(kContainerParamsKey)->z_order_priority >
|
| - priority;
|
| +aura::Window* ScreenManagerImpl::FindContainerByPriority(int priority) {
|
| + for (aura::Window* window : root_window_->children()) {
|
| + if (window->GetProperty(kContainerParamsKey)->z_order_priority == priority)
|
| + return window;
|
| }
|
| - int priority;
|
| -};
|
| -
|
| -#if !defined(NDEBUG)
|
| -struct PriorityMatcher {
|
| - PriorityMatcher(int p) : priority(p) {}
|
| - bool operator()(aura::Window* window) {
|
| - return window->GetProperty(kContainerParamsKey)->z_order_priority ==
|
| - priority;
|
| - }
|
| - int priority;
|
| -};
|
| -#endif
|
| + return NULL;
|
| +}
|
|
|
| aura::Window* ScreenManagerImpl::CreateContainer(
|
| const ContainerParams& params) {
|
| + const aura::Window::Windows& children = root_window_->children();
|
| +
|
| + if (params.default_parent) {
|
| + CHECK(std::find_if(children.begin(), children.end(), &DefaultContainer) ==
|
| + children.end());
|
| + }
|
| + // mmodal container's priority must be higher than the container's priority.
|
| + DCHECK(params.modal_container_priority == -1 ||
|
| + params.modal_container_priority > params.z_order_priority);
|
| + // Default parent must specify modal_container_priority.
|
| + DCHECK(!params.default_parent || params.modal_container_priority != -1);
|
| +
|
| aura::Window* container = new aura::Window(NULL);
|
| CHECK_GE(params.z_order_priority, 0);
|
| container->Init(aura::WINDOW_LAYER_NOT_DRAWN);
|
| container->SetName(params.name);
|
|
|
| - const aura::Window::Windows& children = root_window_->children();
|
| -
|
| -#if !defined(NDEBUG)
|
| - DCHECK(std::find_if(children.begin(),
|
| - children.end(),
|
| - PriorityMatcher(params.z_order_priority))
|
| - == children.end())
|
| - << "The container with the priority "
|
| - << params.z_order_priority << " already exists.";
|
| -#endif
|
| + DCHECK(!FindContainerByPriority(params.z_order_priority))
|
| + << "The container with the priority " << params.z_order_priority
|
| + << " already exists.";
|
|
|
| container->SetProperty(kContainerParamsKey, new ContainerParams(params));
|
|
|
| - // If another container is already grabbing the input, SetEventTargeter
|
| - // implicitly release the grabbing and remove the EventTargeter instance.
|
| - // TODO(mukai|oshima): think about the ideal behavior of multiple grabbing
|
| - // and implement it.
|
| - if (params.grab_inputs) {
|
| - DCHECK(std::find_if(children.begin(), children.end(), &GrabsInput)
|
| - == children.end())
|
| - << "input has already been grabbed by another container";
|
| - AthenaEventTargeter* athena_event_targeter =
|
| - new AthenaEventTargeter(container);
|
| - athena_event_targeter->SetPreviousEventTargeter(
|
| - root_window_->SetEventTargeter(
|
| - scoped_ptr<ui::EventTargeter>(athena_event_targeter)));
|
| - }
|
| -
|
| root_window_->AddChild(container);
|
|
|
| aura::Window::Windows::const_iterator iter =
|
| @@ -350,6 +300,10 @@ aura::Window* ScreenManagerImpl::CreateContainer(
|
| return container;
|
| }
|
|
|
| +aura::Window* ScreenManagerImpl::GetContext() {
|
| + return root_window_;
|
| +}
|
| +
|
| void ScreenManagerImpl::SetRotation(gfx::Display::Rotation rotation) {
|
| last_requested_rotation_ = rotation;
|
| if (rotation_locked_ || rotation ==
|
| @@ -369,14 +323,62 @@ void ScreenManagerImpl::SetRotationLocked(bool rotation_locked) {
|
| SetRotation(last_requested_rotation_);
|
| }
|
|
|
| -} // namespace
|
| +int ScreenManagerImpl::GetModalContainerPriority(aura::Window* window,
|
| + aura::Window* parent) {
|
| + const aura::Window::Windows& children = root_window_->children();
|
| + if (window->GetProperty(aura::client::kAlwaysOnTopKey)) {
|
| + // Use top most modal container.
|
| + auto iter = std::find_if(
|
| + children.rbegin(), children.rend(), &HasModalContainerPriority);
|
| + DCHECK(iter != children.rend());
|
| + return (*iter)->GetProperty(kContainerParamsKey)->modal_container_priority;
|
| + } else {
|
| + // use the container closest to the parent which has modal
|
| + // container priority.
|
| + auto iter = std::find(children.rbegin(), children.rend(), parent);
|
| + DCHECK(iter != children.rend());
|
| + iter = std::find_if(iter, children.rend(), &HasModalContainerPriority);
|
| + DCHECK(iter != children.rend());
|
| + return (*iter)->GetProperty(kContainerParamsKey)->modal_container_priority;
|
| + }
|
| +}
|
| +
|
| +aura::Window* ScreenManagerImpl::GetDefaultParent(aura::Window* context,
|
| + aura::Window* window,
|
| + const gfx::Rect& bounds) {
|
| + aura::Window* parent = wm::GetTransientParent(window);
|
| + if (parent)
|
| + parent = GetContainer(parent);
|
| + else
|
| + parent = GetDefaultContainer();
|
| +
|
| + if (IsSystemModal(window)) {
|
| + DCHECK(window->type() == ui::wm::WINDOW_TYPE_NORMAL ||
|
| + window->type() == ui::wm::WINDOW_TYPE_POPUP);
|
| + int priority = GetModalContainerPriority(window, parent);
|
| +
|
| + parent = FindContainerByPriority(priority);
|
| + if (!parent) {
|
| + ModalWindowController* controller = new ModalWindowController(priority);
|
| + parent = controller->modal_container();
|
| + }
|
| + }
|
| + return parent;
|
| +}
|
| +
|
| +aura::Window* ScreenManagerImpl::GetDefaultContainer() {
|
| + const aura::Window::Windows& children = root_window_->children();
|
| + return *(std::find_if(children.begin(), children.end(), &DefaultContainer));
|
| +}
|
|
|
| ScreenManager::ContainerParams::ContainerParams(const std::string& n,
|
| int priority)
|
| : name(n),
|
| can_activate_children(false),
|
| - grab_inputs(false),
|
| - z_order_priority(priority) {
|
| + block_events(false),
|
| + z_order_priority(priority),
|
| + default_parent(false),
|
| + modal_container_priority(-1) {
|
| }
|
|
|
| // static
|
|
|