diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-05 23:28:27 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-05 23:28:27 +0000 |
commit | c0ce80e3a85d17848197643ed4aaaae6136b91be (patch) | |
tree | dfa25e37db9a3b2b02b3a2f12cd9a1eaac4b687a /ash/wm | |
parent | 392c70f2320491e393556608cd140d367fce0fbd (diff) | |
download | chromium_src-c0ce80e3a85d17848197643ed4aaaae6136b91be.zip chromium_src-c0ce80e3a85d17848197643ed4aaaae6136b91be.tar.gz chromium_src-c0ce80e3a85d17848197643ed4aaaae6136b91be.tar.bz2 |
Show modal screen on all dislpays.
Rename ModalScreen to ModalBackground
remove unnecessary internal:: namespace.
I also fix the case when a window is created with a parent,
but not bounds is specified. It was incorrectly re-parented
to the display that contains (0,0).
BUG=151054
TEST=manual (see bug). added test case.
Review URL: https://chromiumcodereview.appspot.com/11031044
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@160513 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm')
-rw-r--r-- | ash/wm/system_modal_container_layout_manager.cc | 124 | ||||
-rw-r--r-- | ash/wm/system_modal_container_layout_manager.h | 39 | ||||
-rw-r--r-- | ash/wm/system_modal_container_layout_manager_unittest.cc | 68 |
3 files changed, 154 insertions, 77 deletions
diff --git a/ash/wm/system_modal_container_layout_manager.cc b/ash/wm/system_modal_container_layout_manager.cc index 3985c72..c763bc9 100644 --- a/ash/wm/system_modal_container_layout_manager.cc +++ b/ash/wm/system_modal_container_layout_manager.cc @@ -22,6 +22,7 @@ #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/screen.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -30,10 +31,10 @@ namespace internal { namespace { -class ScreenView : public views::View { +class ModalBackgroundView : public views::View { public: - ScreenView() {} - virtual ~ScreenView() {} + ModalBackgroundView() {} + virtual ~ModalBackgroundView() {} // Overridden from views::View: virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { @@ -49,7 +50,7 @@ class ScreenView : public views::View { return SK_ColorBLACK; } - DISALLOW_COPY_AND_ASSIGN(ScreenView); + DISALLOW_COPY_AND_ASSIGN(ModalBackgroundView); }; } // namespace @@ -60,9 +61,7 @@ class ScreenView : public views::View { SystemModalContainerLayoutManager::SystemModalContainerLayoutManager( aura::Window* container) : container_(container), - modal_screen_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(modality_filter_( - new SystemModalContainerEventFilter(this))) { + modal_background_(NULL) { } SystemModalContainerLayoutManager::~SystemModalContainerLayoutManager() { @@ -72,9 +71,10 @@ SystemModalContainerLayoutManager::~SystemModalContainerLayoutManager() { // SystemModalContainerLayoutManager, aura::LayoutManager implementation: void SystemModalContainerLayoutManager::OnWindowResized() { - if (modal_screen_) { + if (modal_background_) { // Note: we have to set the entire bounds with the screen offset. - modal_screen_->SetBounds(container_->bounds()); + modal_background_->SetBounds( + gfx::Screen::GetDisplayNearestWindow(container_).bounds()); } if (!modal_windows_.empty()) { aura::Window::Windows::iterator it = modal_windows_.begin(); @@ -86,7 +86,7 @@ void SystemModalContainerLayoutManager::OnWindowResized() { void SystemModalContainerLayoutManager::OnWindowAddedToLayout( aura::Window* child) { - DCHECK((modal_screen_ && child == modal_screen_->GetNativeView()) || + DCHECK((modal_background_ && child == modal_background_->GetNativeView()) || child->type() == aura::client::WINDOW_TYPE_NORMAL || child->type() == aura::client::WINDOW_TYPE_POPUP); child->AddObserver(this); @@ -135,8 +135,8 @@ void SystemModalContainerLayoutManager::OnWindowPropertyChanged( void SystemModalContainerLayoutManager::OnWindowDestroying( aura::Window* window) { - if (modal_screen_ && modal_screen_->GetNativeView() == window) - modal_screen_ = NULL; + if (modal_background_ && modal_background_->GetNativeView() == window) + modal_background_ = NULL; } @@ -154,12 +154,59 @@ bool SystemModalContainerLayoutManager::CanWindowReceiveEvents( return wm::GetActivatableWindow(window) == modal_window(); } -bool SystemModalContainerLayoutManager::IsModalScreen( +bool SystemModalContainerLayoutManager::ActivateNextModalWindow() { + if (modal_windows_.empty()) + return false; + wm::ActivateWindow(modal_window()); + return true; +} + +void SystemModalContainerLayoutManager::CreateModalBackground() { + if (!modal_background_) { + modal_background_ = new views::Widget; + views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); + params.parent = container_; + params.bounds = gfx::Screen::GetDisplayNearestWindow(container_).bounds(); + modal_background_->Init(params); + modal_background_->GetNativeView()->SetName( + "SystemModalContainerLayoutManager.ModalBackground"); + modal_background_->SetContentsView(new ModalBackgroundView); + modal_background_->GetNativeView()->layer()->SetOpacity(0.0f); + } + + ui::ScopedLayerAnimationSettings settings( + modal_background_->GetNativeView()->layer()->GetAnimator()); + modal_background_->Show(); + modal_background_->GetNativeView()->layer()->SetOpacity(0.5f); + container_->StackChildAtTop(modal_background_->GetNativeView()); +} + +void SystemModalContainerLayoutManager::DestroyModalBackground() { + // modal_background_ can be NULL when a root window is shutting down + // and OnWindowDestroying is called first. + if (modal_background_) { + ui::ScopedLayerAnimationSettings settings( + modal_background_->GetNativeView()->layer()->GetAnimator()); + modal_background_->Close(); + settings.AddObserver(CreateHidingWindowAnimationObserver( + modal_background_->GetNativeView())); + modal_background_->GetNativeView()->layer()->SetOpacity(0.0f); + modal_background_ = NULL; + } +} + +// static +bool SystemModalContainerLayoutManager::IsModalBackground( aura::Window* window) { int id = window->parent()->id(); - return (id == internal::kShellWindowId_SystemModalContainer || - id == internal::kShellWindowId_LockSystemModalContainer) && - window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE; + if (id != internal::kShellWindowId_SystemModalContainer && + id != internal::kShellWindowId_LockSystemModalContainer) + return false; + SystemModalContainerLayoutManager* layout_manager = + static_cast<SystemModalContainerLayoutManager*>( + window->parent()->layout_manager()); + return layout_manager->modal_background_ && + layout_manager->modal_background_->GetNativeWindow() == window; } //////////////////////////////////////////////////////////////////////////////// @@ -172,7 +219,7 @@ void SystemModalContainerLayoutManager::AddModalWindow(aura::Window* window) { capture_window->ReleaseCapture(); } modal_windows_.push_back(window); - CreateModalScreen(); + Shell::GetInstance()->CreateModalBackground(); } void SystemModalContainerLayoutManager::RemoveModalWindow( @@ -182,48 +229,7 @@ void SystemModalContainerLayoutManager::RemoveModalWindow( if (it != modal_windows_.end()) modal_windows_.erase(it); - if (modal_windows_.empty()) - DestroyModalScreen(); - else - wm::ActivateWindow(modal_window()); -} - -void SystemModalContainerLayoutManager::CreateModalScreen() { - if (!modal_screen_) { - modal_screen_ = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); - params.parent = container_; - params.bounds = gfx::Rect(0, 0, container_->bounds().width(), - container_->bounds().height()); - modal_screen_->Init(params); - modal_screen_->GetNativeView()->SetName( - "SystemModalContainerLayoutManager.ModalScreen"); - modal_screen_->SetContentsView(new ScreenView); - modal_screen_->GetNativeView()->layer()->SetOpacity(0.0f); - - Shell::GetInstance()->env_filter()->AddFilter(modality_filter_.get()); - } - - ui::ScopedLayerAnimationSettings settings( - modal_screen_->GetNativeView()->layer()->GetAnimator()); - modal_screen_->Show(); - modal_screen_->GetNativeView()->layer()->SetOpacity(0.5f); - container_->StackChildAtTop(modal_screen_->GetNativeView()); -} - -void SystemModalContainerLayoutManager::DestroyModalScreen() { - Shell::GetInstance()->env_filter()->RemoveFilter(modality_filter_.get()); - // modal_screen_ can be NULL when a root window is shutting down - // and OnWindowDestroying is called first. - if (modal_screen_) { - ui::ScopedLayerAnimationSettings settings( - modal_screen_->GetNativeView()->layer()->GetAnimator()); - modal_screen_->Close(); - settings.AddObserver( - CreateHidingWindowAnimationObserver(modal_screen_->GetNativeView())); - modal_screen_->GetNativeView()->layer()->SetOpacity(0.0f); - modal_screen_ = NULL; - } + Shell::GetInstance()->OnModalWindowRemoved(window); } } // namespace internal diff --git a/ash/wm/system_modal_container_layout_manager.h b/ash/wm/system_modal_container_layout_manager.h index f2aa51c..76618ec 100644 --- a/ash/wm/system_modal_container_layout_manager.h +++ b/ash/wm/system_modal_container_layout_manager.h @@ -7,13 +7,12 @@ #include <vector> -#include "ash/wm/system_modal_container_event_filter_delegate.h" +#include "ash/ash_export.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "ui/aura/layout_manager.h" #include "ui/aura/window_observer.h" -#include "ash/ash_export.h" namespace aura { class Window; @@ -32,12 +31,13 @@ namespace internal { // LayoutManager for the modal window container. class ASH_EXPORT SystemModalContainerLayoutManager : public aura::LayoutManager, - public aura::WindowObserver, - public SystemModalContainerEventFilterDelegate { + public aura::WindowObserver { public: explicit SystemModalContainerLayoutManager(aura::Window* container); virtual ~SystemModalContainerLayoutManager(); + bool has_modal_background() const { return modal_background_ != NULL; } + // Overridden from aura::LayoutManager: virtual void OnWindowResized() OVERRIDE; virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; @@ -54,19 +54,27 @@ class ASH_EXPORT SystemModalContainerLayoutManager intptr_t old) OVERRIDE; virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - // Overridden from SystemModalContainerEventFilterDelegate: - virtual bool CanWindowReceiveEvents(aura::Window* window) OVERRIDE; + // Can a given |window| receive and handle input events? + bool CanWindowReceiveEvents(aura::Window* window); + + // Activates next modal window if any. Returns false if there + // are no more modal windows in this layout manager. + bool ActivateNextModalWindow(); - // Is the |window| modal screen? - static bool IsModalScreen(aura::Window* window); + // Creates modal background window, which is a partially-opaque + // fullscreen window. If there is already a modal background window, + // it will bring it the top. + void CreateModalBackground(); + + void DestroyModalBackground(); + + // Is the |window| modal background? + static bool IsModalBackground(aura::Window* window); private: void AddModalWindow(aura::Window* window); void RemoveModalWindow(aura::Window* window); - void CreateModalScreen(); - void DestroyModalScreen(); - aura::Window* modal_window() { return !modal_windows_.empty() ? modal_windows_.back() : NULL; } @@ -74,18 +82,13 @@ class ASH_EXPORT SystemModalContainerLayoutManager // The container that owns the layout manager. aura::Window* container_; - // A "screen" widget that dims the windows behind the modal window(s) being + // A widget that dims the windows behind the modal window(s) being // shown in |container_|. - views::Widget* modal_screen_; + views::Widget* modal_background_; // A stack of modal windows. Only the topmost can receive events. std::vector<aura::Window*> modal_windows_; - // An event filter that enforces the modality of the topmost window in - // |modal_windows_|. The event filter is attached when a modal window is - // added, and removed when the last is closed. - scoped_ptr<aura::EventFilter> modality_filter_; - DISALLOW_COPY_AND_ASSIGN(SystemModalContainerLayoutManager); }; diff --git a/ash/wm/system_modal_container_layout_manager_unittest.cc b/ash/wm/system_modal_container_layout_manager_unittest.cc index 33397e6..90a6a19 100644 --- a/ash/wm/system_modal_container_layout_manager_unittest.cc +++ b/ash/wm/system_modal_container_layout_manager_unittest.cc @@ -4,6 +4,7 @@ #include "ash/wm/system_modal_container_layout_manager.h" +#include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" @@ -15,6 +16,7 @@ #include "ui/aura/test/event_generator.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" +#include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -29,6 +31,19 @@ aura::Window* GetModalContainer() { ash::internal::kShellWindowId_SystemModalContainer); } +bool AllRootWindowsHaveModalBackgrounds() { + Shell::RootWindowControllerList controllers = + Shell::GetAllRootWindowControllers(); + bool has_modal_screen = !controllers.empty(); + for (Shell::RootWindowControllerList::const_iterator iter = + controllers.begin(); + iter != controllers.end(); ++iter) { + has_modal_screen &= + (*iter)->GetSystemModalLayoutManager()->has_modal_background(); + } + return has_modal_screen; +} + class TestWindow : public views::WidgetDelegateView { public: explicit TestWindow(bool modal) : modal_(modal) {} @@ -341,5 +356,58 @@ TEST_F(SystemModalContainerLayoutManagerTest, KeepVisible) { EXPECT_EQ(bounds, gfx::Rect(700, 500, 100, 100)); } +TEST_F(SystemModalContainerLayoutManagerTest, MultiDisplays) { + UpdateDisplay("500x500,500x500"); + + scoped_ptr<aura::Window> normal(TestWindow::OpenTestWindow(NULL, false)); + normal->SetBounds(gfx::Rect(100, 100, 50, 50)); + + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); + EXPECT_EQ(2U, root_windows.size()); + aura::Window* container1 = Shell::GetContainer( + root_windows[0], ash::internal::kShellWindowId_SystemModalContainer); + aura::Window* container2 = Shell::GetContainer( + root_windows[1], ash::internal::kShellWindowId_SystemModalContainer); + + scoped_ptr<aura::Window> modal1( + TestWindow::OpenTestWindow(container1, true)); + EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); + EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); + + scoped_ptr<aura::Window> modal11( + TestWindow::OpenTestWindow(container1, true)); + EXPECT_TRUE(wm::IsActiveWindow(modal11.get())); + + scoped_ptr<aura::Window> modal2( + TestWindow::OpenTestWindow(container2, true)); + EXPECT_TRUE(wm::IsActiveWindow(modal2.get())); + + // Sanity check if they're on the correct containers. + EXPECT_EQ(container1, modal1->parent()); + EXPECT_EQ(container1, modal11->parent()); + EXPECT_EQ(container2, modal2->parent()); + + modal2.reset(); + EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); + EXPECT_TRUE(wm::IsActiveWindow(modal11.get())); + + modal11.reset(); + EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); + EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); + + UpdateDisplay("500x500"); + EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); + EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); + + UpdateDisplay("500x500,600x600"); + EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds()); + EXPECT_TRUE(wm::IsActiveWindow(modal1.get())); + + // No more modal screen. + modal1.reset(); + EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds()); + EXPECT_TRUE(wm::IsActiveWindow(normal.get())); +} + } // namespace test } // namespace ash |