| 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..3c1362e58384f97f47e0d675cf132c73c45d5d61 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,38 @@ int GetDefaultSnappedWindowWidth(WmWindow* window) {
|
| return std::min(work_area_width, std::max(ideal_width, min_width));
|
| }
|
|
|
| +// Return true if the window or one of its ancestor returns true from
|
| +// IsLockedToRoot().
|
| +bool IsWindowOrAncestorLockedToRoot(const WmWindow* window) {
|
| + return window && (window->IsLockedToRoot() ||
|
| + IsWindowOrAncestorLockedToRoot(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()) {
|
| + const int container_id = transient_child->GetParent()->GetShellWindowId();
|
| + DCHECK_GE(container_id, 0);
|
| + WmWindow* container = dst_root->GetChildByShellWindowId(container_id);
|
| + const gfx::Rect transient_child_bounds_in_screen =
|
| + transient_child->GetBoundsInScreen();
|
| + container->AddChild(transient_child);
|
| + transient_child->SetBoundsInScreen(transient_child_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 +125,77 @@ void CenterWindow(WmWindow* window) {
|
| window->GetWindowState()->OnWMEvent(&event);
|
| }
|
|
|
| +void SetBoundsInScreen(WmWindow* window,
|
| + const gfx::Rect& bounds_in_screen,
|
| + 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() &&
|
| + !IsWindowOrAncestorLockedToRoot(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_in_screen.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_in_screen.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_in_screen.origin());
|
| + const gfx::Point display_origin =
|
| + window->GetDisplayNearestWindow().bounds().origin();
|
| + origin.Offset(-display_origin.x(), -display_origin.y());
|
| + window->SetBounds(gfx::Rect(origin, bounds_in_screen.size()));
|
| +}
|
| +
|
| } // namespace wm
|
| } // namespace ash
|
|
|