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/wm/window_util.h"
9 #include "ash/ash_constants.h"
10 #include "ash/screen_util.h"
11 #include "ash/shell.h"
12 #include "ash/snap_to_pixel_layout_manager.h"
13 #include "ash/wm/window_properties.h"
14 #include "ash/wm/window_state.h"
15 #include "ash/wm/wm_event.h"
16 #include "ui/aura/client/aura_constants.h"
17 #include "ui/aura/window.h"
18 #include "ui/aura/window_delegate.h"
19 #include "ui/aura/window_event_dispatcher.h"
20 #include "ui/compositor/dip_util.h"
21 #include "ui/gfx/display.h"
22 #include "ui/gfx/geometry/rect.h"
23 #include "ui/gfx/geometry/size.h"
24 #include "ui/gfx/screen.h"
25 #include "ui/views/view.h"
26 #include "ui/views/widget/widget.h"
27 #include "ui/wm/core/window_util.h"
28 #include "ui/wm/public/activation_client.h"
35 // Returns the default width of a snapped window.
36 int GetDefaultSnappedWindowWidth(aura::Window
* window
) {
37 const float kSnappedWidthWorkspaceRatio
= 0.5f
;
40 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window
).width();
41 int min_width
= window
->delegate() ?
42 window
->delegate()->GetMinimumSize().width() : 0;
44 static_cast<int>(work_area_width
* kSnappedWidthWorkspaceRatio
);
45 return std::min(work_area_width
, std::max(ideal_width
, min_width
));
50 // TODO(beng): replace many of these functions with the corewm versions.
51 void ActivateWindow(aura::Window
* window
) {
52 ::wm::ActivateWindow(window
);
55 void DeactivateWindow(aura::Window
* window
) {
56 ::wm::DeactivateWindow(window
);
59 bool IsActiveWindow(aura::Window
* window
) {
60 return ::wm::IsActiveWindow(window
);
63 aura::Window
* GetActiveWindow() {
64 return aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
68 aura::Window
* GetActivatableWindow(aura::Window
* window
) {
69 return ::wm::GetActivatableWindow(window
);
72 bool CanActivateWindow(aura::Window
* window
) {
73 return ::wm::CanActivateWindow(window
);
76 bool IsWindowMinimized(aura::Window
* window
) {
77 return ash::wm::GetWindowState(window
)->IsMinimized();
80 void CenterWindow(aura::Window
* window
) {
81 wm::WMEvent
event(wm::WM_EVENT_CENTER
);
82 wm::GetWindowState(window
)->OnWMEvent(&event
);
85 gfx::Rect
GetDefaultLeftSnappedWindowBoundsInParent(aura::Window
* window
) {
86 gfx::Rect
work_area_in_parent(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
88 return gfx::Rect(work_area_in_parent
.x(),
89 work_area_in_parent
.y(),
90 GetDefaultSnappedWindowWidth(window
),
91 work_area_in_parent
.height());
94 gfx::Rect
GetDefaultRightSnappedWindowBoundsInParent(aura::Window
* window
) {
95 gfx::Rect
work_area_in_parent(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
97 int width
= GetDefaultSnappedWindowWidth(window
);
98 return gfx::Rect(work_area_in_parent
.right() - width
,
99 work_area_in_parent
.y(),
101 work_area_in_parent
.height());
104 void AdjustBoundsSmallerThan(const gfx::Size
& max_size
, gfx::Rect
* bounds
) {
105 bounds
->set_width(std::min(bounds
->width(), max_size
.width()));
106 bounds
->set_height(std::min(bounds
->height(), max_size
.height()));
109 void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect
& visible_area
,
111 AdjustBoundsToEnsureWindowVisibility(
112 visible_area
, kMinimumOnScreenArea
, kMinimumOnScreenArea
, bounds
);
115 void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect
& visible_area
,
119 AdjustBoundsSmallerThan(visible_area
.size(), bounds
);
121 min_width
= std::min(min_width
, visible_area
.width());
122 min_height
= std::min(min_height
, visible_area
.height());
124 if (bounds
->right() < visible_area
.x() + min_width
) {
125 bounds
->set_x(visible_area
.x() + min_width
- bounds
->width());
126 } else if (bounds
->x() > visible_area
.right() - min_width
) {
127 bounds
->set_x(visible_area
.right() - min_width
);
129 if (bounds
->bottom() < visible_area
.y() + min_height
) {
130 bounds
->set_y(visible_area
.y() + min_height
- bounds
->height());
131 } else if (bounds
->y() > visible_area
.bottom() - min_height
) {
132 bounds
->set_y(visible_area
.bottom() - min_height
);
134 if (bounds
->y() < visible_area
.y())
135 bounds
->set_y(visible_area
.y());
138 bool MoveWindowToEventRoot(aura::Window
* window
, const ui::Event
& event
) {
139 views::View
* target
= static_cast<views::View
*>(event
.target());
142 aura::Window
* target_root
=
143 target
->GetWidget()->GetNativeView()->GetRootWindow();
144 if (!target_root
|| target_root
== window
->GetRootWindow())
146 aura::Window
* window_container
=
147 ash::Shell::GetContainer(target_root
, window
->parent()->id());
148 // Move the window to the target launcher.
149 window_container
->AddChild(window
);
153 void ReparentChildWithTransientChildren(aura::Window
* child
,
154 aura::Window
* old_parent
,
155 aura::Window
* new_parent
) {
156 if (child
->parent() == old_parent
)
157 new_parent
->AddChild(child
);
158 ReparentTransientChildrenOfChild(child
, old_parent
, new_parent
);
161 void ReparentTransientChildrenOfChild(aura::Window
* child
,
162 aura::Window
* old_parent
,
163 aura::Window
* new_parent
) {
165 i
< ::wm::GetTransientChildren(child
).size();
167 ReparentChildWithTransientChildren(
168 ::wm::GetTransientChildren(child
)[i
],
174 void SnapWindowToPixelBoundary(aura::Window
* window
) {
175 aura::Window
* snapped_ancestor
= window
->parent();
176 while (snapped_ancestor
) {
177 if (snapped_ancestor
->GetProperty(kSnapChildrenToPixelBoundary
)) {
178 ui::SnapLayerToPhysicalPixelBoundary(snapped_ancestor
->layer(),
182 snapped_ancestor
= snapped_ancestor
->parent();
186 void SetSnapsChildrenToPhysicalPixelBoundary(aura::Window
* container
) {
187 DCHECK(!container
->GetProperty(kSnapChildrenToPixelBoundary
))
188 << container
->name();
189 container
->SetProperty(kSnapChildrenToPixelBoundary
, true);
192 void InstallSnapLayoutManagerToContainers(aura::Window
* parent
) {
193 aura::Window::Windows children
= parent
->children();
194 for (aura::Window::Windows::iterator iter
= children
.begin();
195 iter
!= children
.end();
197 aura::Window
* container
= *iter
;
198 if (container
->id() < 0) // not a container
200 if (container
->GetProperty(kSnapChildrenToPixelBoundary
)) {
201 if (!container
->layout_manager())
202 container
->SetLayoutManager(new SnapToPixelLayoutManager(container
));
204 InstallSnapLayoutManagerToContainers(container
);