window_util.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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.
4
5#include "ash/wm/window_util.h"
6
7#include <vector>
8
9#include "ash/ash_constants.h"
10#include "ash/screen_util.h"
11#include "ash/shell.h"
12#include "ash/wm/window_properties.h"
13#include "ash/wm/window_state.h"
14#include "ui/aura/client/activation_client.h"
15#include "ui/aura/client/aura_constants.h"
16#include "ui/aura/window.h"
17#include "ui/aura/window_delegate.h"
18#include "ui/aura/window_event_dispatcher.h"
19#include "ui/gfx/display.h"
20#include "ui/gfx/rect.h"
21#include "ui/gfx/screen.h"
22#include "ui/gfx/size.h"
23#include "ui/views/view.h"
24#include "ui/views/widget/widget.h"
25#include "ui/wm/core/window_util.h"
26
27namespace ash {
28namespace wm {
29
30namespace {
31
32// Returns the default width of a snapped window.
33int GetDefaultSnappedWindowWidth(aura::Window* window) {
34  const float kSnappedWidthWorkspaceRatio = 0.5f;
35
36  int work_area_width =
37      ScreenUtil::GetDisplayWorkAreaBoundsInParent(window).width();
38  int min_width = window->delegate() ?
39      window->delegate()->GetMinimumSize().width() : 0;
40  int ideal_width =
41      static_cast<int>(work_area_width * kSnappedWidthWorkspaceRatio);
42  return std::min(work_area_width, std::max(ideal_width, min_width));
43}
44
45}  // namespace
46
47// TODO(beng): replace many of these functions with the corewm versions.
48void ActivateWindow(aura::Window* window) {
49  ::wm::ActivateWindow(window);
50}
51
52void DeactivateWindow(aura::Window* window) {
53  ::wm::DeactivateWindow(window);
54}
55
56bool IsActiveWindow(aura::Window* window) {
57  return ::wm::IsActiveWindow(window);
58}
59
60aura::Window* GetActiveWindow() {
61  return aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
62      GetActiveWindow();
63}
64
65aura::Window* GetActivatableWindow(aura::Window* window) {
66  return ::wm::GetActivatableWindow(window);
67}
68
69bool CanActivateWindow(aura::Window* window) {
70  return ::wm::CanActivateWindow(window);
71}
72
73bool IsWindowMinimized(aura::Window* window) {
74  return ash::wm::GetWindowState(window)->IsMinimized();
75}
76
77void CenterWindow(aura::Window* window) {
78  wm::WindowState* window_state = wm::GetWindowState(window);
79  if (!window_state->IsNormalOrSnapped())
80    return;
81  const gfx::Display display =
82      Shell::GetScreen()->GetDisplayNearestWindow(window);
83  gfx::Rect center = display.work_area();
84  gfx::Size size = window->bounds().size();
85  if (window_state->IsSnapped()) {
86    if (window_state->HasRestoreBounds())
87      size = window_state->GetRestoreBoundsInScreen().size();
88    center.ClampToCenteredSize(size);
89    window_state->SetRestoreBoundsInScreen(center);
90    window_state->Restore();
91  } else {
92    center = ScreenUtil::ConvertRectFromScreen(window->parent(),
93        center);
94    center.ClampToCenteredSize(size);
95    window->SetBounds(center);
96  }
97}
98
99
100gfx::Rect GetDefaultLeftSnappedWindowBoundsInParent(aura::Window* window) {
101  gfx::Rect work_area_in_parent(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
102      window));
103  return gfx::Rect(work_area_in_parent.x(),
104                   work_area_in_parent.y(),
105                   GetDefaultSnappedWindowWidth(window),
106                   work_area_in_parent.height());
107}
108
109gfx::Rect GetDefaultRightSnappedWindowBoundsInParent(aura::Window* window) {
110  gfx::Rect work_area_in_parent(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
111      window));
112  int width = GetDefaultSnappedWindowWidth(window);
113  return gfx::Rect(work_area_in_parent.right() - width,
114                   work_area_in_parent.y(),
115                   width,
116                   work_area_in_parent.height());
117}
118
119void AdjustBoundsSmallerThan(const gfx::Size& max_size, gfx::Rect* bounds) {
120  bounds->set_width(std::min(bounds->width(), max_size.width()));
121  bounds->set_height(std::min(bounds->height(), max_size.height()));
122}
123
124void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect& visible_area,
125                                                 gfx::Rect* bounds) {
126  AdjustBoundsToEnsureWindowVisibility(
127      visible_area, kMinimumOnScreenArea, kMinimumOnScreenArea, bounds);
128}
129
130void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect& visible_area,
131                                          int min_width,
132                                          int min_height,
133                                          gfx::Rect* bounds) {
134  AdjustBoundsSmallerThan(visible_area.size(), bounds);
135
136  min_width = std::min(min_width, visible_area.width());
137  min_height = std::min(min_height, visible_area.height());
138
139  if (bounds->right() < visible_area.x() + min_width) {
140    bounds->set_x(visible_area.x() + min_width - bounds->width());
141  } else if (bounds->x() > visible_area.right() - min_width) {
142    bounds->set_x(visible_area.right() - min_width);
143  }
144  if (bounds->bottom() < visible_area.y() + min_height) {
145    bounds->set_y(visible_area.y() + min_height - bounds->height());
146  } else if (bounds->y() > visible_area.bottom() - min_height) {
147    bounds->set_y(visible_area.bottom() - min_height);
148  }
149  if (bounds->y() < visible_area.y())
150    bounds->set_y(visible_area.y());
151}
152
153bool MoveWindowToEventRoot(aura::Window* window, const ui::Event& event) {
154  views::View* target = static_cast<views::View*>(event.target());
155  if (!target)
156    return false;
157  aura::Window* target_root =
158      target->GetWidget()->GetNativeView()->GetRootWindow();
159  if (!target_root || target_root == window->GetRootWindow())
160    return false;
161  aura::Window* window_container =
162      ash::Shell::GetContainer(target_root, window->parent()->id());
163  // Move the window to the target launcher.
164  window_container->AddChild(window);
165  return true;
166}
167
168void ReparentChildWithTransientChildren(aura::Window* child,
169                                        aura::Window* old_parent,
170                                        aura::Window* new_parent) {
171  if (child->parent() == old_parent)
172    new_parent->AddChild(child);
173  ReparentTransientChildrenOfChild(child, old_parent, new_parent);
174}
175
176void ReparentTransientChildrenOfChild(aura::Window* child,
177                                      aura::Window* old_parent,
178                                      aura::Window* new_parent) {
179  for (size_t i = 0;
180       i < ::wm::GetTransientChildren(child).size();
181       ++i) {
182    ReparentChildWithTransientChildren(
183        ::wm::GetTransientChildren(child)[i],
184        old_parent,
185        new_parent);
186  }
187}
188
189}  // namespace wm
190}  // namespace ash
191