summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--ash/display/screen_position_controller.cc4
-rw-r--r--ash/root_window_controller.cc73
-rw-r--r--ash/root_window_controller.h20
-rw-r--r--ash/shell.cc45
-rw-r--r--ash/shell.h18
-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
-rw-r--r--ui/views/widget/native_widget_aura.cc16
9 files changed, 282 insertions, 125 deletions
diff --git a/ash/display/screen_position_controller.cc b/ash/display/screen_position_controller.cc
index e8567ae..3f2c392 100644
--- a/ash/display/screen_position_controller.cc
+++ b/ash/display/screen_position_controller.cc
@@ -114,8 +114,8 @@ void ScreenPositionController::SetBounds(aura::Window* window,
int container_id = window->parent()->id();
// All containers that uses screen coordinates must have valid window ids.
DCHECK_GE(container_id, 0);
- // Don't move modal screen.
- if (!SystemModalContainerLayoutManager::IsModalScreen(window))
+ // Don't move modal background.
+ if (!SystemModalContainerLayoutManager::IsModalBackground(window))
dst_container = Shell::GetContainer(dst_root, container_id);
}
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 3b6e672..1f08095 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -122,7 +122,8 @@ void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) {
iter != children.end(); ++iter) {
aura::Window* window = *iter;
// Don't move modal screen.
- if (internal::SystemModalContainerLayoutManager::IsModalScreen(window))
+ if (internal::SystemModalContainerLayoutManager::IsModalBackground(
+ window))
continue;
ReparentWindow(window, dst_container);
@@ -144,8 +145,8 @@ RootWindowController::RootWindowController(aura::RootWindow* root_window)
: root_window_(root_window) {
SetRootWindowController(root_window, this);
- event_client_.reset(new internal::EventClientImpl(root_window));
- screen_dimmer_.reset(new internal::ScreenDimmer(root_window));
+ event_client_.reset(new EventClientImpl(root_window));
+ screen_dimmer_.reset(new ScreenDimmer(root_window));
}
RootWindowController::~RootWindowController() {
@@ -171,25 +172,31 @@ void RootWindowController::Shutdown() {
root_window_->PrepareForShutdown();
}
+SystemModalContainerLayoutManager*
+RootWindowController::GetSystemModalLayoutManager() {
+ return static_cast<SystemModalContainerLayoutManager*>(
+ GetContainer(kShellWindowId_SystemModalContainer)->layout_manager());
+}
+
aura::Window* RootWindowController::GetContainer(int container_id) {
return root_window_->GetChildById(container_id);
}
void RootWindowController::InitLayoutManagers() {
root_window_layout_ =
- new internal::RootWindowLayoutManager(root_window_.get());
+ new RootWindowLayoutManager(root_window_.get());
root_window_->SetLayoutManager(root_window_layout_);
aura::Window* default_container =
- GetContainer(internal::kShellWindowId_DefaultContainer);
+ GetContainer(kShellWindowId_DefaultContainer);
// Workspace manager has its own layout managers.
workspace_controller_.reset(
- new internal::WorkspaceController(default_container));
+ new WorkspaceController(default_container));
aura::Window* always_on_top_container =
- GetContainer(internal::kShellWindowId_AlwaysOnTopContainer);
+ GetContainer(kShellWindowId_AlwaysOnTopContainer);
always_on_top_container->SetLayoutManager(
- new internal::BaseLayoutManager(
+ new BaseLayoutManager(
always_on_top_container->GetRootWindow()));
}
@@ -278,44 +285,44 @@ void RootWindowController::CreateContainersInRootWindow(
// container (moved back on unlock). We want to make sure that there's an
// opaque layer occluding the non-lock-screen layers.
- CreateContainer(internal::kShellWindowId_SystemBackgroundContainer,
+ CreateContainer(kShellWindowId_SystemBackgroundContainer,
"SystemBackgroundContainer", root_window);
aura::Window* desktop_background_containers = CreateContainer(
- internal::kShellWindowId_DesktopBackgroundContainer,
+ kShellWindowId_DesktopBackgroundContainer,
"DesktopBackgroundContainer",
root_window);
SetChildWindowVisibilityChangesAnimated(desktop_background_containers);
aura::Window* non_lock_screen_containers = CreateContainer(
- internal::kShellWindowId_NonLockScreenContainersContainer,
+ kShellWindowId_NonLockScreenContainersContainer,
"NonLockScreenContainersContainer",
root_window);
aura::Window* lock_background_containers = CreateContainer(
- internal::kShellWindowId_LockScreenBackgroundContainer,
+ kShellWindowId_LockScreenBackgroundContainer,
"LockScreenBackgroundContainer",
root_window);
SetChildWindowVisibilityChangesAnimated(lock_background_containers);
aura::Window* lock_screen_containers = CreateContainer(
- internal::kShellWindowId_LockScreenContainersContainer,
+ kShellWindowId_LockScreenContainersContainer,
"LockScreenContainersContainer",
root_window);
aura::Window* lock_screen_related_containers = CreateContainer(
- internal::kShellWindowId_LockScreenRelatedContainersContainer,
+ kShellWindowId_LockScreenRelatedContainersContainer,
"LockScreenRelatedContainersContainer",
root_window);
- CreateContainer(internal::kShellWindowId_UnparentedControlContainer,
+ CreateContainer(kShellWindowId_UnparentedControlContainer,
"UnparentedControlContainer",
non_lock_screen_containers);
aura::Window* default_container = CreateContainer(
- internal::kShellWindowId_DefaultContainer,
+ kShellWindowId_DefaultContainer,
"DefaultContainer",
non_lock_screen_containers);
- if (!internal::WorkspaceController::IsWorkspace2Enabled()) {
+ if (!WorkspaceController::IsWorkspace2Enabled()) {
default_container_handler_.reset(
new ToplevelWindowEventHandler(default_container));
}
@@ -323,7 +330,7 @@ void RootWindowController::CreateContainersInRootWindow(
SetUsesScreenCoordinates(default_container);
aura::Window* always_on_top_container = CreateContainer(
- internal::kShellWindowId_AlwaysOnTopContainer,
+ kShellWindowId_AlwaysOnTopContainer,
"AlwaysOnTopContainer",
non_lock_screen_containers);
always_on_top_container_handler_.reset(
@@ -332,36 +339,36 @@ void RootWindowController::CreateContainersInRootWindow(
SetUsesScreenCoordinates(always_on_top_container);
aura::Window* panel_container = CreateContainer(
- internal::kShellWindowId_PanelContainer,
+ kShellWindowId_PanelContainer,
"PanelContainer",
non_lock_screen_containers);
SetUsesScreenCoordinates(panel_container);
aura::Window* launcher_container =
- CreateContainer(internal::kShellWindowId_LauncherContainer,
+ CreateContainer(kShellWindowId_LauncherContainer,
"LauncherContainer",
non_lock_screen_containers);
SetUsesScreenCoordinates(launcher_container);
aura::Window* app_list_container =
- CreateContainer(internal::kShellWindowId_AppListContainer,
+ CreateContainer(kShellWindowId_AppListContainer,
"AppListContainer",
non_lock_screen_containers);
SetUsesScreenCoordinates(app_list_container);
aura::Window* modal_container = CreateContainer(
- internal::kShellWindowId_SystemModalContainer,
+ kShellWindowId_SystemModalContainer,
"SystemModalContainer",
non_lock_screen_containers);
modal_container_handler_.reset(
new ToplevelWindowEventHandler(modal_container));
modal_container->SetLayoutManager(
- new internal::SystemModalContainerLayoutManager(modal_container));
+ new SystemModalContainerLayoutManager(modal_container));
SetChildWindowVisibilityChangesAnimated(modal_container);
SetUsesScreenCoordinates(modal_container);
aura::Window* input_method_container = CreateContainer(
- internal::kShellWindowId_InputMethodContainer,
+ kShellWindowId_InputMethodContainer,
"InputMethodContainer",
non_lock_screen_containers);
SetUsesScreenCoordinates(input_method_container);
@@ -369,54 +376,54 @@ void RootWindowController::CreateContainersInRootWindow(
// TODO(beng): Figure out if we can make this use
// SystemModalContainerEventFilter instead of stops_event_propagation.
aura::Window* lock_container = CreateContainer(
- internal::kShellWindowId_LockScreenContainer,
+ kShellWindowId_LockScreenContainer,
"LockScreenContainer",
lock_screen_containers);
lock_container->SetLayoutManager(
- new internal::BaseLayoutManager(root_window));
+ new BaseLayoutManager(root_window));
SetUsesScreenCoordinates(lock_container);
// TODO(beng): stopsevents
aura::Window* lock_modal_container = CreateContainer(
- internal::kShellWindowId_LockSystemModalContainer,
+ kShellWindowId_LockSystemModalContainer,
"LockSystemModalContainer",
lock_screen_containers);
lock_modal_container_handler_.reset(
new ToplevelWindowEventHandler(lock_modal_container));
lock_modal_container->SetLayoutManager(
- new internal::SystemModalContainerLayoutManager(lock_modal_container));
+ new SystemModalContainerLayoutManager(lock_modal_container));
SetChildWindowVisibilityChangesAnimated(lock_modal_container);
SetUsesScreenCoordinates(lock_modal_container);
aura::Window* status_container =
- CreateContainer(internal::kShellWindowId_StatusContainer,
+ CreateContainer(kShellWindowId_StatusContainer,
"StatusContainer",
lock_screen_related_containers);
SetUsesScreenCoordinates(status_container);
aura::Window* settings_bubble_container = CreateContainer(
- internal::kShellWindowId_SettingBubbleContainer,
+ kShellWindowId_SettingBubbleContainer,
"SettingBubbleContainer",
lock_screen_related_containers);
SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
SetUsesScreenCoordinates(settings_bubble_container);
aura::Window* menu_container = CreateContainer(
- internal::kShellWindowId_MenuContainer,
+ kShellWindowId_MenuContainer,
"MenuContainer",
lock_screen_related_containers);
SetChildWindowVisibilityChangesAnimated(menu_container);
SetUsesScreenCoordinates(menu_container);
aura::Window* drag_drop_container = CreateContainer(
- internal::kShellWindowId_DragImageAndTooltipContainer,
+ kShellWindowId_DragImageAndTooltipContainer,
"DragImageAndTooltipContainer",
lock_screen_related_containers);
SetChildWindowVisibilityChangesAnimated(drag_drop_container);
SetUsesScreenCoordinates(drag_drop_container);
aura::Window* overlay_container = CreateContainer(
- internal::kShellWindowId_OverlayContainer,
+ kShellWindowId_OverlayContainer,
"OverlayContainer",
lock_screen_related_containers);
SetUsesScreenCoordinates(overlay_container);
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 29f9c04..e8f623d 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -5,6 +5,7 @@
#ifndef ASH_ROOT_WINDOW_CONTROLLER_H_
#define ASH_ROOT_WINDOW_CONTROLLER_H_
+#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
@@ -28,6 +29,7 @@ class EventClientImpl;
class RootWindowLayoutManager;
class ScreenDimmer;
class SystemBackgroundController;
+class SystemModalContainerLayoutManager;
class WorkspaceController;
// This class maintains the per root window state for ash. This class
@@ -35,7 +37,7 @@ class WorkspaceController;
// deleted upon the deletion of the root window. The RootWindowController
// for particular root window is stored as a property and can be obtained
// using |GetRootWindowController(aura::RootWindow*)| function.
-class RootWindowController {
+class ASH_EXPORT RootWindowController {
public:
explicit RootWindowController(aura::RootWindow* root_window);
~RootWindowController();
@@ -44,18 +46,20 @@ class RootWindowController {
return root_window_.get();
}
- internal::RootWindowLayoutManager* root_window_layout() {
+ RootWindowLayoutManager* root_window_layout() {
return root_window_layout_;
}
- internal::WorkspaceController* workspace_controller() {
+ WorkspaceController* workspace_controller() {
return workspace_controller_.get();
}
- internal::ScreenDimmer* screen_dimmer() {
+ ScreenDimmer* screen_dimmer() {
return screen_dimmer_.get();
}
+ SystemModalContainerLayoutManager* GetSystemModalLayoutManager();
+
aura::Window* GetContainer(int container_id);
void InitLayoutManagers();
@@ -89,7 +93,7 @@ class RootWindowController {
void CreateContainersInRootWindow(aura::RootWindow* root_window);
scoped_ptr<aura::RootWindow> root_window_;
- internal::RootWindowLayoutManager* root_window_layout_;
+ RootWindowLayoutManager* root_window_layout_;
// A background layer that's displayed beneath all other layers. Without
// this, portions of the root window that aren't covered by layers will be
@@ -98,9 +102,9 @@ class RootWindowController {
scoped_ptr<SystemBackgroundController> background_;
// An event filter that pre-handles all key events to send them to an IME.
- scoped_ptr<internal::EventClientImpl> event_client_;
- scoped_ptr<internal::ScreenDimmer> screen_dimmer_;
- scoped_ptr<internal::WorkspaceController> workspace_controller_;
+ scoped_ptr<EventClientImpl> event_client_;
+ scoped_ptr<ScreenDimmer> screen_dimmer_;
+ scoped_ptr<WorkspaceController> workspace_controller_;
// We need to own event handlers for various containers.
scoped_ptr<ToplevelWindowEventHandler> default_container_handler_;
diff --git a/ash/shell.cc b/ash/shell.cc
index 560e5e8..3627616 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -55,6 +55,7 @@
#include "ash/wm/stacking_controller.h"
#include "ash/wm/status_area_layout_manager.h"
#include "ash/wm/system_gesture_event_filter.h"
+#include "ash/wm/system_modal_container_event_filter.h"
#include "ash/wm/system_modal_container_layout_manager.h"
#include "ash/wm/user_activity_detector.h"
#include "ash/wm/video_detector.h"
@@ -656,6 +657,34 @@ void Shell::SetDimming(bool should_dim) {
(*iter)->screen_dimmer()->SetDimming(should_dim);
}
+void Shell::CreateModalBackground() {
+ if (!modality_filter_.get()) {
+ modality_filter_.reset(new internal::SystemModalContainerEventFilter(this));
+ AddEnvEventFilter(modality_filter_.get());
+ }
+ RootWindowControllerList controllers = GetAllRootWindowControllers();
+ for (RootWindowControllerList::iterator iter = controllers.begin();
+ iter != controllers.end(); ++iter)
+ (*iter)->GetSystemModalLayoutManager()->CreateModalBackground();
+}
+
+void Shell::OnModalWindowRemoved(aura::Window* removed) {
+ RootWindowControllerList controllers = GetAllRootWindowControllers();
+ bool activated = false;
+ for (RootWindowControllerList::iterator iter = controllers.begin();
+ iter != controllers.end() && !activated; ++iter) {
+ activated =
+ (*iter)->GetSystemModalLayoutManager()->ActivateNextModalWindow();
+ }
+ if (!activated) {
+ RemoveEnvEventFilter(modality_filter_.get());
+ modality_filter_.reset();
+ for (RootWindowControllerList::iterator iter = controllers.begin();
+ iter != controllers.end(); ++iter)
+ (*iter)->GetSystemModalLayoutManager()->DestroyModalBackground();
+ }
+}
+
SystemTrayDelegate* Shell::tray_delegate() {
return status_area_widget_->system_tray_delegate();
}
@@ -722,6 +751,10 @@ void Shell::InitRootWindowController(
root_window->GetChildById(internal::kShellWindowId_AlwaysOnTopContainer));
root_window->SetProperty(internal::kAlwaysOnTopControllerKey,
always_on_top_controller);
+ if (GetPrimaryRootWindowController()->GetSystemModalLayoutManager()->
+ has_modal_background()) {
+ controller->GetSystemModalLayoutManager()->CreateModalBackground();
+ }
window_cycle_controller_->OnRootWindowAdded(root_window);
}
@@ -776,4 +809,16 @@ void Shell::ShowCursor(bool visible) {
(*iter)->ShowCursor(visible);
}
+bool Shell::CanWindowReceiveEvents(aura::Window* window) {
+ RootWindowControllerList controllers = GetAllRootWindowControllers();
+ for (RootWindowControllerList::iterator iter = controllers.begin();
+ iter != controllers.end(); ++iter) {
+ if ((*iter)->GetSystemModalLayoutManager()->
+ CanWindowReceiveEvents(window)) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace ash
diff --git a/ash/shell.h b/ash/shell.h
index a1cebe6..ef869bf 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -13,6 +13,7 @@
#include "ash/wm/cursor_delegate.h"
#include "ash/wm/cursor_manager.h"
#include "ash/wm/shelf_types.h"
+#include "ash/wm/system_modal_container_event_filter_delegate.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
@@ -100,6 +101,7 @@ class SlowAnimationEventFilter;
class StackingController;
class StatusAreaWidget;
class SystemGestureEventFilter;
+class SystemModalContainerEventFilter;
class TooltipController;
class TouchObserverHUD;
class VisibilityController;
@@ -112,7 +114,8 @@ class WorkspaceController;
//
// Upon creation, the Shell sets itself as the RootWindow's delegate, which
// takes ownership of the Shell.
-class ASH_EXPORT Shell : ash::CursorDelegate {
+class ASH_EXPORT Shell : CursorDelegate,
+ internal::SystemModalContainerEventFilterDelegate {
public:
typedef std::vector<aura::RootWindow*> RootWindowList;
typedef std::vector<internal::RootWindowController*> RootWindowControllerList;
@@ -318,6 +321,15 @@ class ASH_EXPORT Shell : ash::CursorDelegate {
// Dims or undims the screen.
void SetDimming(bool should_dim);
+ // Creates modal background, which is a partially-opaque fullscreen
+ // window, on all displays.
+ void CreateModalBackground();
+
+ // Called when a modal window is removed. It will activate
+ // another modal window if any, or remove modal screens
+ // on all displays.
+ void OnModalWindowRemoved(aura::Window* removed);
+
// TODO(sky): don't expose this!
internal::ShelfLayoutManager* shelf() const { return shelf_; }
@@ -388,6 +400,9 @@ class ASH_EXPORT Shell : ash::CursorDelegate {
virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
virtual void ShowCursor(bool visible) OVERRIDE;
+ // ash::internal::SystemModalContainerEventFilterDelegate overrides:
+ virtual bool CanWindowReceiveEvents(aura::Window* window) OVERRIDE;
+
static Shell* instance_;
// If set before the Shell is initialized, the mouse cursor will be hidden
@@ -441,6 +456,7 @@ class ASH_EXPORT Shell : ash::CursorDelegate {
scoped_ptr<aura::client::UserActionClient> user_action_client_;
scoped_ptr<internal::MouseCursorEventFilter> mouse_cursor_filter_;
scoped_ptr<internal::ScreenPositionController> screen_position_controller_;
+ scoped_ptr<internal::SystemModalContainerEventFilter> modality_filter_;
// An event filter that rewrites or drops an event.
scoped_ptr<internal::EventRewriterEventFilter> event_rewriter_filter_;
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
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index ecd71bc..ee2fe37 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -176,6 +176,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
window_->Show();
delegate_->OnNativeWidgetCreated();
+
+ gfx::Rect window_bounds = params.bounds;
if (desktop_helper_.get() && desktop_helper_->GetRootWindow()) {
if (!params.child && params.GetParent())
params.GetParent()->AddTransientChild(window_);
@@ -203,10 +205,16 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
// SetAlwaysOnTop before SetParent so that always-on-top container is used.
SetAlwaysOnTop(params.keep_on_top);
// If the parent is not specified, find the default parent for
- // the |window_| using the desired |params.bounds|.
+ // the |window_| using the desired |window_bounds|.
if (!parent) {
parent = aura::client::GetStackingClient()->GetDefaultParent(
- window_, params.bounds);
+ window_, window_bounds);
+ } else if (window_bounds == gfx::Rect()) {
+ // If a parent is specified but no bounds are given,
+ // use the origin of the parent's display so that the widget
+ // will be added to the same display as the parent.
+ gfx::Rect bounds = gfx::Screen::GetDisplayNearestWindow(parent).bounds();
+ window_bounds.set_origin(bounds.origin());
}
window_->SetParent(parent);
}
@@ -215,9 +223,9 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
// true state/bounds (the LayoutManager may enforce a particular
// state/bounds).
if (IsMaximized())
- SetRestoreBounds(window_, params.bounds);
+ SetRestoreBounds(window_, window_bounds);
else
- SetBounds(params.bounds);
+ SetBounds(window_bounds);
window_->set_ignore_events(!params.accept_events);
can_activate_ =
params.can_activate && params.type != Widget::InitParams::TYPE_CONTROL;