Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: chrome/browser/ui/views/ash/window_positioner.cc

Issue 10832287: ash: Remove old files and update DEPS whitelist. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "chrome/browser/ui/views/ash/window_positioner.h"
6
7 #include "ash/shell.h"
8 #include "ash/wm/window_cycle_controller.h"
9 #include "ash/wm/window_resizer.h"
10 #include "ash/wm/window_util.h"
11 #include "ui/aura/window.h"
12 #include "ui/aura/window_delegate.h"
13 #include "ui/compositor/layer.h"
14 #include "ui/gfx/screen.h"
15
16 WindowPositioner::WindowPositioner()
17 : pop_position_offset_increment_x(0),
18 pop_position_offset_increment_y(0),
19 popup_position_offset_from_screen_corner_x(0),
20 popup_position_offset_from_screen_corner_y(0),
21 last_popup_position_x_(0),
22 last_popup_position_y_(0) {
23 }
24
25 WindowPositioner::~WindowPositioner() {
26 }
27
28 gfx::Rect WindowPositioner::GetPopupPosition(const gfx::Rect& old_pos) {
29 int grid = ash::Shell::GetInstance()->GetGridSize();
30 // Make sure that the grid has a minimum resolution of 10 pixels.
31 if (!grid) {
32 grid = 10;
33 } else {
34 while (grid < 10)
35 grid *= 2;
36 }
37 popup_position_offset_from_screen_corner_x = grid;
38 popup_position_offset_from_screen_corner_y = grid;
39 if (!pop_position_offset_increment_x) {
40 // When the popup position increment is , the last popup position
41 // was not yet initialized.
42 last_popup_position_x_ = popup_position_offset_from_screen_corner_x;
43 last_popup_position_y_ = popup_position_offset_from_screen_corner_y;
44 }
45 pop_position_offset_increment_x = grid;
46 pop_position_offset_increment_y = grid;
47 // We handle the Multi monitor support by retrieving the active window's
48 // work area.
49 aura::Window* window = ash::wm::GetActiveWindow();
50 const gfx::Rect work_area = window && window->IsVisible() ?
51 gfx::Screen::GetDisplayNearestWindow(window).work_area() :
52 gfx::Screen::GetPrimaryDisplay().work_area();
53 // Only try to reposition the popup when it is not spanning the entire
54 // screen.
55 if ((old_pos.width() + popup_position_offset_from_screen_corner_x >=
56 work_area.width()) ||
57 (old_pos.height() + popup_position_offset_from_screen_corner_y >=
58 work_area.height()))
59 return AlignPopupPosition(old_pos, work_area, grid);
60 const gfx::Rect result = SmartPopupPosition(old_pos, work_area, grid);
61 if (!result.IsEmpty())
62 return AlignPopupPosition(result, work_area, grid);
63 return NormalPopupPosition(old_pos, work_area);
64 }
65
66 gfx::Rect WindowPositioner::NormalPopupPosition(
67 const gfx::Rect& old_pos,
68 const gfx::Rect& work_area) {
69 int w = old_pos.width();
70 int h = old_pos.height();
71 // Note: The 'last_popup_position' is checked and kept relative to the
72 // screen size. The offsetting will be done in the last step when the
73 // target rectangle gets returned.
74 bool reset = false;
75 if (last_popup_position_y_ + h > work_area.height() ||
76 last_popup_position_x_ + w > work_area.width()) {
77 // Popup does not fit on screen. Reset to next diagonal row.
78 last_popup_position_x_ -= last_popup_position_y_ -
79 popup_position_offset_from_screen_corner_x -
80 pop_position_offset_increment_x;
81 last_popup_position_y_ = popup_position_offset_from_screen_corner_y;
82 reset = true;
83 }
84 if (last_popup_position_x_ + w > work_area.width()) {
85 // Start again over.
86 last_popup_position_x_ = popup_position_offset_from_screen_corner_x;
87 last_popup_position_y_ = popup_position_offset_from_screen_corner_y;
88 reset = true;
89 }
90 int x = last_popup_position_x_;
91 int y = last_popup_position_y_;
92 if (!reset) {
93 last_popup_position_x_ += pop_position_offset_increment_x;
94 last_popup_position_y_ += pop_position_offset_increment_y;
95 }
96 return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h);
97 }
98
99 gfx::Rect WindowPositioner::SmartPopupPosition(
100 const gfx::Rect& old_pos,
101 const gfx::Rect& work_area,
102 int grid) {
103 const std::vector<aura::Window*> windows =
104 ash::WindowCycleController::BuildWindowList(NULL);
105
106 std::vector<const gfx::Rect*> regions;
107 // Process the window list and check if we can bail immediately.
108 for (size_t i = 0; i < windows.size(); i++) {
109 // We only include opaque and visible windows.
110 if (windows[i] && windows[i]->IsVisible() && windows[i]->layer() &&
111 (!windows[i]->transparent() ||
112 windows[i]->layer()->GetTargetOpacity() == 1.0)) {
113 // When any window is maximized we cannot find any free space.
114 if (ash::wm::IsWindowMaximized(windows[i]) ||
115 ash::wm::IsWindowFullscreen(windows[i]))
116 return gfx::Rect(0, 0, 0, 0);
117 if (ash::wm::IsWindowNormal(windows[i]))
118 regions.push_back(&windows[i]->bounds());
119 }
120 }
121
122 if (regions.empty())
123 return gfx::Rect(0, 0, 0, 0);
124
125 int w = old_pos.width();
126 int h = old_pos.height();
127 int x_end = work_area.width() / 2;
128 int x, x_increment;
129 // We parse for a proper location on the screen. We do this in two runs:
130 // The first run will start from the left, parsing down, skipping any
131 // overlapping windows it will encounter until the popup's height can not
132 // be served anymore. Then the next grid position to the right will be
133 // taken, and the same cycle starts again. This will be repeated until we
134 // hit the middle of the screen (or we find a suitable location).
135 // In the second run we parse beginning from the right corner downwards and
136 // then to the left.
137 // When no location was found, an empty rectangle will be returned.
138 for (int run = 0; run < 2; run++) {
139 if (run == 0) { // First run: Start left, parse right till mid screen.
140 x = 0;
141 x_increment = pop_position_offset_increment_x;
142 } else { // Second run: Start right, parse left till mid screen.
143 x = work_area.width() - w;
144 x_increment = -pop_position_offset_increment_x;
145 }
146 // Note: The passing (x,y,w,h) window is always relative to the work area's
147 // origin.
148 for (; x_increment > 0 ? (x < x_end) : (x > x_end); x += x_increment) {
149 int y = 0;
150 while (y + h <= work_area.height()) {
151 size_t i;
152 for (i = 0; i < regions.size(); i++) {
153 if (regions[i]->Intersects(gfx::Rect(x + work_area.x(),
154 y + work_area.y(), w, h))) {
155 y = regions[i]->bottom() - work_area.y();
156 if (grid > 1) {
157 // Align to the (next) grid step.
158 y = ash::WindowResizer::AlignToGridRoundUp(y, grid);
159 }
160 break;
161 }
162 }
163 if (i >= regions.size())
164 return gfx::Rect(x + work_area.x(), y + work_area.y(), w, h);
165 }
166 }
167 }
168 return gfx::Rect(0, 0, 0, 0);
169 }
170
171 gfx::Rect WindowPositioner::AlignPopupPosition(
172 const gfx::Rect& pos,
173 const gfx::Rect& work_area,
174 int grid) {
175 if (grid <= 1)
176 return pos;
177
178 int x = pos.x() - (pos.x() - work_area.x()) % grid;
179 int y = pos.y() - (pos.y() - work_area.y()) % grid;
180 int w = pos.width();
181 int h = pos.height();
182
183 // If the alignment was pushing the window out of the screen, we ignore the
184 // alignment for that call.
185 if (abs(pos.right() - work_area.right()) < grid)
186 x = work_area.right() - w;
187 if (abs(pos.bottom() - work_area.bottom()) < grid)
188 y = work_area.bottom() - h;
189 return gfx::Rect(x, y, w, h);
190 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/ash/window_positioner.h ('k') | chrome/browser/ui/views/ash/window_positioner_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698