Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1075)

Unified Diff: athena/screen/screen_manager_impl.cc

Issue 662763002: Support modal windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git/+/master
Patch Set: fix leaks Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « athena/screen/screen_manager_impl.h ('k') | athena/screen/screen_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « athena/screen/screen_manager_impl.h ('k') | athena/screen/screen_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698