summaryrefslogtreecommitdiffstats
path: root/athena
diff options
context:
space:
mode:
authoroshima <oshima@chromium.org>2014-10-20 10:19:18 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-20 17:20:09 +0000
commit44bf2fd5fb11d3777e522fae68de024c8f6ce46f (patch)
treeee959cfe4065367147ab432ddd4b22a51f504004 /athena
parent3f5d1eae967412133ff221d2aea6dd325b45928c (diff)
downloadchromium_src-44bf2fd5fb11d3777e522fae68de024c8f6ce46f.zip
chromium_src-44bf2fd5fb11d3777e522fae68de024c8f6ce46f.tar.gz
chromium_src-44bf2fd5fb11d3777e522fae68de024c8f6ce46f.tar.bz2
Support modal windows
* New ContainerParams - default_parent to specify the default parent when no transient parent is specified. - modal_container_priority now controls the modal container used for a modal window created for the given container. - if not specified, it will fallback downwards to find one. - if window is specified as always_on_top, it will use top most modal container. * Changed network selector/shutdown dialog to use the new API. * Other change: Separated test windows to athena/test/base/test_windows.h BUG=410499 TBR=sky@chromium.org,reed@chromium.org TEST=coverd by unit tests Committed: https://crrev.com/4903fd36b2b36f00efeb1b7bba81b7de6e9457a3 Cr-Commit-Position: refs/heads/master@{#300192} Review URL: https://codereview.chromium.org/662763002 Cr-Commit-Position: refs/heads/master@{#300288}
Diffstat (limited to 'athena')
-rw-r--r--athena/activity/activity_manager_unittest.cc3
-rw-r--r--athena/athena.gyp5
-rw-r--r--athena/main/athena_launcher.cc4
-rw-r--r--athena/screen/DEPS3
-rw-r--r--athena/screen/modal_window_controller.cc146
-rw-r--r--athena/screen/modal_window_controller.h59
-rw-r--r--athena/screen/modal_window_controller_unittest.cc144
-rw-r--r--athena/screen/public/screen_manager.h35
-rw-r--r--athena/screen/screen_accelerator_handler.h4
-rw-r--r--athena/screen/screen_manager_impl.cc312
-rw-r--r--athena/screen/screen_manager_impl.h72
-rw-r--r--athena/screen/screen_manager_unittest.cc174
-rw-r--r--athena/system/network_selector.cc108
-rw-r--r--athena/system/network_selector.h6
-rw-r--r--athena/system/shutdown_dialog.cc48
-rw-r--r--athena/system/shutdown_dialog.h2
-rw-r--r--athena/system/status_icon_container_view.cc8
-rw-r--r--athena/system/status_icon_container_view.h10
-rw-r--r--athena/system/system_ui_impl.cc31
-rw-r--r--athena/test/DEPS2
-rw-r--r--athena/test/base/athena_test_base.cc14
-rw-r--r--athena/test/base/athena_test_base.h3
-rw-r--r--athena/test/base/test_windows.cc53
-rw-r--r--athena/test/base/test_windows.h39
-rw-r--r--athena/util/container_priorities.h2
-rw-r--r--athena/wm/split_view_controller_unittest.cc7
-rw-r--r--athena/wm/window_list_provider_impl_unittest.cc25
-rw-r--r--athena/wm/window_manager_impl.cc6
-rw-r--r--athena/wm/window_manager_unittest.cc3
29 files changed, 933 insertions, 395 deletions
diff --git a/athena/activity/activity_manager_unittest.cc b/athena/activity/activity_manager_unittest.cc
index 0ed2a9a..37f73f6 100644
--- a/athena/activity/activity_manager_unittest.cc
+++ b/athena/activity/activity_manager_unittest.cc
@@ -7,6 +7,7 @@
#include "athena/activity/public/activity.h"
#include "athena/activity/public/activity_factory.h"
#include "athena/test/base/athena_test_base.h"
+#include "athena/test/base/test_windows.h"
#include "ui/aura/window.h"
namespace athena {
@@ -53,7 +54,7 @@ TEST_F(ActivityManagerTest, GetActivityForWindow) {
EXPECT_EQ(NULL, manager->GetActivityForWindow(NULL));
- scoped_ptr<aura::Window> window = CreateTestWindow(NULL, gfx::Rect());
+ scoped_ptr<aura::Window> window = test::CreateNormalWindow(NULL, NULL);
EXPECT_EQ(NULL, manager->GetActivityForWindow(window.get()));
}
diff --git a/athena/athena.gyp b/athena/athena.gyp
index 4084fb2..ba463af 100644
--- a/athena/athena.gyp
+++ b/athena/athena.gyp
@@ -84,6 +84,8 @@
'screen/screen_accelerator_handler.cc',
'screen/screen_accelerator_handler.h',
'screen/screen_manager_impl.cc',
+ 'screen/modal_window_controller.cc',
+ 'screen/modal_window_controller.h',
'system/background_controller.cc',
'system/background_controller.h',
'system/network_selector.cc',
@@ -274,6 +276,8 @@
'test/base/test_app_model_builder.cc',
'test/base/test_app_model_builder.h',
'test/base/test_resource_manager_delegate.cc',
+ 'test/base/test_windows.cc',
+ 'test/base/test_windows.h',
'wm/test/window_manager_impl_test_api.cc',
'wm/test/window_manager_impl_test_api.h',
],
@@ -301,6 +305,7 @@
'input/input_manager_unittest.cc',
'resource_manager/memory_pressure_notifier_unittest.cc',
'resource_manager/resource_manager_unittest.cc',
+ 'screen/modal_window_controller_unittest.cc',
'screen/screen_manager_unittest.cc',
'test/base/athena_unittests.cc',
'util/drag_handle_unittest.cc',
diff --git a/athena/main/athena_launcher.cc b/athena/main/athena_launcher.cc
index 2634489..28059df 100644
--- a/athena/main/athena_launcher.cc
+++ b/athena/main/athena_launcher.cc
@@ -115,8 +115,8 @@ void StartAthenaEnv(scoped_refptr<base::TaskRunner> blocking_task_runner) {
athena::InputManager::Create()->OnRootWindowCreated(root_window);
athena::ScreenManager::Create(root_window);
- athena::SystemUI::Create(blocking_task_runner);
athena::WindowManager::Create();
+ athena::SystemUI::Create(blocking_task_runner);
athena::AppRegistry::Create();
SetupBackgroundImage();
@@ -166,8 +166,8 @@ void ShutdownAthena() {
session_started = false;
}
athena::AppRegistry::ShutDown();
- athena::WindowManager::Shutdown();
athena::SystemUI::Shutdown();
+ athena::WindowManager::Shutdown();
athena::ScreenManager::Shutdown();
athena::InputManager::Shutdown();
athena::AthenaEnv::Shutdown();
diff --git a/athena/screen/DEPS b/athena/screen/DEPS
index 1809145..423ee38 100644
--- a/athena/screen/DEPS
+++ b/athena/screen/DEPS
@@ -5,4 +5,7 @@ include_rules = [
"+ui/events",
"+ui/gfx",
"+ui/wm",
+ "+third_party/skia/include",
+ # for tests.
+ "+athena/athena_export.h",
]
diff --git a/athena/screen/modal_window_controller.cc b/athena/screen/modal_window_controller.cc
new file mode 100644
index 0000000..71a19ff
--- /dev/null
+++ b/athena/screen/modal_window_controller.cc
@@ -0,0 +1,146 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/screen/modal_window_controller.h"
+
+#include "athena/screen/public/screen_manager.h"
+#include "base/message_loop/message_loop.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/wm/core/window_animations.h"
+
+namespace athena {
+namespace {
+
+DEFINE_OWNED_WINDOW_PROPERTY_KEY(ModalWindowController,
+ kModalWindowControllerKey,
+ NULL);
+
+} // namespace
+
+// static
+ModalWindowController* ModalWindowController::Get(aura::Window* container) {
+ ModalWindowController* controller =
+ container->GetProperty(kModalWindowControllerKey);
+ CHECK(controller);
+ return controller;
+}
+
+ModalWindowController::ModalWindowController(int priority)
+ : modal_container_(NULL),
+ dimmer_window_(new aura::Window(NULL)),
+ dimmed_(false) {
+ ScreenManager::ContainerParams params("ModalContainer", priority);
+ params.can_activate_children = true;
+ params.block_events = true;
+ modal_container_ = ScreenManager::Get()->CreateContainer(params);
+ modal_container_->SetProperty(kModalWindowControllerKey, this);
+
+ dimmer_window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
+ dimmer_window_->Init(aura::WINDOW_LAYER_SOLID_COLOR);
+ dimmer_window_->layer()->SetColor(SK_ColorBLACK);
+ dimmer_window_->layer()->SetOpacity(0.0f);
+ dimmer_window_->Show();
+
+ modal_container_->AddChild(dimmer_window_);
+ modal_container_->AddObserver(this);
+
+ UpdateDimmerWindowBounds();
+}
+
+ModalWindowController::~ModalWindowController() {
+ if (modal_container_)
+ modal_container_->RemoveObserver(this);
+}
+
+void ModalWindowController::OnWindowAdded(aura::Window* child) {
+ DCHECK_NE(child, dimmer_window_);
+ if (IsChildWindow(child)) {
+ child->AddObserver(this);
+ UpdateDimming(NULL);
+ }
+}
+
+void ModalWindowController::OnWindowVisibilityChanged(aura::Window* window,
+ bool visible) {
+ if (IsChildWindow(window))
+ UpdateDimming(NULL);
+}
+
+void ModalWindowController::OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ if (window == modal_container_)
+ UpdateDimmerWindowBounds();
+}
+
+void ModalWindowController::OnWindowDestroyed(aura::Window* window) {
+ UpdateDimming(window);
+}
+
+bool ModalWindowController::IsChildWindow(aura::Window* child) const {
+ return child->parent() == modal_container_ && child != dimmer_window_;
+}
+
+void ModalWindowController::UpdateDimmerWindowBounds() {
+ gfx::Rect bounds(modal_container_->bounds().size());
+ dimmer_window_->SetBounds(bounds);
+}
+
+void ModalWindowController::UpdateDimming(aura::Window* ignore) {
+ if (!modal_container_ || !dimmer_window_)
+ return;
+ bool should_delete = true;
+ for (aura::Window* window : modal_container_->children()) {
+ if (window == dimmer_window_ || window == ignore)
+ continue;
+ should_delete = false;
+ if (window->TargetVisibility()) {
+ SetDimmed(true);
+ return;
+ }
+ }
+ SetDimmed(false);
+
+ if (should_delete) {
+ // Remove the container from root so that the container becomes
+ // invisible, but don't delete it until next event execution
+ // because the call stack may still have and use the pointer.
+ modal_container_->RemoveObserver(this);
+ modal_container_->parent()->RemoveChild(modal_container_);
+ base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE, modal_container_);
+ modal_container_ = NULL;
+ dimmer_window_ = NULL;
+ }
+}
+
+void ModalWindowController::SetDimmed(bool dimmed) {
+ const float kDimmedOpacity = 0.4f;
+
+ if (!dimmer_window_ || dimmed_ == dimmed)
+ return;
+ dimmed_ = dimmed;
+
+ const int kDimmAnimationDurationMs = 500;
+ if (dimmed) {
+ ui::ScopedLayerAnimationSettings settings(
+ dimmer_window_->layer()->GetAnimator());
+ settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs));
+ dimmer_window_->layer()->SetOpacity(kDimmedOpacity);
+ } else {
+ // ScopedHidingAnimationSettings will detach the animating and
+ // recreate layers for the container so that animation can continue
+ // even if the container is removed immediately.
+ wm::ScopedHidingAnimationSettings settings(modal_container_);
+ settings.layer_animation_settings()->SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kDimmAnimationDurationMs));
+ modal_container_->layer()->SetOpacity(0.0f);
+ }
+}
+
+} // namespace athena
diff --git a/athena/screen/modal_window_controller.h b/athena/screen/modal_window_controller.h
new file mode 100644
index 0000000..b4c7ec5
--- /dev/null
+++ b/athena/screen/modal_window_controller.h
@@ -0,0 +1,59 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_SCREEN_MODAL_WINDOW_CONTROLLER_H_
+#define ATHENA_SCREEN_MODAL_WINDOW_CONTROLLER_H_
+
+#include "athena/athena_export.h"
+#include "ui/aura/window_observer.h"
+
+namespace athena {
+
+// ModalWindow controller manages the modal window and
+// its container. This gets created when a modal window is opened
+// and deleted when all modal windows are deleted.
+class ATHENA_EXPORT ModalWindowController : public aura::WindowObserver {
+ public:
+ // Returns the ModalWindowController associated with the container.
+ static ModalWindowController* Get(aura::Window* container);
+
+ explicit ModalWindowController(int container_priority);
+ virtual ~ModalWindowController();
+
+ aura::Window* modal_container() { return modal_container_; }
+
+ bool dimmed() const { return dimmed_; }
+
+ private:
+ // aura::WindowObserver:
+ virtual void OnWindowAdded(aura::Window* child) override;
+ virtual void OnWindowVisibilityChanged(aura::Window* window,
+ bool visible) override;
+ virtual void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
+ virtual void OnWindowDestroyed(aura::Window* window) override;
+
+ // Tells if the child is not a dimmer window and a child of the modal
+ // container.
+ bool IsChildWindow(aura::Window* child) const;
+
+ void UpdateDimmerWindowBounds();
+
+ // Change dimming state based on the visible window in the container.
+ void UpdateDimming(aura::Window* ignore);
+
+ // Note: changing true -> false will delete the modal_container_.
+ void SetDimmed(bool dimmed);
+
+ aura::Window* modal_container_; // not owned.
+ aura::Window* dimmer_window_; // not owned.
+
+ bool dimmed_;
+ DISALLOW_COPY_AND_ASSIGN(ModalWindowController);
+};
+
+} // namespace athena
+
+#endif // ATHENA_SCREEN_MODAL_WINDOW_CONTROLLER_H_
diff --git a/athena/screen/modal_window_controller_unittest.cc b/athena/screen/modal_window_controller_unittest.cc
new file mode 100644
index 0000000..b73399a
--- /dev/null
+++ b/athena/screen/modal_window_controller_unittest.cc
@@ -0,0 +1,144 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/screen/modal_window_controller.h"
+#include "athena/screen/screen_manager_impl.h"
+#include "athena/test/base/athena_test_base.h"
+#include "athena/test/base/test_windows.h"
+#include "athena/util/container_priorities.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/window.h"
+
+namespace athena {
+
+typedef test::AthenaTestBase ModalWindowControllerTest;
+
+aura::Window* FindContainerByPriority(int priority) {
+ ScreenManagerImpl* screen_manager =
+ static_cast<ScreenManagerImpl*>(ScreenManager::Get());
+ return screen_manager->FindContainerByPriority(priority);
+}
+
+TEST_F(ModalWindowControllerTest, ModalContainer) {
+ aura::test::EventCountDelegate delegate;
+ scoped_ptr<aura::Window> modal(test::CreateTransientWindow(
+ &delegate, NULL, ui::MODAL_TYPE_SYSTEM, false));
+
+ aura::Window* modal_container = FindContainerByPriority(CP_SYSTEM_MODAL);
+ EXPECT_TRUE(modal_container);
+
+ ModalWindowController* modal_controller =
+ ModalWindowController::Get(modal_container);
+ ASSERT_TRUE(modal_controller);
+ EXPECT_EQ(modal_container, modal->parent());
+ EXPECT_FALSE(modal_controller->dimmed());
+ modal->Show();
+ EXPECT_TRUE(modal_controller->dimmed());
+
+ modal->Hide();
+ EXPECT_TRUE(FindContainerByPriority(CP_SYSTEM_MODAL));
+ EXPECT_FALSE(modal_controller->dimmed());
+
+ modal->Show();
+ EXPECT_TRUE(FindContainerByPriority(CP_SYSTEM_MODAL));
+ EXPECT_TRUE(modal_controller->dimmed());
+
+ modal.reset();
+ EXPECT_FALSE(FindContainerByPriority(CP_SYSTEM_MODAL));
+
+ // Create two.
+ modal = test::CreateTransientWindow(
+ &delegate, NULL, ui::MODAL_TYPE_SYSTEM, false).Pass();
+ scoped_ptr<aura::Window> modal2(test::CreateTransientWindow(
+ &delegate, NULL, ui::MODAL_TYPE_SYSTEM, false));
+
+ modal_container = FindContainerByPriority(CP_SYSTEM_MODAL);
+ EXPECT_TRUE(modal_container);
+ modal_controller = ModalWindowController::Get(modal_container);
+ ASSERT_TRUE(modal_controller);
+ EXPECT_EQ(modal_container, modal->parent());
+ EXPECT_EQ(modal_container, modal2->parent());
+
+ EXPECT_FALSE(modal_controller->dimmed());
+ modal->Show();
+ EXPECT_TRUE(modal_controller->dimmed());
+ modal2->Show();
+ EXPECT_TRUE(modal_controller->dimmed());
+
+ modal->Hide();
+ EXPECT_TRUE(modal_controller->dimmed());
+ modal2->Hide();
+ EXPECT_FALSE(modal_controller->dimmed());
+ EXPECT_TRUE(FindContainerByPriority(CP_SYSTEM_MODAL));
+
+ modal2.reset();
+ EXPECT_TRUE(FindContainerByPriority(CP_SYSTEM_MODAL));
+ EXPECT_FALSE(modal_controller->dimmed());
+
+ modal.reset();
+ EXPECT_FALSE(FindContainerByPriority(CP_SYSTEM_MODAL));
+}
+
+TEST_F(ModalWindowControllerTest, NestedModalWindows) {
+ ScreenManager::ContainerParams params("top", CP_END);
+ params.can_activate_children = true;
+ params.modal_container_priority = CP_END + 1;
+ aura::Window* top_container = ScreenManager::Get()->CreateContainer(params);
+
+ aura::test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> top_w1(
+ test::CreateNormalWindow(&delegate, top_container));
+ EXPECT_EQ(top_container, top_w1->parent());
+
+ aura::Window* default_container = FindContainerByPriority(CP_DEFAULT);
+ EXPECT_TRUE(default_container);
+
+ scoped_ptr<aura::Window> normal_w1(test::CreateNormalWindow(&delegate, NULL));
+ EXPECT_EQ(default_container, normal_w1->parent());
+
+ scoped_ptr<aura::Window> normal_m1(test::CreateTransientWindow(
+ &delegate, normal_w1.get(), ui::MODAL_TYPE_SYSTEM, false));
+ aura::Window* default_modal_container =
+ FindContainerByPriority(CP_SYSTEM_MODAL);
+ EXPECT_EQ(default_modal_container, normal_m1->parent());
+
+ // A modal window with the transient parent which doesn't specify
+ // the modal container should fallback the default container's modal
+ // container.
+ aura::Window* home_container = FindContainerByPriority(CP_DEFAULT);
+ EXPECT_TRUE(home_container);
+
+ scoped_ptr<aura::Window> normal_m2(test::CreateTransientWindow(
+ &delegate, home_container, ui::MODAL_TYPE_SYSTEM, false));
+ EXPECT_EQ(default_modal_container, normal_m2->parent());
+
+ // No modal container for top container yet.
+ EXPECT_FALSE(FindContainerByPriority(CP_END + 1));
+
+ // Creating a modal with always on top creates the modal dialog on top
+ // most dialog container.
+ scoped_ptr<aura::Window> top_m0(test::CreateTransientWindow(
+ &delegate, NULL, ui::MODAL_TYPE_SYSTEM, true));
+
+ aura::Window* top_modal_container = FindContainerByPriority(CP_END + 1);
+ EXPECT_EQ(top_modal_container, top_m0->parent());
+
+ // Creating a modal dialog with transient parent on the top container
+ // creates the winodw on the top container's modal container.
+ scoped_ptr<aura::Window> top_m1(test::CreateTransientWindow(
+ &delegate, top_w1.get(), ui::MODAL_TYPE_SYSTEM, true));
+ EXPECT_EQ(top_modal_container, top_m1->parent());
+
+ normal_m1.reset();
+ EXPECT_TRUE(FindContainerByPriority(CP_SYSTEM_MODAL));
+ normal_m2.reset();
+ EXPECT_FALSE(FindContainerByPriority(CP_SYSTEM_MODAL));
+
+ top_m0.reset();
+ EXPECT_TRUE(FindContainerByPriority(CP_END + 1));
+ top_m1.reset();
+ EXPECT_FALSE(FindContainerByPriority(CP_END + 1));
+}
+
+} // namespace athena
diff --git a/athena/screen/public/screen_manager.h b/athena/screen/public/screen_manager.h
index e263782..11dda1f 100644
--- a/athena/screen/public/screen_manager.h
+++ b/athena/screen/public/screen_manager.h
@@ -29,11 +29,37 @@ class ATHENA_EXPORT ScreenManager {
// True if the container can activate its child window.
bool can_activate_children;
- // True if the container will grab all of input events.
- bool grab_inputs;
+ // True if the container will block evnets from containers behind it.
+ bool block_events;
// Defines the z_order priority of the container.
int z_order_priority;
+
+ // True if this container should be used as a default parent.
+ bool default_parent;
+
+ // The container priority used to open modal dialog window
+ // created with this container as a transient parent (Note: A modal window
+ // should
+ // use a trnasient parent, not a direct parent, or no transient parent.)
+ //
+ // Default is -1, and it will fallback to the container behind this
+ // container,
+ // that has the modal container proiroty.
+ //
+ // The modal container for modal window is selected as follows.
+ // 1) a window must be created with |aura::client::kModalKey| property
+ // without explicit parent set.
+ // 2.a) If aura::client::kAlwaysOnTopKey is NOT set, it uses the stand flow
+ // described above. (fallback to containers behind this).
+ // 2.b) If aura::client::kAlwaysOnTopKey is set, it searches the top most
+ // container which has |modal_container_priority| != -1.
+ // 3) Look for the container with |modal_container_priority|, and create
+ // one if it doesn't exist.
+ //
+ // Created modal container will self destruct if last modal window
+ // is deleted.
+ int modal_container_priority;
};
// Creates, returns and deletes the singleton object of the ScreenManager
@@ -44,11 +70,6 @@ class ATHENA_EXPORT ScreenManager {
virtual ~ScreenManager() {}
- // Creates the container window that is used when creating a normal
- // widget without specific parent.
- virtual aura::Window* CreateDefaultContainer(
- const ContainerParams& params) = 0;
-
// Creates the container window on the screen.
virtual aura::Window* CreateContainer(const ContainerParams& params) = 0;
diff --git a/athena/screen/screen_accelerator_handler.h b/athena/screen/screen_accelerator_handler.h
index ab57879..fcde448 100644
--- a/athena/screen/screen_accelerator_handler.h
+++ b/athena/screen/screen_accelerator_handler.h
@@ -1,6 +1,8 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef ATHENA_SCREEN_SCREEN_ACCELERATOR_HANDLER_H_
+#define ATHENA_SCREEN_SCREEN_ACCELERATOR_HANDLER_H_
#include "athena/input/public/accelerator_manager.h"
@@ -31,3 +33,5 @@ class ScreenAcceleratorHandler : public AcceleratorHandler {
};
} // namespace athena
+
+#endif // ATHENA_SCREEN_SCREEN_ACCELERATOR_HANDLER_H_
diff --git a/athena/screen/screen_manager_impl.cc b/athena/screen/screen_manager_impl.cc
index 3ece198..5182b7e 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
diff --git a/athena/screen/screen_manager_impl.h b/athena/screen/screen_manager_impl.h
new file mode 100644
index 0000000..1738542
--- /dev/null
+++ b/athena/screen/screen_manager_impl.h
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_SCREEN_SCREEN_MANAGER_IMPL_H_
+#define ATHENA_SCREEN_SCREEN_MANAGER_IMPL_H_
+
+#include "athena/athena_export.h"
+#include "athena/screen/public/screen_manager.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/client/window_tree_client.h"
+
+namespace aura {
+namespace client {
+class FocusClient;
+class ScreenPositionClient;
+}
+}
+
+namespace wm {
+class ScopedCaptureClient;
+}
+
+namespace athena {
+class AcceleratorHandler;
+
+class ATHENA_EXPORT ScreenManagerImpl : public ScreenManager,
+ public aura::client::WindowTreeClient {
+ public:
+ explicit ScreenManagerImpl(aura::Window* root_window);
+ virtual ~ScreenManagerImpl();
+
+ void Init();
+
+ // Returns a container which has |priority|. Null if such container
+ // doesn't exist.
+ aura::Window* FindContainerByPriority(int priority);
+
+ private:
+ // ScreenManager:
+ virtual aura::Window* CreateContainer(const ContainerParams& params) override;
+ virtual aura::Window* GetContext() override;
+ virtual void SetRotation(gfx::Display::Rotation rotation) override;
+ virtual void SetRotationLocked(bool rotation_locked) override;
+
+ // aura::client::WindowTreeClient:
+ virtual aura::Window* GetDefaultParent(aura::Window* context,
+ aura::Window* window,
+ const gfx::Rect& bounds) override;
+
+ int GetModalContainerPriority(aura::Window* window, aura::Window* parent);
+
+ // Returns a container with |params.default_parent| == true.
+ aura::Window* GetDefaultContainer();
+
+ // Not owned.
+ aura::Window* root_window_;
+
+ scoped_ptr<aura::client::FocusClient> focus_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);
+};
+
+} // namespace athena
+
+#endif // ATHENA_SCREEN_SCREEN_MANAGER_IMPL_H_
diff --git a/athena/screen/screen_manager_unittest.cc b/athena/screen/screen_manager_unittest.cc
index ed8b248..c8787da 100644
--- a/athena/screen/screen_manager_unittest.cc
+++ b/athena/screen/screen_manager_unittest.cc
@@ -2,15 +2,16 @@
// 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 <algorithm>
#include <string>
+#include "athena/screen/screen_manager_impl.h"
#include "athena/test/base/athena_test_base.h"
+#include "athena/test/base/test_windows.h"
#include "athena/util/container_priorities.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_targeter.h"
#include "ui/events/test/event_generator.h"
#include "ui/wm/core/window_util.h"
@@ -111,12 +112,83 @@ TEST_F(ScreenManagerTest, NonActivatableContainer) {
EXPECT_TRUE(wm::CanActivateWindow(window.get()));
}
-TEST_F(ScreenManagerTest, GrabInputContainer) {
+TEST_F(ScreenManagerTest, BlockInputsShouldNotBlockVirtualKeyboard) {
+ ScreenManager::ContainerParams block_params("blocking", kTestZOrderPriority);
+ block_params.can_activate_children = true;
+ block_params.block_events = true;
+ aura::Window* block_container =
+ ScreenManager::Get()->CreateContainer(block_params);
+
+ aura::test::EventCountDelegate block_delegate;
+ scoped_ptr<aura::Window> block_window(CreateWindow(
+ block_container, &block_delegate, gfx::Rect(0, 0, 100, 100)));
+ EXPECT_TRUE(wm::CanActivateWindow(block_window.get()));
+
+ // Create a normal container appearing over the |block_container|. This is
+ // essentially the case of virtual keyboard.
+ ScreenManager::ContainerParams vk_params("virtual keyboard",
+ kTestZOrderPriority + 1);
+ vk_params.can_activate_children = true;
+ aura::Window* vk_container = ScreenManager::Get()->CreateContainer(vk_params);
+
+ aura::test::EventCountDelegate vk_delegate;
+ scoped_ptr<aura::Window> vk_window(
+ CreateWindow(vk_container, &vk_delegate, gfx::Rect(0, 20, 100, 80)));
+ EXPECT_TRUE(wm::CanActivateWindow(vk_window.get()));
+
+ ui::test::EventGenerator event_generator(root_window());
+ event_generator.MoveMouseTo(10, 25);
+ event_generator.ClickLeftButton();
+ EXPECT_EQ("0 0", block_delegate.GetMouseButtonCountsAndReset());
+ EXPECT_EQ("1 1", vk_delegate.GetMouseButtonCountsAndReset());
+}
+
+TEST_F(ScreenManagerTest, DefaultContainer) {
+ ScreenManagerImpl* impl =
+ static_cast<ScreenManagerImpl*>(ScreenManager::Get());
+ aura::Window* original_default = impl->FindContainerByPriority(CP_DEFAULT);
+ aura::Window* parent = original_default->parent();
+ // Temporarily remove the original default container from tree.
+ parent->RemoveChild(original_default);
+
+ ScreenManager::ContainerParams params("new_default", CP_END + 1);
+ params.default_parent = true;
+ params.modal_container_priority = CP_END + 2;
+ aura::Window* new_default = ScreenManager::Get()->CreateContainer(params);
+ aura::Window* w = test::CreateNormalWindow(NULL, NULL).release();
+ EXPECT_EQ(new_default, w->parent());
+ delete new_default;
+
+ // Add the original back to shutdown properly.
+ parent->AddChild(original_default);
+}
+
+namespace {
+
+class ScreenManagerTargeterTest
+ : public athena::test::AthenaTestBase,
+ public testing::WithParamInterface<bool> {
+ public:
+ ScreenManagerTargeterTest()
+ : targeter_(GetParam() ? NULL : new aura::WindowTargeter) {}
+ virtual ~ScreenManagerTargeterTest() {}
+
+ protected:
+ scoped_ptr<ui::EventTargeter> targeter_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenManagerTargeterTest);
+};
+
+} // namespace
+
+TEST_P(ScreenManagerTargeterTest, BlockContainer) {
ScreenManager::ContainerParams normal_params(
"normal", kTestZOrderPriority);
normal_params.can_activate_children = true;
aura::Window* normal_container =
ScreenManager::Get()->CreateContainer(normal_params);
+ normal_container->SetEventTargeter(targeter_.Pass());
aura::test::EventCountDelegate normal_delegate;
scoped_ptr<aura::Window> normal_window(CreateWindow(
@@ -132,76 +204,48 @@ TEST_F(ScreenManagerTest, GrabInputContainer) {
event_generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE);
EXPECT_EQ("1 1", normal_delegate.GetKeyCountsAndReset());
- ScreenManager::ContainerParams grab_params(
- "grabbing", kTestZOrderPriority + 1);
- grab_params.can_activate_children = true;
- grab_params.grab_inputs = true;
- aura::Window* grab_container =
- ScreenManager::Get()->CreateContainer(grab_params);
+ ScreenManager::ContainerParams block_params("blocking",
+ kTestZOrderPriority + 1);
+ block_params.can_activate_children = true;
+ block_params.block_events = true;
+ aura::Window* block_container =
+ ScreenManager::Get()->CreateContainer(block_params);
EXPECT_FALSE(wm::CanActivateWindow(normal_window.get()));
- aura::test::EventCountDelegate grab_delegate;
- scoped_ptr<aura::Window> grab_window(CreateWindow(
- grab_container, &grab_delegate, gfx::Rect(10, 10, 100, 100)));
- EXPECT_TRUE(wm::CanActivateWindow(grab_window.get()));
+ aura::test::EventCountDelegate block_delegate;
+ scoped_ptr<aura::Window> block_window(CreateWindow(
+ block_container, &block_delegate, gfx::Rect(10, 10, 100, 100)));
+ EXPECT_TRUE(wm::CanActivateWindow(block_window.get()));
- wm::ActivateWindow(grab_window.get());
+ wm::ActivateWindow(block_window.get());
// (0, 0) is still on normal_window, but the event should not go there
- // because grabbing_container prevents it.
+ // because blockbing_container prevents it.
event_generator.MoveMouseTo(0, 0);
event_generator.ClickLeftButton();
EXPECT_EQ("0 0", normal_delegate.GetMouseButtonCountsAndReset());
- EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
+ EXPECT_EQ("0 0", block_delegate.GetMouseButtonCountsAndReset());
+ event_generator.MoveMouseWheel(0, 10);
+ // EXPECT_EQ(0, normal_event_counter.num_scroll_events());
event_generator.MoveMouseTo(20, 20);
event_generator.ClickLeftButton();
- EXPECT_EQ("1 1", grab_delegate.GetMouseButtonCountsAndReset());
+ EXPECT_EQ("1 1", block_delegate.GetMouseButtonCountsAndReset());
event_generator.PressKey(ui::VKEY_A, ui::EF_NONE);
event_generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE);
EXPECT_EQ("0 0", normal_delegate.GetKeyCountsAndReset());
- EXPECT_EQ("1 1", grab_delegate.GetKeyCountsAndReset());
-}
-
-TEST_F(ScreenManagerTest, GrabShouldNotBlockVirtualKeyboard) {
- ScreenManager::ContainerParams grab_params("grabbing", kTestZOrderPriority);
- grab_params.can_activate_children = true;
- grab_params.grab_inputs = true;
- aura::Window* grab_container =
- ScreenManager::Get()->CreateContainer(grab_params);
-
- aura::test::EventCountDelegate grab_delegate;
- scoped_ptr<aura::Window> grab_window(
- CreateWindow(grab_container, &grab_delegate, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(wm::CanActivateWindow(grab_window.get()));
-
- // Create a normal container appearing over the |grab_container|. This is
- // essentially the case of virtual keyboard.
- ScreenManager::ContainerParams vk_params(
- "virtual keyboard", kTestZOrderPriority + 1);
- vk_params.can_activate_children = true;
- aura::Window* vk_container = ScreenManager::Get()->CreateContainer(vk_params);
-
- aura::test::EventCountDelegate vk_delegate;
- scoped_ptr<aura::Window> vk_window(
- CreateWindow(vk_container, &vk_delegate, gfx::Rect(0, 20, 100, 80)));
- EXPECT_TRUE(wm::CanActivateWindow(vk_window.get()));
-
- ui::test::EventGenerator event_generator(root_window());
- event_generator.MoveMouseTo(10, 25);
- event_generator.ClickLeftButton();
- EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
- EXPECT_EQ("1 1", vk_delegate.GetMouseButtonCountsAndReset());
+ EXPECT_EQ("1 1", block_delegate.GetKeyCountsAndReset());
}
-TEST_F(ScreenManagerTest, GrabAndMouseCapture) {
+TEST_P(ScreenManagerTargeterTest, BlockAndMouseCapture) {
ScreenManager::ContainerParams normal_params(
"normal", kTestZOrderPriority);
normal_params.can_activate_children = true;
aura::Window* normal_container =
ScreenManager::Get()->CreateContainer(normal_params);
+ normal_container->SetEventTargeter(targeter_.Pass());
aura::test::EventCountDelegate normal_delegate;
scoped_ptr<aura::Window> normal_window(CreateWindow(
@@ -211,29 +255,33 @@ TEST_F(ScreenManagerTest, GrabAndMouseCapture) {
event_generator.MoveMouseTo(0, 0);
event_generator.PressLeftButton();
- // Creating grabbing container while mouse pressing.
- ScreenManager::ContainerParams grab_params(
- "grabbing", kTestZOrderPriority + 1);
- grab_params.can_activate_children = true;
- grab_params.grab_inputs = true;
- aura::Window* grab_container =
- ScreenManager::Get()->CreateContainer(grab_params);
+ // Creating blocking container while mouse pressing.
+ ScreenManager::ContainerParams block_params("blocking",
+ kTestZOrderPriority + 1);
+ block_params.can_activate_children = true;
+ block_params.block_events = true;
+ aura::Window* block_container =
+ ScreenManager::Get()->CreateContainer(block_params);
- aura::test::EventCountDelegate grab_delegate;
- scoped_ptr<aura::Window> grab_window(CreateWindow(
- grab_container, &grab_delegate, gfx::Rect(10, 10, 100, 100)));
+ aura::test::EventCountDelegate block_delegate;
+ scoped_ptr<aura::Window> block_window(CreateWindow(
+ block_container, &block_delegate, gfx::Rect(10, 10, 100, 100)));
// Release event should be sent to |normal_window| because it captures the
// mouse event.
event_generator.ReleaseLeftButton();
EXPECT_EQ("1 1", normal_delegate.GetMouseButtonCountsAndReset());
- EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
+ EXPECT_EQ("0 0", block_delegate.GetMouseButtonCountsAndReset());
// After release, further mouse events should not be sent to |normal_window|
- // because grab_container grabs the input.
+ // because block_container blocks the input.
event_generator.ClickLeftButton();
EXPECT_EQ("0 0", normal_delegate.GetMouseButtonCountsAndReset());
- EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
+ EXPECT_EQ("0 0", block_delegate.GetMouseButtonCountsAndReset());
}
+INSTANTIATE_TEST_CASE_P(WithOrWithoutTargeter,
+ ScreenManagerTargeterTest,
+ testing::Values(false, true));
+
} // namespace athena
diff --git a/athena/system/network_selector.cc b/athena/system/network_selector.cc
index 7519968..ef45bfb 100644
--- a/athena/system/network_selector.cc
+++ b/athena/system/network_selector.cc
@@ -4,6 +4,7 @@
#include "athena/system/network_selector.h"
+#include "athena/screen/public/screen_manager.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/network/network_configuration_handler.h"
@@ -38,6 +39,7 @@
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
+#include "ui/views/window/dialog_delegate.h"
using chromeos::NetworkConfigurationHandler;
using chromeos::NetworkConnectionHandler;
@@ -47,18 +49,14 @@ using chromeos::NetworkState;
namespace {
-const int kBackgroundColor = SkColorSetARGB(0x7f, 0, 0, 0);
-
// The View for the user to enter the password for connceting to a network. This
// view also shows an error message if the network connection fails.
class PasswordView : public views::View, public views::ButtonListener {
public:
PasswordView(const ui::NetworkInfo& network,
- const base::Callback<void(bool)>& callback,
- views::View* parent_container)
+ const base::Callback<void(bool)>& callback)
: network_(network),
callback_(callback),
- parent_container_(parent_container),
connect_(NULL),
cancel_(NULL),
textfield_(NULL),
@@ -102,7 +100,7 @@ class PasswordView : public views::View, public views::ButtonListener {
virtual ~PasswordView() {}
private:
- void Close(bool successful) { callback_.Run(successful); }
+ void CloseDialog(bool successful) { callback_.Run(successful); }
void OnKnownError(const std::string& error_name,
scoped_ptr<base::DictionaryValue> error_data) {
@@ -122,7 +120,7 @@ class PasswordView : public views::View, public views::ButtonListener {
if (!error_msg_->parent()) {
AddChildView(error_msg_);
InvalidateLayout();
- parent_container_->Layout();
+ GetWidget()->GetRootView()->Layout();
ScrollRectToVisible(error_msg_->bounds());
}
connect_->SetEnabled(true);
@@ -149,7 +147,7 @@ class PasswordView : public views::View, public views::ButtonListener {
check_error_state);
}
- void OnConnectionSucceed() { Close(true); }
+ void OnConnectionSucceed() { CloseDialog(true); }
// views::View:
virtual void ViewHierarchyChanged(
@@ -176,7 +174,7 @@ class PasswordView : public views::View, public views::ButtonListener {
textfield_->text()),
base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()));
} else if (sender == cancel_) {
- Close(false);
+ CloseDialog(false);
} else {
NOTREACHED();
}
@@ -184,7 +182,6 @@ class PasswordView : public views::View, public views::ButtonListener {
ui::NetworkInfo network_;
base::Callback<void(bool)> callback_;
- views::View* parent_container_;
views::BlueButton* connect_;
views::LabelButton* cancel_;
@@ -199,8 +196,8 @@ class PasswordView : public views::View, public views::ButtonListener {
// contains the View for taking password for password-protected networks.
class NetworkRow : public views::View {
public:
- NetworkRow(const ui::NetworkInfo& network, views::View* container)
- : network_(network), container_(container), weak_ptr_(this) {
+ NetworkRow(const ui::NetworkInfo& network)
+ : network_(network), weak_ptr_(this) {
SetBorder(views::Border::CreateEmptyBorder(10, 5, 10, 5));
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 10));
@@ -230,7 +227,7 @@ class NetworkRow : public views::View {
void OnPasswordComplete(bool successful) {
password_view_.reset();
InvalidateLayout();
- container_->Layout();
+ GetWidget()->GetRootView()->Layout();
ScrollRectToVisible(GetContentsBounds());
}
@@ -249,12 +246,11 @@ class NetworkRow : public views::View {
password_view_.reset(new PasswordView(
network_,
- base::Bind(&NetworkRow::OnPasswordComplete, weak_ptr_.GetWeakPtr()),
- container_));
+ base::Bind(&NetworkRow::OnPasswordComplete, weak_ptr_.GetWeakPtr())));
password_view_->set_owned_by_client();
AddChildView(password_view_.get());
PreferredSizeChanged();
- container_->Layout();
+ GetWidget()->GetRootView()->Layout();
ScrollRectToVisible(password_view_->bounds());
}
@@ -310,7 +306,6 @@ class NetworkRow : public views::View {
}
ui::NetworkInfo network_;
- views::View* container_;
scoped_ptr<views::View> password_view_;
base::WeakPtrFactory<NetworkRow> weak_ptr_;
@@ -319,15 +314,12 @@ class NetworkRow : public views::View {
class NetworkSelector : public ui::NetworkListDelegate,
public chromeos::NetworkStateHandlerObserver,
- public ui::EventHandler {
+ public views::DialogDelegate {
public:
- explicit NetworkSelector(aura::Window* container)
- : background_view_(NULL),
- scroll_content_(NULL),
- scroller_(NULL),
- network_list_(this) {
- CreateWidget(container);
+ NetworkSelector()
+ : scroll_content_(NULL), scroller_(NULL), network_list_(this) {
CreateNetworkList();
+ CreateWidget();
NetworkHandler::Get()->network_state_handler()->RequestScan();
NetworkHandler::Get()->network_state_handler()->AddObserver(this,
@@ -340,36 +332,19 @@ class NetworkSelector : public ui::NetworkListDelegate,
}
private:
- void CreateWidget(aura::Window* container) {
- views::Widget::InitParams params;
- params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
- params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
- params.activatable = views::Widget::InitParams::ACTIVATABLE_DEFAULT;
- params.accept_events = true;
- params.bounds = gfx::Rect(container->bounds().size());
- params.parent = container;
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget_.reset(new views::Widget());
- widget_->Init(params);
- widget_->Show();
-
- background_view_ = new views::View;
- background_view_->set_background(
- views::Background::CreateSolidBackground(kBackgroundColor));
- background_view_->SetBorder(
- views::Border::CreateEmptyBorder(100, 300, 300, 300));
- background_view_->SetLayoutManager(new views::FillLayout());
- background_view_->set_target_handler(this);
-
- widget_->SetContentsView(background_view_);
+ void CreateWidget() {
+ // Same as CreateDialogWidgetWithBounds() with an empty |bounds|.
+ views::Widget* widget = views::DialogDelegate::CreateDialogWidget(
+ this, athena::ScreenManager::Get()->GetContext(), NULL);
+ widget->Show();
+ widget->CenterWindow(gfx::Size(400, 400));
}
void CreateNetworkList() {
- const int kListHeight = 500;
+ const int kListHeight = 400;
scroller_ = new views::ScrollView();
scroller_->set_background(
views::Background::CreateSolidBackground(SK_ColorWHITE));
- scroller_->SetBounds(0, 0, 400, kListHeight);
scroll_content_ = new views::View;
scroll_content_->SetLayoutManager(
@@ -378,21 +353,16 @@ class NetworkSelector : public ui::NetworkListDelegate,
scroller_->ClipHeightTo(kListHeight, kListHeight);
scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
- background_view_->AddChildView(scroller_);
-
- background_view_->Layout();
network_list_.set_content_view(scroll_content_);
}
void UpdateNetworkList() { network_list_.UpdateNetworkList(); }
- void Close() { delete this; }
-
// ui::NetworkListDelegate:
virtual views::View* CreateViewForNetwork(
const ui::NetworkInfo& info) override {
- return new NetworkRow(info, background_view_);
+ return new NetworkRow(info);
}
virtual bool IsViewHovered(views::View* view) override {
@@ -429,25 +399,19 @@ class NetworkSelector : public ui::NetworkListDelegate,
virtual void NetworkPropertiesUpdated(
const chromeos::NetworkState* network) override {}
- // ui::EventHandler:
- virtual void OnMouseEvent(ui::MouseEvent* mouse) override {
- CHECK_EQ(background_view_, mouse->target());
- if (mouse->type() == ui::ET_MOUSE_PRESSED && !mouse->handled()) {
- Close();
- mouse->SetHandled();
- }
+ // views::DialogDelegate:
+ virtual ui::ModalType GetModalType() const override {
+ return ui::MODAL_TYPE_SYSTEM;
}
-
- virtual void OnGestureEvent(ui::GestureEvent* gesture) override {
- CHECK_EQ(background_view_, gesture->target());
- if (gesture->type() == ui::ET_GESTURE_TAP && !gesture->handled()) {
- Close();
- gesture->SetHandled();
- }
+ virtual void DeleteDelegate() override { delete this; }
+ virtual views::Widget* GetWidget() override { return scroller_->GetWidget(); }
+ virtual const views::Widget* GetWidget() const override {
+ return scroller_->GetWidget();
}
+ virtual views::View* GetContentsView() override { return scroller_; }
+ virtual int GetDialogButtons() const override { return ui::DIALOG_BUTTON_OK; }
+ virtual bool Close() override { return true; }
- scoped_ptr<views::Widget> widget_;
- views::View* background_view_;
views::View* scroll_content_;
views::ScrollView* scroller_;
@@ -462,8 +426,8 @@ class NetworkSelector : public ui::NetworkListDelegate,
namespace athena {
-void CreateNetworkSelector(aura::Window* container) {
- new NetworkSelector(container);
+void CreateNetworkSelector() {
+ new NetworkSelector();
}
} // namespace athena
diff --git a/athena/system/network_selector.h b/athena/system/network_selector.h
index 90aaf7f..01cf94b 100644
--- a/athena/system/network_selector.h
+++ b/athena/system/network_selector.h
@@ -5,13 +5,9 @@
#ifndef ATHENA_SYSTEM_NETWORK_SELECTOR_H_
#define ATHENA_SYSTEM_NETWORK_SELECTOR_H_
-namespace aura {
-class Window;
-}
-
namespace athena {
-void CreateNetworkSelector(aura::Window* window);
+void CreateNetworkSelector();
} // namespace athena
diff --git a/athena/system/shutdown_dialog.cc b/athena/system/shutdown_dialog.cc
index 865349e..d4648d7e 100644
--- a/athena/system/shutdown_dialog.cc
+++ b/athena/system/shutdown_dialog.cc
@@ -15,6 +15,7 @@
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
+#include "ui/views/window/dialog_delegate.h"
namespace athena {
namespace {
@@ -23,10 +24,33 @@ namespace {
// device after shutdown dialog is shown.
const int kShutdownTimeoutMs = 4000;
+class ModalWidgetDelegate : public views::WidgetDelegate {
+ public:
+ explicit ModalWidgetDelegate(views::View* contents_view)
+ : contents_view_(contents_view) {}
+ virtual ~ModalWidgetDelegate() {}
+
+ // Overridden from WidgetDelegate:
+ virtual views::Widget* GetWidget() override {
+ return contents_view_->GetWidget();
+ }
+ virtual const views::Widget* GetWidget() const override {
+ return contents_view_->GetWidget();
+ }
+ virtual views::View* GetContentsView() override { return contents_view_; }
+ virtual ui::ModalType GetModalType() const override {
+ return ui::MODAL_TYPE_SYSTEM;
+ }
+
+ private:
+ views::View* contents_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate);
+};
+
} // namespace
-ShutdownDialog::ShutdownDialog(aura::Window* dialog_container)
- : warning_message_container_(dialog_container), state_(STATE_OTHER) {
+ShutdownDialog::ShutdownDialog() : state_(STATE_OTHER) {
InputManager::Get()->AddPowerButtonObserver(this);
}
@@ -37,13 +61,6 @@ ShutdownDialog::~ShutdownDialog() {
void ShutdownDialog::ShowShutdownWarningDialog() {
state_ = STATE_SHUTDOWN_WARNING_VISIBLE;
- shutdown_warning_message_.reset(new views::Widget);
-
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = warning_message_container_;
- shutdown_warning_message_->Init(params);
-
views::Label* label =
new views::Label(l10n_util::GetStringUTF16(IDS_ATHENA_SHUTDOWN_WARNING));
label->SetBackgroundColor(SK_ColorWHITE);
@@ -59,9 +76,18 @@ void ShutdownDialog::ShowShutdownWarningDialog() {
views::Background::CreateSolidBackground(SK_ColorWHITE));
container->SetBorder(views::Border::CreateSolidBorder(1, SK_ColorBLACK));
- shutdown_warning_message_->SetContentsView(container);
- shutdown_warning_message_->CenterWindow(container->GetPreferredSize());
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
+ params.delegate = new ModalWidgetDelegate(container);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.context = ScreenManager::Get()->GetContext();
+ // Use top most modal container.
+ params.keep_on_top = true;
+
+ shutdown_warning_message_.reset(new views::Widget);
+ shutdown_warning_message_->Init(params);
shutdown_warning_message_->Show();
+ shutdown_warning_message_->CenterWindow(container->GetPreferredSize());
+
timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
this,
diff --git a/athena/system/shutdown_dialog.h b/athena/system/shutdown_dialog.h
index bda5add..fb8d168 100644
--- a/athena/system/shutdown_dialog.h
+++ b/athena/system/shutdown_dialog.h
@@ -23,7 +23,7 @@ namespace athena {
// Shuts down in response to the power button being pressed.
class ShutdownDialog : public PowerButtonObserver {
public:
- explicit ShutdownDialog(aura::Window* dialog_container);
+ explicit ShutdownDialog();
virtual ~ShutdownDialog();
private:
diff --git a/athena/system/status_icon_container_view.cc b/athena/system/status_icon_container_view.cc
index 811c645c..a7c5f85 100644
--- a/athena/system/status_icon_container_view.cc
+++ b/athena/system/status_icon_container_view.cc
@@ -208,9 +208,7 @@ class StatusIconContainerView::UpdateStatus
};
StatusIconContainerView::StatusIconContainerView(
- SystemUI::ColorScheme color_scheme,
- aura::Window* system_modal_container)
- : system_modal_container_(system_modal_container) {
+ SystemUI::ColorScheme color_scheme) {
const int kHorizontalSpacing = 10;
const int kVerticalSpacing = 3;
const int kBetweenChildSpacing = 10;
@@ -241,13 +239,13 @@ StatusIconContainerView::~StatusIconContainerView() {
}
bool StatusIconContainerView::OnMousePressed(const ui::MouseEvent& event) {
- CreateNetworkSelector(system_modal_container_);
+ CreateNetworkSelector();
return true;
}
void StatusIconContainerView::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP) {
- CreateNetworkSelector(system_modal_container_);
+ CreateNetworkSelector();
event->SetHandled();
}
}
diff --git a/athena/system/status_icon_container_view.h b/athena/system/status_icon_container_view.h
index ec60488..6e77b49 100644
--- a/athena/system/status_icon_container_view.h
+++ b/athena/system/status_icon_container_view.h
@@ -9,17 +9,12 @@
#include "base/memory/scoped_ptr.h"
#include "ui/views/view.h"
-namespace aura {
-class Window;
-}
-
namespace athena {
// View which displays the system tray icons.
class StatusIconContainerView : public views::View {
public:
- StatusIconContainerView(SystemUI::ColorScheme color_scheme,
- aura::Window* popup_container);
+ StatusIconContainerView(SystemUI::ColorScheme color_scheme);
virtual ~StatusIconContainerView();
private:
@@ -28,9 +23,6 @@ class StatusIconContainerView : public views::View {
virtual void OnGestureEvent(ui::GestureEvent* event) override;
virtual void ChildPreferredSizeChanged(views::View* child) override;
- // Parent container that the "select network" dialog should use.
- aura::Window* system_modal_container_;
-
class PowerStatus;
scoped_ptr<PowerStatus> power_status_;
diff --git a/athena/system/system_ui_impl.cc b/athena/system/system_ui_impl.cc
index 353a45b..64653ba 100644
--- a/athena/system/system_ui_impl.cc
+++ b/athena/system/system_ui_impl.cc
@@ -27,11 +27,9 @@ SystemUI* instance = NULL;
// right.
class SystemInfoView : public views::View {
public:
- SystemInfoView(SystemUI::ColorScheme color_scheme,
- aura::Window* system_modal_container)
+ SystemInfoView(SystemUI::ColorScheme color_scheme)
: time_view_(new TimeView(color_scheme)),
- status_icon_view_(
- new StatusIconContainerView(color_scheme, system_modal_container)) {
+ status_icon_view_(new StatusIconContainerView(color_scheme)) {
AddChildView(time_view_);
AddChildView(status_icon_view_);
}
@@ -76,8 +74,7 @@ class SystemUIImpl : public SystemUI {
public:
SystemUIImpl(scoped_refptr<base::TaskRunner> blocking_task_runner)
: orientation_controller_(new OrientationController()),
- background_container_(NULL),
- system_modal_container_(NULL) {
+ background_container_(NULL) {
orientation_controller_->InitWith(blocking_task_runner);
}
@@ -93,34 +90,22 @@ class SystemUIImpl : public SystemUI {
ScreenManager::ContainerParams("AthenaBackground", CP_BACKGROUND));
background_container_->SetLayoutManager(
new FillLayoutManager(background_container_));
- ScreenManager::ContainerParams system_modal_params(
- "AthenaSystemModalContainer", CP_SYSTEM_MODAL);
- system_modal_params.can_activate_children = true;
- system_modal_container_ =
- screen_manager->CreateContainer(system_modal_params);
- login_screen_system_modal_container_ = screen_manager->CreateContainer(
- ScreenManager::ContainerParams("AthenaLoginScreenSystemModalContainer",
- CP_LOGIN_SCREEN_SYSTEM_MODAL));
-
- // Use |login_screen_system_modal_container_| for the power button's dialog
- // because it needs to show over the login screen.
- // TODO(pkotwicz): Pick the most appropriate container based on whether the
- // user has logged in.
- shutdown_dialog_.reset(
- new ShutdownDialog(login_screen_system_modal_container_));
+
+ shutdown_dialog_.reset(new ShutdownDialog());
background_controller_.reset(
new BackgroundController(background_container_));
}
+ private:
+ // SystemUI:
virtual void SetBackgroundImage(const gfx::ImageSkia& image) override {
background_controller_->SetImage(image);
}
virtual views::View* CreateSystemInfoView(ColorScheme color_scheme) override {
- return new SystemInfoView(color_scheme, system_modal_container_);
+ return new SystemInfoView(color_scheme);
}
- private:
scoped_ptr<OrientationController> orientation_controller_;
scoped_ptr<ShutdownDialog> shutdown_dialog_;
scoped_ptr<BackgroundController> background_controller_;
diff --git a/athena/test/DEPS b/athena/test/DEPS
index 9fc07db..39df6ee 100644
--- a/athena/test/DEPS
+++ b/athena/test/DEPS
@@ -16,6 +16,6 @@ include_rules = [
"+ui/gfx",
"+ui/gl",
"+ui/views",
- "+ui/wm/core",
+ "+ui/wm",
]
diff --git a/athena/test/base/athena_test_base.cc b/athena/test/base/athena_test_base.cc
index a6f88b1..180baea 100644
--- a/athena/test/base/athena_test_base.cc
+++ b/athena/test/base/athena_test_base.cc
@@ -5,11 +5,8 @@
#include "athena/test/base/athena_test_base.h"
#include "athena/env/public/athena_env.h"
-#include "athena/screen/public/screen_manager.h"
#include "athena/test/base/athena_test_helper.h"
-#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/test/event_generator_delegate_aura.h"
-#include "ui/aura/window.h"
#include "ui/compositor/test/context_factories_for_test.h"
#if defined(USE_X11)
@@ -65,16 +62,5 @@ void AthenaTestBase::RunAllPendingInMessageLoop() {
helper_->RunAllPendingInMessageLoop();
}
-scoped_ptr<aura::Window> AthenaTestBase::CreateTestWindow(
- aura::WindowDelegate* delegate,
- const gfx::Rect& bounds) {
- scoped_ptr<aura::Window> window(new aura::Window(delegate));
- window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
- window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
- aura::client::ParentWindowWithContext(
- window.get(), ScreenManager::Get()->GetContext(), bounds);
- return window.Pass();
-}
-
} // namespace test
} // namespace athena
diff --git a/athena/test/base/athena_test_base.h b/athena/test/base/athena_test_base.h
index 1ca1cd8..f1abab0 100644
--- a/athena/test/base/athena_test_base.h
+++ b/athena/test/base/athena_test_base.h
@@ -31,9 +31,6 @@ class AthenaTestBase : public testing::Test {
protected:
void RunAllPendingInMessageLoop();
- scoped_ptr<aura::Window> CreateTestWindow(aura::WindowDelegate* delegate,
- const gfx::Rect& bounds);
-
aura::Window* root_window() { return helper_->GetRootWindow(); }
aura::WindowTreeHost* host() { return helper_->GetHost(); }
diff --git a/athena/test/base/test_windows.cc b/athena/test/base/test_windows.cc
new file mode 100644
index 0000000..9559b85
--- /dev/null
+++ b/athena/test/base/test_windows.cc
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/test/base/test_windows.h"
+
+#include "athena/screen/public/screen_manager.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/window.h"
+#include "ui/wm/core/window_util.h"
+
+namespace athena {
+namespace test {
+
+scoped_ptr<aura::Window> CreateNormalWindow(aura::WindowDelegate* delegate,
+ aura::Window* parent) {
+ return CreateWindowWithType(delegate, parent, ui::wm::WINDOW_TYPE_NORMAL);
+}
+
+scoped_ptr<aura::Window> CreateWindowWithType(aura::WindowDelegate* delegate,
+ aura::Window* parent,
+ ui::wm::WindowType window_type) {
+ scoped_ptr<aura::Window> window(new aura::Window(delegate));
+ window->SetType(window_type);
+ window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
+ if (parent) {
+ parent->AddChild(window.get());
+ } else {
+ aura::client::ParentWindowWithContext(
+ window.get(), ScreenManager::Get()->GetContext(), gfx::Rect());
+ }
+ return window.Pass();
+}
+
+scoped_ptr<aura::Window> CreateTransientWindow(aura::WindowDelegate* delegate,
+ aura::Window* transient_parent,
+ ui::ModalType modal_type,
+ bool top_most) {
+ scoped_ptr<aura::Window> window(new aura::Window(delegate));
+ window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
+ window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
+ window->SetProperty(aura::client::kModalKey, modal_type);
+ window->SetProperty(aura::client::kAlwaysOnTopKey, top_most);
+ if (transient_parent)
+ wm::AddTransientChild(transient_parent, window.get());
+ aura::client::ParentWindowWithContext(
+ window.get(), ScreenManager::Get()->GetContext(), gfx::Rect());
+ return window.Pass();
+}
+
+} // namespace test
+} // namespace athena
diff --git a/athena/test/base/test_windows.h b/athena/test/base/test_windows.h
new file mode 100644
index 0000000..86d49bf
--- /dev/null
+++ b/athena/test/base/test_windows.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_TEST_BASE_TEST_WINDOWS_H_
+#define ATHENA_TEST_BASE_TEST_WINDOWS_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/wm/public/window_types.h"
+
+namespace aura {
+class Window;
+class WindowDelegate;
+}
+
+namespace gfx {
+class Rect;
+}
+
+namespace athena {
+namespace test {
+
+scoped_ptr<aura::Window> CreateNormalWindow(aura::WindowDelegate* delegate,
+ aura::Window* parent);
+
+scoped_ptr<aura::Window> CreateWindowWithType(aura::WindowDelegate* delegate,
+ aura::Window* parent,
+ ui::wm::WindowType window_type);
+
+scoped_ptr<aura::Window> CreateTransientWindow(aura::WindowDelegate* delegate,
+ aura::Window* transient_parent,
+ ui::ModalType modal_type,
+ bool top_most);
+
+} // namespace test
+} // namespace athena
+
+#endif // ATHENA_TEST_BASE_TEST_WINDOWS_H_
diff --git a/athena/util/container_priorities.h b/athena/util/container_priorities.h
index 33b687d..8b30300 100644
--- a/athena/util/container_priorities.h
+++ b/athena/util/container_priorities.h
@@ -12,9 +12,11 @@ enum ContainerPriorities {
CP_DEFAULT,
CP_HOME_CARD,
CP_SYSTEM_MODAL,
+ // TODO(oshima): rename LOGIN_xxx to something more generic.
CP_LOGIN_SCREEN,
CP_LOGIN_SCREEN_SYSTEM_MODAL,
CP_VIRTUAL_KEYBOARD,
+ CP_END,
};
} // namespace athena
diff --git a/athena/wm/split_view_controller_unittest.cc b/athena/wm/split_view_controller_unittest.cc
index 91e7ee5..c90a3cf 100644
--- a/athena/wm/split_view_controller_unittest.cc
+++ b/athena/wm/split_view_controller_unittest.cc
@@ -6,6 +6,7 @@
#include "athena/screen/public/screen_manager.h"
#include "athena/test/base/athena_test_base.h"
+#include "athena/test/base/test_windows.h"
#include "athena/wm/public/window_list_provider.h"
#include "athena/wm/test/window_manager_impl_test_api.h"
#include "base/memory/scoped_vector.h"
@@ -102,7 +103,7 @@ TEST_F(SplitViewControllerTest, SplitModeActivation) {
ScopedVector<aura::Window> windows;
const int kNumWindows = 6;
for (size_t i = 0; i < kNumWindows; ++i) {
- scoped_ptr<aura::Window> window = CreateTestWindow(NULL, gfx::Rect());
+ scoped_ptr<aura::Window> window = test::CreateNormalWindow(NULL, NULL);
windows.push_back(window.release());
windows[i]->Hide();
}
@@ -194,7 +195,7 @@ TEST_F(SplitViewControllerTest, ScrollDragHandle) {
ScopedVector<aura::Window> windows;
const int kNumWindows = 2;
for (size_t i = 0; i < kNumWindows; ++i) {
- scoped_ptr<aura::Window> window = CreateTestWindow(NULL, gfx::Rect());
+ scoped_ptr<aura::Window> window = test::CreateNormalWindow(NULL, NULL);
windows.push_back(window.release());
windows[i]->Hide();
}
@@ -290,7 +291,7 @@ TEST_F(SplitViewControllerTest, LandscapeOnly) {
ScopedVector<aura::Window> windows;
const int kNumWindows = 2;
for (size_t i = 0; i < kNumWindows; ++i) {
- scoped_ptr<aura::Window> window = CreateTestWindow(NULL, gfx::Rect());
+ scoped_ptr<aura::Window> window = test::CreateNormalWindow(NULL, NULL);
window->Hide();
windows.push_back(window.release());
}
diff --git a/athena/wm/window_list_provider_impl_unittest.cc b/athena/wm/window_list_provider_impl_unittest.cc
index 5b03d2d..d3dd285 100644
--- a/athena/wm/window_list_provider_impl_unittest.cc
+++ b/athena/wm/window_list_provider_impl_unittest.cc
@@ -8,6 +8,7 @@
#include "athena/screen/public/screen_manager.h"
#include "athena/test/base/athena_test_base.h"
+#include "athena/test/base/test_windows.h"
#include "athena/wm/public/window_list_provider_observer.h"
#include "athena/wm/public/window_manager.h"
#include "ui/aura/client/window_tree_client.h"
@@ -36,18 +37,6 @@ scoped_ptr<aura::Window> CreateWindow(aura::Window* parent,
return window.Pass();
}
-scoped_ptr<aura::Window> CreateTransientWindow(aura::Window* transient_parent,
- aura::WindowDelegate* delegate,
- ui::wm::WindowType window_type) {
- scoped_ptr<aura::Window> window(new aura::Window(delegate));
- window->SetType(window_type);
- window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
- wm::AddTransientChild(transient_parent, window.get());
- aura::client::ParentWindowWithContext(
- window.get(), ScreenManager::Get()->GetContext(), gfx::Rect());
- return window.Pass();
-}
-
// Return a string which defines the order of windows in |now| using the indices
// of |original|. The string will then have the lowest/oldest window on the left
// and the highest / newest on the right.
@@ -116,8 +105,8 @@ TEST_F(WindowListProviderImplTest, StackingOrder) {
scoped_ptr<WindowListProvider> list_provider(
new WindowListProviderImpl(container.get()));
- scoped_ptr<aura::Window> first =
- CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL);
+ scoped_ptr<aura::Window> first = test::CreateWindowWithType(
+ &delegate, container.get(), ui::wm::WINDOW_TYPE_NORMAL);
scoped_ptr<aura::Window> second =
CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL);
scoped_ptr<aura::Window> third =
@@ -307,12 +296,12 @@ TEST_F(WindowListProviderImplTest, TransientWindows) {
scoped_ptr<WindowListObserver> observer(
new WindowListObserver(list_provider));
- scoped_ptr<aura::Window> w1 = CreateTestWindow(&delegate, gfx::Rect());
+ scoped_ptr<aura::Window> w1 = test::CreateNormalWindow(&delegate, NULL);
w1->Show();
- scoped_ptr<aura::Window> w2 = CreateTestWindow(&delegate, gfx::Rect());
+ scoped_ptr<aura::Window> w2 = test::CreateNormalWindow(&delegate, NULL);
w2->Show();
- scoped_ptr<aura::Window> t1 =
- CreateTransientWindow(w1.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL);
+ scoped_ptr<aura::Window> t1 = test::CreateTransientWindow(
+ &delegate, w1.get(), ui::MODAL_TYPE_NONE, false);
t1->Show();
EXPECT_EQ(2u, list_provider->GetWindowList().size());
diff --git a/athena/wm/window_manager_impl.cc b/athena/wm/window_manager_impl.cc
index 3e6e390..f0020c4 100644
--- a/athena/wm/window_manager_impl.cc
+++ b/athena/wm/window_manager_impl.cc
@@ -150,7 +150,9 @@ void AthenaContainerLayoutManager::SetChildBounds(
WindowManagerImpl::WindowManagerImpl() {
ScreenManager::ContainerParams params("DefaultContainer", CP_DEFAULT);
params.can_activate_children = true;
- container_.reset(ScreenManager::Get()->CreateDefaultContainer(params));
+ params.default_parent = true;
+ params.modal_container_priority = CP_SYSTEM_MODAL;
+ container_.reset(ScreenManager::Get()->CreateContainer(params));
container_->SetLayoutManager(new AthenaContainerLayoutManager);
container_->AddObserver(this);
window_list_provider_.reset(new WindowListProviderImpl(container_.get()));
@@ -164,6 +166,8 @@ WindowManagerImpl::WindowManagerImpl() {
wm_state_.reset(new wm::WMState());
aura::client::ActivationClient* activation_client =
aura::client::GetActivationClient(container_->GetRootWindow());
+ DCHECK(container_->GetRootWindow());
+ DCHECK(activation_client);
shadow_controller_.reset(new wm::ShadowController(activation_client));
instance = this;
InstallAccelerators();
diff --git a/athena/wm/window_manager_unittest.cc b/athena/wm/window_manager_unittest.cc
index 7adda80..9cbedaa 100644
--- a/athena/wm/window_manager_unittest.cc
+++ b/athena/wm/window_manager_unittest.cc
@@ -6,6 +6,7 @@
#include "athena/screen/public/screen_manager.h"
#include "athena/test/base/athena_test_base.h"
+#include "athena/test/base/test_windows.h"
#include "athena/wm/public/window_list_provider.h"
#include "athena/wm/split_view_controller.h"
#include "athena/wm/test/window_manager_impl_test_api.h"
@@ -28,7 +29,7 @@ class WindowManagerTest : public test::AthenaTestBase {
scoped_ptr<aura::Window> CreateAndActivateWindow(
aura::WindowDelegate* delegate) {
- scoped_ptr<aura::Window> window(CreateTestWindow(delegate, gfx::Rect()));
+ scoped_ptr<aura::Window> window(test::CreateNormalWindow(delegate, NULL));
window->Show();
wm::ActivateWindow(window.get());
return window.Pass();