1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/display/screen_position_controller.h"
7 #include "ash/display/display_controller.h"
8 #include "ash/root_window_controller.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/coordinate_conversion.h"
12 #include "ash/wm/system_modal_container_layout_manager.h"
13 #include "ash/wm/window_properties.h"
14 #include "ash/wm/workspace_controller.h"
15 #include "ui/aura/client/activation_client.h"
16 #include "ui/aura/client/capture_client.h"
17 #include "ui/aura/client/stacking_client.h"
18 #include "ui/aura/focus_manager.h"
19 #include "ui/aura/root_window.h"
20 #include "ui/aura/window_tracker.h"
21 #include "ui/gfx/display.h"
22 #include "ui/gfx/screen.h"
27 // Move all transient children to |dst_root|, including the ones in
28 // the child windows and transient children of the transient children.
29 void MoveAllTransientChildrenToNewRoot(const gfx::Display
& display
,
30 aura::Window
* window
) {
31 aura::RootWindow
* dst_root
= Shell::GetInstance()->display_controller()->
32 GetRootWindowForDisplayId(display
.id());
33 aura::Window::Windows transient_children
= window
->transient_children();
34 for (aura::Window::Windows::iterator iter
= transient_children
.begin();
35 iter
!= transient_children
.end(); ++iter
) {
36 aura::Window
* transient_child
= *iter
;
37 int container_id
= transient_child
->parent()->id();
38 DCHECK_GE(container_id
, 0);
39 aura::Window
* container
= Shell::GetContainer(dst_root
, container_id
);
40 gfx::Rect parent_bounds_in_screen
= transient_child
->GetBoundsInScreen();
41 container
->AddChild(transient_child
);
42 transient_child
->SetBoundsInScreen(parent_bounds_in_screen
, display
);
44 // Transient children may have transient children.
45 MoveAllTransientChildrenToNewRoot(display
, transient_child
);
47 // Move transient children of the child windows if any.
48 aura::Window::Windows children
= window
->children();
49 for (aura::Window::Windows::iterator iter
= children
.begin();
50 iter
!= children
.end(); ++iter
)
51 MoveAllTransientChildrenToNewRoot(display
, *iter
);
58 void ScreenPositionController::ConvertPointToScreen(
59 const aura::Window
* window
,
61 const aura::RootWindow
* root
= window
->GetRootWindow();
62 aura::Window::ConvertPointToTarget(window
, root
, point
);
63 const gfx::Point display_origin
=
64 gfx::Screen::GetDisplayNearestWindow(
65 const_cast<aura::RootWindow
*>(root
)).bounds().origin();
66 point
->Offset(display_origin
.x(), display_origin
.y());
69 void ScreenPositionController::ConvertPointFromScreen(
70 const aura::Window
* window
,
72 const aura::RootWindow
* root
= window
->GetRootWindow();
73 const gfx::Point display_origin
=
74 gfx::Screen::GetDisplayNearestWindow(
75 const_cast<aura::RootWindow
*>(root
)).bounds().origin();
76 point
->Offset(-display_origin
.x(), -display_origin
.y());
77 aura::Window::ConvertPointToTarget(root
, window
, point
);
80 void ScreenPositionController::ConvertNativePointToScreen(
83 std::pair
<aura::RootWindow
*, gfx::Point
> pair
=
84 wm::GetRootWindowRelativeToWindow(window
, *point
);
86 ConvertPointToScreen(pair
.first
, point
);
89 void ScreenPositionController::SetBounds(aura::Window
* window
,
90 const gfx::Rect
& bounds
,
91 const gfx::Display
& display
) {
92 DCHECK_NE(-1, display
.id());
93 if (!window
->parent()->GetProperty(internal::kUsesScreenCoordinatesKey
)) {
94 window
->SetBounds(bounds
);
98 // Don't move a window to other root window if:
99 // a) the window is a transient window. It moves when its
100 // transient_parent moves.
101 // b) if the window has kStayInSameRootWindowkey. It's intentionally kept in
102 // the same root window even if the bounds is outside of the display.
103 if (!window
->transient_parent() &&
104 !window
->GetProperty(internal::kStayInSameRootWindowKey
)) {
105 aura::RootWindow
* dst_root
=
106 Shell::GetInstance()->display_controller()->GetRootWindowForDisplayId(
109 aura::Window
* dst_container
= NULL
;
110 if (dst_root
!= window
->GetRootWindow()) {
111 int container_id
= window
->parent()->id();
112 // All containers that uses screen coordinates must have valid window ids.
113 DCHECK_GE(container_id
, 0);
114 // Don't move modal screen.
115 if (!SystemModalContainerLayoutManager::IsModalScreen(window
))
116 dst_container
= Shell::GetContainer(dst_root
, container_id
);
119 if (dst_container
&& window
->parent() != dst_container
) {
120 aura::Window
* focused
= window
->GetFocusManager()->GetFocusedWindow();
121 aura::client::ActivationClient
* activation_client
=
122 aura::client::GetActivationClient(window
->GetRootWindow());
123 aura::Window
* active
= activation_client
->GetActiveWindow();
125 aura::WindowTracker tracker
;
127 tracker
.Add(focused
);
128 if (active
&& focused
!= active
)
131 if (dst_container
->id() == kShellWindowId_WorkspaceContainer
) {
133 GetRootWindowController(dst_root
)->workspace_controller()->
134 GetParentForNewWindow(window
);
137 dst_container
->AddChild(window
);
139 MoveAllTransientChildrenToNewRoot(display
, window
);
141 // Restore focused/active window.
142 if (tracker
.Contains(focused
))
143 window
->GetFocusManager()->SetFocusedWindow(focused
, NULL
);
144 else if (tracker
.Contains(active
))
145 activation_client
->ActivateWindow(active
);
149 gfx::Point
origin(bounds
.origin());
150 const gfx::Point display_origin
=
151 gfx::Screen::GetDisplayNearestWindow(window
).bounds().origin();
152 origin
.Offset(-display_origin
.x(), -display_origin
.y());
153 window
->SetBounds(gfx::Rect(origin
, bounds
.size()));