summaryrefslogtreecommitdiffstats
path: root/ash/wm
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-05 23:28:27 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-05 23:28:27 +0000
commitc0ce80e3a85d17848197643ed4aaaae6136b91be (patch)
treedfa25e37db9a3b2b02b3a2f12cd9a1eaac4b687a /ash/wm
parent392c70f2320491e393556608cd140d367fce0fbd (diff)
downloadchromium_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.cc124
-rw-r--r--ash/wm/system_modal_container_layout_manager.h39
-rw-r--r--ash/wm/system_modal_container_layout_manager_unittest.cc68
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