Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3192)

Unified Diff: ash/root_window_controller.cc

Issue 2070163002: Fix "modal isn't modal in multi displays" issue (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Modal fix Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ash/root_window_controller.cc
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index c2c2aeaa5738a691a6ba86b842060f878c6f7e2f..f00bd927d0801250c5186362d1de94adc258febc 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -262,6 +262,51 @@ class WorkspaceLayoutManagerDelegateImpl
DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerDelegateImpl);
};
+bool IsWindowAboveContainer(aura::Window* window,
James Cook 2016/06/16 20:31:35 nit: move up above the class definitions, near the
oshima 2016/06/17 00:06:12 Done.
+ aura::Window* blocking_container) {
+ std::vector<aura::Window*> target_path;
+ std::vector<aura::Window*> blocking_path;
+
+ while (window) {
+ target_path.push_back(window);
+ window = window->parent();
+ }
+
+ while (blocking_container) {
+ blocking_path.push_back(blocking_container);
+ blocking_container = blocking_container->parent();
+ }
+
+ while (!blocking_path.empty()) {
+ if (target_path.empty())
+ return false;
+
+ aura::Window* target = target_path.back();
+ target_path.pop_back();
+ aura::Window* blocking = blocking_path.back();
+ blocking_path.pop_back();
+
+ // Still on the same path, continue.
+ if (target == blocking)
+ continue;
+
+ // This can happen only if unparented window is passed because
+ // first element must be the same root.
+ if (!target->parent() || !blocking->parent())
+ return false;
+
+ aura::Window* common_parent = target->parent();
+ DCHECK_EQ(common_parent, blocking->parent());
James Cook 2016/06/16 20:31:35 I don't understand how this algorithm works. Maybe
oshima 2016/06/17 00:06:12 Comparison start from the root and that's probably
James Cook 2016/06/17 16:04:43 Ah, yes, I missed that the roots were at the end o
+ aura::Window::Windows windows = common_parent->children();
+ auto blocking_iter = std::find(windows.begin(), windows.end(), blocking);
+ // If the target window is above blocking window, the window can handle
+ // events.
+ return std::find(blocking_iter, windows.end(), target) != windows.end();
+ }
+
+ return true;
+}
+
} // namespace
void RootWindowController::CreateForPrimaryDisplay(AshWindowTreeHost* host) {
@@ -363,6 +408,51 @@ void RootWindowController::Shutdown() {
aura::client::SetScreenPositionClient(root_window, NULL);
}
+bool RootWindowController::CanWindowReceiveEvents(aura::Window* window) {
+ if (GetRootWindow() != window->GetRootWindow())
+ return false;
+
+ // Always allow events to fall through to the virtual keyboard even if
+ // displaying a system modal dialog.
+ if (IsVirtualKeyboardWindow(window))
+ return true;
+
+ aura::Window* blocking_container = nullptr;
+
+ int modal_container_id = 0;
+ if (Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()) {
+ blocking_container =
+ GetContainer(kShellWindowId_LockScreenContainersContainer);
+ modal_container_id = kShellWindowId_LockSystemModalContainer;
+ } else {
+ modal_container_id = kShellWindowId_SystemModalContainer;
+ }
+ aura::Window* modal_container = GetContainer(modal_container_id);
+ SystemModalContainerLayoutManager* modal_layout_manager = nullptr;
+ if (modal_container) {
James Cook 2016/06/16 20:31:35 Shouldn't we always have a modal_container?
oshima 2016/06/17 00:06:11 yes, you're right. Done.
+ modal_layout_manager = static_cast<SystemModalContainerLayoutManager*>(
+ modal_container->layout_manager());
+ if (modal_layout_manager->has_modal_background())
+ blocking_container = modal_container;
+ else
+ modal_layout_manager = nullptr;
James Cook 2016/06/16 20:31:35 do you need this else clause?
oshima 2016/06/17 00:06:12 Changed to modal_container for line 450. The condi
+ }
+
+ // In normal session.
+ if (blocking_container == nullptr)
+ return true;
+
+ if (!IsWindowAboveContainer(window, blocking_container))
+ return false;
+
+ // If the window is in the target modal container, only allow the top most
+ // one.
+ if (modal_container && modal_container->Contains(window))
+ return modal_layout_manager->IsActiveModalWindows(window);
+
+ return true;
+}
+
SystemModalContainerLayoutManager*
RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
aura::Window* modal_container = NULL;

Powered by Google App Engine
This is Rietveld 408576698