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 bool IsWindowUserPositionable(aura::Window
* window
) {
81 return GetWindowState(window
)->IsUserPositionable();
84 void CenterWindow(aura::Window
* window
) {
85 wm::WMEvent
event(wm::WM_EVENT_CENTER
);
86 wm::GetWindowState(window
)->OnWMEvent(&event
);
89 gfx::Rect
GetDefaultLeftSnappedWindowBoundsInParent(aura::Window
* window
) {
90 gfx::Rect
work_area_in_parent(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
92 return gfx::Rect(work_area_in_parent
.x(),
93 work_area_in_parent
.y(),
94 GetDefaultSnappedWindowWidth(window
),
95 work_area_in_parent
.height());
98 gfx::Rect
GetDefaultRightSnappedWindowBoundsInParent(aura::Window
* window
) {
99 gfx::Rect
work_area_in_parent(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
101 int width
= GetDefaultSnappedWindowWidth(window
);
102 return gfx::Rect(work_area_in_parent
.right() - width
,
103 work_area_in_parent
.y(),
105 work_area_in_parent
.height());
108 void AdjustBoundsSmallerThan(const gfx::Size
& max_size
, gfx::Rect
* bounds
) {
109 bounds
->set_width(std::min(bounds
->width(), max_size
.width()));
110 bounds
->set_height(std::min(bounds
->height(), max_size
.height()));
113 void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect
& visible_area
,
115 AdjustBoundsToEnsureWindowVisibility(
116 visible_area
, kMinimumOnScreenArea
, kMinimumOnScreenArea
, bounds
);
119 void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect
& visible_area
,
123 AdjustBoundsSmallerThan(visible_area
.size(), bounds
);
125 min_width
= std::min(min_width
, visible_area
.width());
126 min_height
= std::min(min_height
, visible_area
.height());
128 if (bounds
->right() < visible_area
.x() + min_width
) {
129 bounds
->set_x(visible_area
.x() + min_width
- bounds
->width());
130 } else if (bounds
->x() > visible_area
.right() - min_width
) {
131 bounds
->set_x(visible_area
.right() - min_width
);
133 if (bounds
->bottom() < visible_area
.y() + min_height
) {
134 bounds
->set_y(visible_area
.y() + min_height
- bounds
->height());
135 } else if (bounds
->y() > visible_area
.bottom() - min_height
) {
136 bounds
->set_y(visible_area
.bottom() - min_height
);
138 if (bounds
->y() < visible_area
.y())
139 bounds
->set_y(visible_area
.y());
142 bool MoveWindowToEventRoot(aura::Window
* window
, const ui::Event
& event
) {
143 views::View
* target
= static_cast<views::View
*>(event
.target());
146 aura::Window
* target_root
=
147 target
->GetWidget()->GetNativeView()->GetRootWindow();
148 if (!target_root
|| target_root
== window
->GetRootWindow())
150 aura::Window
* window_container
=
151 ash::Shell::GetContainer(target_root
, window
->parent()->id());
152 // Move the window to the target launcher.
153 window_container
->AddChild(window
);
157 void ReparentChildWithTransientChildren(aura::Window
* child
,
158 aura::Window
* old_parent
,
159 aura::Window
* new_parent
) {
160 if (child
->parent() == old_parent
)
161 new_parent
->AddChild(child
);
162 ReparentTransientChildrenOfChild(child
, old_parent
, new_parent
);
165 void ReparentTransientChildrenOfChild(aura::Window
* child
,
166 aura::Window
* old_parent
,
167 aura::Window
* new_parent
) {
169 i
< ::wm::GetTransientChildren(child
).size();
171 ReparentChildWithTransientChildren(
172 ::wm::GetTransientChildren(child
)[i
],
178 void SnapWindowToPixelBoundary(aura::Window
* window
) {
179 aura::Window
* snapped_ancestor
= window
->parent();
180 while (snapped_ancestor
) {
181 if (snapped_ancestor
->GetProperty(kSnapChildrenToPixelBoundary
)) {
182 ui::SnapLayerToPhysicalPixelBoundary(snapped_ancestor
->layer(),
186 snapped_ancestor
= snapped_ancestor
->parent();
190 void SetSnapsChildrenToPhysicalPixelBoundary(aura::Window
* container
) {
191 DCHECK(!container
->GetProperty(kSnapChildrenToPixelBoundary
))
192 << container
->name();
193 container
->SetProperty(kSnapChildrenToPixelBoundary
, true);
196 void InstallSnapLayoutManagerToContainers(aura::Window
* parent
) {
197 aura::Window::Windows children
= parent
->children();
198 for (aura::Window::Windows::iterator iter
= children
.begin();
199 iter
!= children
.end();
201 aura::Window
* container
= *iter
;
202 if (container
->id() < 0) // not a container
204 if (container
->GetProperty(kSnapChildrenToPixelBoundary
)) {
205 if (!container
->layout_manager())
206 container
->SetLayoutManager(new SnapToPixelLayoutManager(container
));
208 InstallSnapLayoutManagerToContainers(container
);