Chromium Code Reviews| Index: ash/common/wm/window_positioning_utils.cc |
| diff --git a/ash/common/wm/window_positioning_utils.cc b/ash/common/wm/window_positioning_utils.cc |
| index e9ddee57c28c343fe1da3d5c98ecd85f072f14a5..91ea42bd7ddc02894d7160d183c77bb74742ed81 100644 |
| --- a/ash/common/wm/window_positioning_utils.cc |
| +++ b/ash/common/wm/window_positioning_utils.cc |
| @@ -6,10 +6,16 @@ |
| #include <algorithm> |
| +#include "ash/common/wm/system_modal_container_layout_manager.h" |
| #include "ash/common/wm/window_state.h" |
| #include "ash/common/wm/wm_event.h" |
| #include "ash/common/wm/wm_screen_util.h" |
| +#include "ash/common/wm_lookup.h" |
| +#include "ash/common/wm_root_window_controller.h" |
| +#include "ash/common/wm_shell.h" |
| #include "ash/common/wm_window.h" |
| +#include "ash/common/wm_window_tracker.h" |
| +#include "ui/display/display.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size.h" |
| @@ -29,6 +35,36 @@ int GetDefaultSnappedWindowWidth(WmWindow* window) { |
| return std::min(work_area_width, std::max(ideal_width, min_width)); |
| } |
| +// Return true if the window or its ancestor has |kStayInSameRootWindowkey| |
| +// property. |
| +bool ShouldStayInSameRootWindow(const WmWindow* window) { |
| + return window && (window->IsLockedToRoot() || |
| + ShouldStayInSameRootWindow(window->GetParent())); |
| +} |
| + |
| +// Move all transient children to |dst_root|, including the ones in |
| +// the child windows and transient children of the transient children. |
| +void MoveAllTransientChildrenToNewRoot(const display::Display& display, |
| + WmWindow* window) { |
| + WmWindow* dst_root = WmLookup::Get() |
| + ->GetRootWindowControllerWithDisplayId(display.id()) |
| + ->GetWindow(); |
| + for (WmWindow* transient_child : window->GetTransientChildren()) { |
| + int container_id = transient_child->GetParent()->GetShellWindowId(); |
| + DCHECK_GE(container_id, 0); |
| + WmWindow* container = dst_root->GetChildByShellWindowId(container_id); |
| + gfx::Rect parent_bounds_in_screen = transient_child->GetBoundsInScreen(); |
|
James Cook
2016/09/15 16:31:40
Another naming nit/question: Does this have anythi
sky
2016/09/15 17:35:03
You're right. Updated.
|
| + container->AddChild(transient_child); |
| + transient_child->SetBoundsInScreen(parent_bounds_in_screen, display); |
| + |
| + // Transient children may have transient children. |
| + MoveAllTransientChildrenToNewRoot(display, transient_child); |
| + } |
| + // Move transient children of the child windows if any. |
| + for (WmWindow* child : window->GetChildren()) |
| + MoveAllTransientChildrenToNewRoot(display, child); |
| +} |
| + |
| } // namespace |
| void AdjustBoundsSmallerThan(const gfx::Size& max_size, gfx::Rect* bounds) { |
| @@ -87,5 +123,76 @@ void CenterWindow(WmWindow* window) { |
| window->GetWindowState()->OnWMEvent(&event); |
| } |
| +void SetBoundsInScreen(WmWindow* window, |
| + const gfx::Rect& bounds, |
|
James Cook
2016/09/15 16:31:40
How about |bounds_in_screen|? Coordinate systems h
sky
2016/09/15 17:35:03
Done.
|
| + const display::Display& display) { |
| + DCHECK_NE(display::Display::kInvalidDisplayID, display.id()); |
| + // Don't move a window to other root window if: |
| + // a) the window is a transient window. It moves when its |
| + // transient parent moves. |
| + // b) if the window or its ancestor has IsLockedToRoot(). It's intentionally |
| + // kept in the same root window even if the bounds is outside of the |
| + // display. |
| + if (!window->GetTransientParent() && !ShouldStayInSameRootWindow(window)) { |
| + WmRootWindowController* dst_root_window_controller = |
| + WmLookup::Get()->GetRootWindowControllerWithDisplayId(display.id()); |
| + DCHECK(dst_root_window_controller); |
| + WmWindow* dst_root = dst_root_window_controller->GetWindow(); |
| + DCHECK(dst_root); |
| + WmWindow* dst_container = nullptr; |
| + if (dst_root != window->GetRootWindow()) { |
| + int container_id = window->GetParent()->GetShellWindowId(); |
| + // All containers that uses screen coordinates must have valid window ids. |
| + DCHECK_GE(container_id, 0); |
| + // Don't move modal background. |
| + if (!SystemModalContainerLayoutManager::IsModalBackground(window)) |
| + dst_container = dst_root->GetChildByShellWindowId(container_id); |
| + } |
| + |
| + if (dst_container && window->GetParent() != dst_container) { |
| + WmWindow* focused = WmShell::Get()->GetFocusedWindow(); |
| + WmWindow* active = WmShell::Get()->GetActiveWindow(); |
| + |
| + WmWindowTracker tracker; |
| + if (focused) |
| + tracker.Add(focused); |
| + if (active && focused != active) |
| + tracker.Add(active); |
| + |
| + gfx::Point origin = bounds.origin(); |
| + const gfx::Point display_origin = display.bounds().origin(); |
| + origin.Offset(-display_origin.x(), -display_origin.y()); |
| + gfx::Rect new_bounds = gfx::Rect(origin, bounds.size()); |
| + |
| + // Set new bounds now so that the container's layout manager can adjust |
| + // the bounds if necessary. |
| + window->SetBounds(new_bounds); |
| + |
| + dst_container->AddChild(window); |
| + |
| + MoveAllTransientChildrenToNewRoot(display, window); |
| + |
| + // Restore focused/active window. |
| + if (tracker.Contains(focused)) { |
| + focused->SetFocused(); |
| + WmShell::Get()->set_root_window_for_new_windows( |
| + focused->GetRootWindow()); |
| + } else if (tracker.Contains(active)) { |
| + active->Activate(); |
| + } |
| + // TODO(oshima): We should not have to update the bounds again |
| + // below in theory, but we currently do need as there is a code |
| + // that assumes that the bounds will never be overridden by the |
| + // layout mananger. We should have more explicit control how |
| + // constraints are applied by the layout manager. |
| + } |
| + } |
| + gfx::Point origin(bounds.origin()); |
| + const gfx::Point display_origin = |
| + window->GetDisplayNearestWindow().bounds().origin(); |
| + origin.Offset(-display_origin.x(), -display_origin.y()); |
| + window->SetBounds(gfx::Rect(origin, bounds.size())); |
| +} |
| + |
| } // namespace wm |
| } // namespace ash |