Chromium Code Reviews| 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; |