diff options
author | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-15 00:20:18 +0000 |
---|---|---|
committer | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-15 00:20:18 +0000 |
commit | 488b420457ae3b003ba2cd9e9dd12fc4067833ec (patch) | |
tree | 0f70baea04a2a50ab27203a4b01a2a0d249e1851 /ui/aura_shell | |
parent | f3fa076c5af0d1f384fa298bced8fddcac912a6e (diff) | |
download | chromium_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.cc | 80 | ||||
-rw-r--r-- | ui/aura_shell/always_on_top_controller.h | 54 | ||||
-rw-r--r-- | ui/aura_shell/aura_shell.gyp | 5 | ||||
-rw-r--r-- | ui/aura_shell/shell.cc | 8 | ||||
-rw-r--r-- | ui/aura_shell/shell_unittest.cc | 107 | ||||
-rw-r--r-- | ui/aura_shell/stacking_controller.cc | 10 | ||||
-rw-r--r-- | ui/aura_shell/stacking_controller.h | 8 | ||||
-rw-r--r-- | ui/aura_shell/stacking_controller_unittest.cc | 6 | ||||
-rw-r--r-- | ui/aura_shell/test/aura_shell_test_base.cc | 36 | ||||
-rw-r--r-- | ui/aura_shell/test/aura_shell_test_base.h | 31 |
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_ |