summaryrefslogtreecommitdiffstats
path: root/ui/aura_shell
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-15 00:20:18 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-15 00:20:18 +0000
commit488b420457ae3b003ba2cd9e9dd12fc4067833ec (patch)
tree0f70baea04a2a50ab27203a4b01a2a0d249e1851 /ui/aura_shell
parentf3fa076c5af0d1f384fa298bced8fddcac912a6e (diff)
downloadchromium_src-488b420457ae3b003ba2cd9e9dd12fc4067833ec.zip
chromium_src-488b420457ae3b003ba2cd9e9dd12fc4067833ec.tar.gz
chromium_src-488b420457ae3b003ba2cd9e9dd12fc4067833ec.tar.bz2
[Aura] Support always-on-top top level window.
BUG=97256,102582 TEST=AlwaysOnTop related tests in ShellTest should pass. Review URL: http://codereview.chromium.org/8387043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109990 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/aura_shell')
-rw-r--r--ui/aura_shell/always_on_top_controller.cc80
-rw-r--r--ui/aura_shell/always_on_top_controller.h54
-rw-r--r--ui/aura_shell/aura_shell.gyp5
-rw-r--r--ui/aura_shell/shell.cc8
-rw-r--r--ui/aura_shell/shell_unittest.cc107
-rw-r--r--ui/aura_shell/stacking_controller.cc10
-rw-r--r--ui/aura_shell/stacking_controller.h8
-rw-r--r--ui/aura_shell/stacking_controller_unittest.cc6
-rw-r--r--ui/aura_shell/test/aura_shell_test_base.cc36
-rw-r--r--ui/aura_shell/test/aura_shell_test_base.h31
10 files changed, 340 insertions, 5 deletions
diff --git a/ui/aura_shell/always_on_top_controller.cc b/ui/aura_shell/always_on_top_controller.cc
new file mode 100644
index 0000000..177deb3
--- /dev/null
+++ b/ui/aura_shell/always_on_top_controller.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2011 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 "ui/aura_shell/always_on_top_controller.h"
+
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_types.h"
+
+namespace aura_shell {
+namespace internal {
+
+AlwaysOnTopController::AlwaysOnTopController()
+ : default_container_(NULL),
+ always_on_top_container_(NULL) {
+}
+
+AlwaysOnTopController::~AlwaysOnTopController() {
+ if (default_container_)
+ default_container_->RemoveObserver(this);
+ if (always_on_top_container_)
+ always_on_top_container_->RemoveObserver(this);
+}
+
+void AlwaysOnTopController::SetContainers(aura::Window* default_container,
+ aura::Window* always_on_top_container) {
+ // Both containers should have no children.
+ DCHECK(default_container->children().empty());
+ DCHECK(always_on_top_container->children().empty());
+
+ // We are not handling any containers yet.
+ DCHECK(default_container_ == NULL && always_on_top_container_ == NULL);
+
+ default_container_ = default_container;
+ default_container_->AddObserver(this);
+
+ always_on_top_container_ = always_on_top_container;
+ always_on_top_container_->AddObserver(this);
+}
+
+aura::Window* AlwaysOnTopController::GetContainer(aura::Window* window) const {
+ DCHECK(default_container_ && always_on_top_container_);
+ return !window->GetProperty(aura::kAlwaysOnTopKey) ? default_container_ :
+ always_on_top_container_;
+}
+
+void AlwaysOnTopController::OnWindowAdded(aura::Window* child) {
+ // Observe direct child of the containers.
+ if (child->parent() == default_container_ ||
+ child->parent() == always_on_top_container_) {
+ child->AddObserver(this);
+ }
+}
+
+void AlwaysOnTopController::OnWillRemoveWindow(aura::Window* child) {
+ child->RemoveObserver(this);
+}
+
+void AlwaysOnTopController::OnPropertyChanged(aura::Window* window,
+ const char* name,
+ void* old) {
+ if (name == aura::kAlwaysOnTopKey) {
+ DCHECK(window->type() == aura::WINDOW_TYPE_NORMAL ||
+ window->type() == aura::WINDOW_TYPE_POPUP);
+ aura::Window* container = GetContainer(window);
+ if (window->parent() != container)
+ container->AddChild(window);
+ }
+}
+
+void AlwaysOnTopController::OnWindowDestroyed(aura::Window* window) {
+ if (window == default_container_)
+ default_container_ = NULL;
+ if (window == always_on_top_container_)
+ always_on_top_container_ = NULL;
+}
+
+} // namespace internal
+} // namespace aura_shell
diff --git a/ui/aura_shell/always_on_top_controller.h b/ui/aura_shell/always_on_top_controller.h
new file mode 100644
index 0000000..e0690b3
--- /dev/null
+++ b/ui/aura_shell/always_on_top_controller.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 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 UI_AURA_SHELL_ALWAYS_ON_TOP_CONTROLLER_H_
+#define UI_AURA_SHELL_ALWAYS_ON_TOP_CONTROLLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ui/aura/window_observer.h"
+
+namespace aura {
+class Window;
+}
+
+namespace aura_shell {
+namespace internal {
+
+// AlwaysOnTopController puts window into proper containers based on its
+// 'AlwaysOnTop' property. That is, putting a window to |default_container_|
+// if its "AlwaysOnTop" property is false. Otherwise, put it in
+// |always_on_top_container_|.
+class AlwaysOnTopController : public aura::WindowObserver {
+ public:
+ AlwaysOnTopController();
+ virtual ~AlwaysOnTopController();
+
+ // Sets the two top level window containers.
+ void SetContainers(aura::Window* default_container,
+ aura::Window* always_on_top_container);
+
+ // Gets container for given |window| based on its "AlwaysOnTop" property.
+ aura::Window* GetContainer(aura::Window* window) const;
+
+ private:
+ // Overridden from aura::WindowObserver:
+ virtual void OnWindowAdded(aura::Window* child) OVERRIDE;
+ virtual void OnWillRemoveWindow(aura::Window* child) OVERRIDE;
+ virtual void OnPropertyChanged(aura::Window* window,
+ const char* name,
+ void* old) OVERRIDE;
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
+
+ aura::Window* default_container_;
+ aura::Window* always_on_top_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(AlwaysOnTopController);
+};
+
+} // namepsace aura_shell
+} // namepsace internal
+
+#endif // UI_AURA_SHELL_ALWAYS_ON_TOP_CONTROLLER_H_
diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp
index 9a9fb01..240f49b 100644
--- a/ui/aura_shell/aura_shell.gyp
+++ b/ui/aura_shell/aura_shell.gyp
@@ -33,6 +33,8 @@
],
'sources': [
# All .cc, .h under views, except unittests
+ 'always_on_top_controller.cc',
+ 'always_on_top_controller.h',
'default_container_event_filter.cc',
'default_container_event_filter.h',
'default_container_layout_manager.cc',
@@ -121,9 +123,12 @@
'launcher/view_model_unittest.cc',
'launcher/view_model_utils_unittest.cc',
'run_all_unittests.cc',
+ 'shell_unittest.cc',
'stacking_controller_unittest.cc',
'test_suite.cc',
'test_suite.h',
+ 'test/aura_shell_test_base.cc',
+ 'test/aura_shell_test_base.h',
'toplevel_layout_manager_unittest.cc',
'toplevel_window_event_filter_unittest.cc',
'workspace_controller_unittest.cc',
diff --git a/ui/aura_shell/shell.cc b/ui/aura_shell/shell.cc
index c16b63c..dc40423 100644
--- a/ui/aura_shell/shell.cc
+++ b/ui/aura_shell/shell.cc
@@ -92,6 +92,9 @@ Shell::Shell(ShellDelegate* delegate)
}
Shell::~Shell() {
+ DCHECK(instance_ == this);
+ instance_ = NULL;
+
// Make sure we delete WorkspaceController before launcher is
// deleted as it has a reference to launcher model.
workspace_controller_.reset();
@@ -130,6 +133,11 @@ void Shell::Init() {
(*i)->Show();
}
+ internal::StackingController* stacking_controller =
+ static_cast<internal::StackingController*>(
+ desktop_window->stacking_client());
+ stacking_controller->Init();
+
internal::DesktopLayoutManager* desktop_layout =
new internal::DesktopLayoutManager(desktop_window);
desktop_window->SetLayoutManager(desktop_layout);
diff --git a/ui/aura_shell/shell_unittest.cc b/ui/aura_shell/shell_unittest.cc
new file mode 100644
index 0000000..a9a18e2
--- /dev/null
+++ b/ui/aura_shell/shell_unittest.cc
@@ -0,0 +1,107 @@
+// Copyright (c) 2011 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 "ui/aura/test/aura_test_base.h"
+#include "ui/aura/window.h"
+#include "ui/aura_shell/shell.h"
+#include "ui/aura_shell/shell_window_ids.h"
+#include "ui/aura_shell/test/aura_shell_test_base.h"
+#include "views/widget/widget.h"
+
+namespace aura_shell {
+namespace test {
+
+namespace {
+
+views::Widget* CreateTestWindow(const views::Widget::InitParams& params) {
+ views::Widget* widget = new views::Widget;
+ widget->Init(params);
+ return widget;
+}
+
+aura::Window* GetDefaultContainer() {
+ return Shell::GetInstance()->GetContainer(
+ aura_shell::internal::kShellWindowId_DefaultContainer);
+}
+
+aura::Window* GetAlwaysOnTopContainer() {
+ return Shell::GetInstance()->GetContainer(
+ aura_shell::internal::kShellWindowId_AlwaysOnTopContainer);
+}
+
+void TestCreateWindow(views::Widget::InitParams::Type type,
+ bool always_on_top,
+ aura::Window* expected_container) {
+ views::Widget::InitParams widget_params(type);
+ widget_params.keep_on_top = always_on_top;
+
+ views::Widget* widget = CreateTestWindow(widget_params);
+ widget->Show();
+
+ EXPECT_EQ(expected_container, widget->GetNativeWindow()->parent()) <<
+ "TestCreateWindow: type=" << type << ", always_on_top=" << always_on_top;
+
+ widget->Close();
+}
+
+} // namespace
+
+class ShellTest : public AuraShellTestBase {
+ public:
+ ShellTest() {}
+ virtual ~ShellTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellTest);
+};
+
+TEST_F(ShellTest, CreateWindow) {
+ // Normal window should be created in default container.
+ TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW,
+ false, // always_on_top
+ GetDefaultContainer());
+ TestCreateWindow(views::Widget::InitParams::TYPE_POPUP,
+ false, // always_on_top
+ GetDefaultContainer());
+
+ // Always-on-top window and popup are created in always-on-top container.
+ TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW,
+ true, // always_on_top
+ GetAlwaysOnTopContainer());
+ TestCreateWindow(views::Widget::InitParams::TYPE_POPUP,
+ true, // always_on_top
+ GetAlwaysOnTopContainer());
+}
+
+TEST_F(ShellTest, ChangeAlwaysOnTop) {
+ views::Widget::InitParams widget_params(
+ views::Widget::InitParams::TYPE_WINDOW);
+
+ // Creates a normal window
+ views::Widget* widget = CreateTestWindow(widget_params);
+ widget->Show();
+
+ // It should be in default container.
+ EXPECT_EQ(GetDefaultContainer(), widget->GetNativeWindow()->parent());
+
+ // Flip always-on-top flag.
+ widget->SetAlwaysOnTop(true);
+ // And it should in always on top container now.
+ EXPECT_EQ(GetAlwaysOnTopContainer(), widget->GetNativeWindow()->parent());
+
+ // Flip always-on-top flag.
+ widget->SetAlwaysOnTop(false);
+ // It should go back to default container.
+ EXPECT_EQ(GetDefaultContainer(), widget->GetNativeWindow()->parent());
+
+ // Set the same always-on-top flag again.
+ widget->SetAlwaysOnTop(false);
+ // Should have no effect and we are still in the default container.
+ EXPECT_EQ(GetDefaultContainer(), widget->GetNativeWindow()->parent());
+
+ widget->Close();
+}
+
+} // namespace test
+} // namespace aura_shell
diff --git a/ui/aura_shell/stacking_controller.cc b/ui/aura_shell/stacking_controller.cc
index 2fb3ec6..3a913c3 100644
--- a/ui/aura_shell/stacking_controller.cc
+++ b/ui/aura_shell/stacking_controller.cc
@@ -6,6 +6,7 @@
#include "ui/aura/desktop.h"
#include "ui/aura/window.h"
+#include "ui/aura_shell/always_on_top_controller.h"
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/shell_window_ids.h"
@@ -35,6 +36,13 @@ StackingController::StackingController() {
StackingController::~StackingController() {
}
+void StackingController::Init() {
+ always_on_top_controller_.reset(new internal::AlwaysOnTopController);
+ always_on_top_controller_->SetContainers(
+ GetContainer(internal::kShellWindowId_DefaultContainer),
+ GetContainer(internal::kShellWindowId_AlwaysOnTopContainer));
+}
+
// static
aura::Window* StackingController::GetActivatableWindow(aura::Window* window) {
aura::Window* parent = window->parent();
@@ -60,7 +68,7 @@ void StackingController::AddChildToDefaultParent(aura::Window* window) {
switch (window->type()) {
case aura::WINDOW_TYPE_NORMAL:
case aura::WINDOW_TYPE_POPUP:
- parent = GetContainer(internal::kShellWindowId_DefaultContainer);
+ parent = always_on_top_controller_->GetContainer(window);
break;
case aura::WINDOW_TYPE_MENU:
case aura::WINDOW_TYPE_TOOLTIP:
diff --git a/ui/aura_shell/stacking_controller.h b/ui/aura_shell/stacking_controller.h
index 2091f1f..20bb5fe 100644
--- a/ui/aura_shell/stacking_controller.h
+++ b/ui/aura_shell/stacking_controller.h
@@ -8,16 +8,22 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
#include "ui/aura/client/stacking_client.h"
namespace aura_shell {
namespace internal {
+class AlwaysOnTopController;
+
class StackingController : public aura::StackingClient {
public:
StackingController();
virtual ~StackingController();
+ // Initializes this controller.
+ void Init();
+
// Returns true if |window| exists within a container that supports
// activation.
static aura::Window* GetActivatableWindow(aura::Window* window);
@@ -29,6 +35,8 @@ class StackingController : public aura::StackingClient {
aura::Window* ignore) const OVERRIDE;
private:
+ scoped_ptr<internal::AlwaysOnTopController> always_on_top_controller_;
+
DISALLOW_COPY_AND_ASSIGN(StackingController);
};
diff --git a/ui/aura_shell/stacking_controller_unittest.cc b/ui/aura_shell/stacking_controller_unittest.cc
index 500c24f..cf4fdc7 100644
--- a/ui/aura_shell/stacking_controller_unittest.cc
+++ b/ui/aura_shell/stacking_controller_unittest.cc
@@ -5,18 +5,16 @@
#include "ui/aura_shell/stacking_controller.h"
#include "ui/aura/desktop.h"
-#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura_shell/shell.h"
+#include "ui/aura_shell/test/aura_shell_test_base.h"
namespace aura_shell {
namespace test {
-typedef aura::test::AuraTestBase StackingControllerTest;
+typedef aura_shell::test::AuraShellTestBase StackingControllerTest;
TEST_F(StackingControllerTest, GetTopmostWindowToActivate) {
- Shell::CreateInstance(NULL);
aura::test::ActivateWindowDelegate activate;
aura::test::ActivateWindowDelegate non_activate(false);
diff --git a/ui/aura_shell/test/aura_shell_test_base.cc b/ui/aura_shell/test/aura_shell_test_base.cc
new file mode 100644
index 0000000..fe121f2
--- /dev/null
+++ b/ui/aura_shell/test/aura_shell_test_base.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 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 "ui/aura_shell/test/aura_shell_test_base.h"
+
+#include "ui/aura_shell/shell.h"
+
+namespace aura_shell {
+namespace test {
+
+AuraShellTestBase::AuraShellTestBase() {
+}
+
+AuraShellTestBase::~AuraShellTestBase() {
+}
+
+void AuraShellTestBase::SetUp() {
+ aura::test::AuraTestBase::SetUp();
+
+ // Creates Shell and hook with Desktop.
+ aura_shell::Shell::CreateInstance(NULL);
+}
+
+void AuraShellTestBase::TearDown() {
+ // Flush the message loop to finish pending release tasks.
+ RunAllPendingInMessageLoop();
+
+ // Tear down the shell.
+ aura_shell::Shell::DeleteInstanceForTesting();
+
+ aura::test::AuraTestBase::TearDown();
+}
+
+} // namespace test
+} // namespace aura_shell
diff --git a/ui/aura_shell/test/aura_shell_test_base.h b/ui/aura_shell/test/aura_shell_test_base.h
new file mode 100644
index 0000000..c08c556
--- /dev/null
+++ b/ui/aura_shell/test/aura_shell_test_base.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 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 UI_AURA_SHELL_TEST_AURA_SHELL_TEST_BASE_H_
+#define UI_AURA_SHELL_TEST_AURA_SHELL_TEST_BASE_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "ui/aura/test/aura_test_base.h"
+
+namespace aura_shell {
+namespace test {
+
+class AuraShellTestBase : public aura::test::AuraTestBase {
+ public:
+ AuraShellTestBase();
+ virtual ~AuraShellTestBase();
+
+ // testing::Test:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AuraShellTestBase);
+};
+
+} // namespace test
+} // namespace aura_shell
+
+#endif // UI_AURA_SHELL_TEST_AURA_SHELL_TEST_BASE_H_