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

Side by Side Diff: ui/aura_shell/toplevel_window_event_filter.cc

Issue 9035001: Move some more WM functionality down into ash. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 12 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) 2011 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 "ui/aura_shell/toplevel_window_event_filter.h"
6
7 #include "ui/aura/client/aura_constants.h"
8 #include "ui/aura/cursor.h"
9 #include "ui/aura/event.h"
10 #include "ui/aura/root_window.h"
11 #include "ui/aura/window.h"
12 #include "ui/aura/window_delegate.h"
13 #include "ui/aura_shell/window_util.h"
14 #include "ui/base/hit_test.h"
15 #include "ui/base/ui_base_types.h"
16
17 namespace aura_shell {
18
19 namespace {
20
21 // Identifies the types of bounds change operations performed by a drag to a
22 // particular window component.
23 const int kBoundsChange_None = 0;
24 const int kBoundsChange_Repositions = 1;
25 const int kBoundsChange_Resizes = 2;
26
27 int GetBoundsChangeForWindowComponent(int window_component) {
28 int bounds_change = kBoundsChange_None;
29 switch (window_component) {
30 case HTTOPLEFT:
31 case HTTOP:
32 case HTTOPRIGHT:
33 case HTLEFT:
34 case HTBOTTOMLEFT:
35 bounds_change |= kBoundsChange_Repositions | kBoundsChange_Resizes;
36 break;
37 case HTCAPTION:
38 bounds_change |= kBoundsChange_Repositions;
39 break;
40 case HTRIGHT:
41 case HTBOTTOMRIGHT:
42 case HTBOTTOM:
43 case HTGROWBOX:
44 bounds_change |= kBoundsChange_Resizes;
45 break;
46 default:
47 break;
48 }
49 return bounds_change;
50 }
51
52 // Possible directions for changing bounds.
53
54 const int kBoundsChangeDirection_None = 0;
55 const int kBoundsChangeDirection_Horizontal = 1;
56 const int kBoundsChangeDirection_Vertical = 2;
57
58 int GetPositionChangeDirectionForWindowComponent(int window_component) {
59 int pos_change_direction = kBoundsChangeDirection_None;
60 switch (window_component) {
61 case HTTOPLEFT:
62 case HTBOTTOMRIGHT:
63 case HTGROWBOX:
64 case HTCAPTION:
65 pos_change_direction |=
66 kBoundsChangeDirection_Horizontal | kBoundsChangeDirection_Vertical;
67 break;
68 case HTTOP:
69 case HTTOPRIGHT:
70 case HTBOTTOM:
71 pos_change_direction |= kBoundsChangeDirection_Vertical;
72 break;
73 case HTBOTTOMLEFT:
74 case HTRIGHT:
75 case HTLEFT:
76 pos_change_direction |= kBoundsChangeDirection_Horizontal;
77 break;
78 default:
79 break;
80 }
81 return pos_change_direction;
82 }
83
84 int GetSizeChangeDirectionForWindowComponent(int window_component) {
85 int size_change_direction = kBoundsChangeDirection_None;
86 switch (window_component) {
87 case HTTOPLEFT:
88 case HTTOPRIGHT:
89 case HTBOTTOMLEFT:
90 case HTBOTTOMRIGHT:
91 case HTGROWBOX:
92 case HTCAPTION:
93 size_change_direction |=
94 kBoundsChangeDirection_Horizontal | kBoundsChangeDirection_Vertical;
95 break;
96 case HTTOP:
97 case HTBOTTOM:
98 size_change_direction |= kBoundsChangeDirection_Vertical;
99 break;
100 case HTRIGHT:
101 case HTLEFT:
102 size_change_direction |= kBoundsChangeDirection_Horizontal;
103 break;
104 default:
105 break;
106 }
107 return size_change_direction;
108 }
109
110 // Returns true for resize components along the right edge, where a drag in
111 // positive x will make the window larger.
112 bool IsRightEdge(int window_component) {
113 return window_component == HTTOPRIGHT ||
114 window_component == HTRIGHT ||
115 window_component == HTBOTTOMRIGHT ||
116 window_component == HTGROWBOX;
117 }
118
119 // Returns true for resize components in along the bottom edge, where a drag
120 // in positive y will make the window larger.
121 bool IsBottomEdge(int window_component) {
122 return window_component == HTBOTTOMLEFT ||
123 window_component == HTBOTTOM ||
124 window_component == HTBOTTOMRIGHT ||
125 window_component == HTGROWBOX;
126 }
127
128 void ToggleMaximizedState(aura::Window* window) {
129 window->SetIntProperty(aura::client::kShowStateKey,
130 IsWindowMaximized(window) ?
131 ui::SHOW_STATE_NORMAL : ui::SHOW_STATE_MAXIMIZED);
132 }
133
134 } // namespace
135
136 ToplevelWindowEventFilter::ToplevelWindowEventFilter(aura::Window* owner)
137 : EventFilter(owner),
138 window_component_(HTNOWHERE) {
139 }
140
141 ToplevelWindowEventFilter::~ToplevelWindowEventFilter() {
142 }
143
144 bool ToplevelWindowEventFilter::PreHandleKeyEvent(aura::Window* target,
145 aura::KeyEvent* event) {
146 return false;
147 }
148
149 bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target,
150 aura::MouseEvent* event) {
151 // Process EventFilters implementation first so that it processes
152 // activation/focus first.
153 switch (event->type()) {
154 case ui::ET_MOUSE_MOVED:
155 UpdateWindowComponentForEvent(target, event);
156 break;
157 case ui::ET_MOUSE_PRESSED:
158 // We also update the current window component here because for the
159 // mouse-drag-release-press case, where the mouse is released and
160 // pressed without mouse move event.
161 UpdateWindowComponentForEvent(target, event);
162 if (window_component_ == HTCAPTION &&
163 event->flags() & ui::EF_IS_DOUBLE_CLICK) {
164 ToggleMaximizedState(target);
165 }
166 UpdateLocationFromEvent(target, event);
167 return GetBoundsChangeForWindowComponent(window_component_) !=
168 kBoundsChange_None;
169 case ui::ET_MOUSE_DRAGGED:
170 return HandleDrag(target, event);
171 case ui::ET_MOUSE_RELEASED:
172 window_component_ = HTNOWHERE;
173 break;
174 default:
175 break;
176 }
177 return false;
178 }
179
180 ui::TouchStatus ToplevelWindowEventFilter::PreHandleTouchEvent(
181 aura::Window* target,
182 aura::TouchEvent* event) {
183 // Process EventFilters implementation first so that it processes
184 // activation/focus first.
185 // TODO(sad): Allow resizing/maximizing etc. from touch?
186 UpdateWindowComponentForEvent(target, event);
187 int bounds_change = GetBoundsChangeForWindowComponent(window_component_);
188 if (bounds_change == kBoundsChange_None)
189 return ui::TOUCH_STATUS_UNKNOWN;
190
191 // Handle touch move by simulate mouse drag with single touch.
192 switch (event->type()) {
193 case ui::ET_TOUCH_PRESSED:
194 UpdateLocationFromEvent(target, event);
195 pressed_touch_ids_.insert(event->touch_id());
196 if (pressed_touch_ids_.size() == 1)
197 return ui::TOUCH_STATUS_START;
198 break;
199 case ui::ET_TOUCH_MOVED:
200 if (pressed_touch_ids_.size() == 1) {
201 if (HandleDrag(target, event))
202 return ui::TOUCH_STATUS_CONTINUE;
203 }
204 break;
205 case ui::ET_TOUCH_RELEASED:
206 pressed_touch_ids_.erase(event->touch_id());
207 if (pressed_touch_ids_.empty()) {
208 window_component_ = HTNOWHERE;
209 return ui::TOUCH_STATUS_END;
210 }
211 break;
212 default:
213 break;
214 }
215 return ui::TOUCH_STATUS_UNKNOWN;
216 }
217
218 void ToplevelWindowEventFilter::MoveWindowToFront(aura::Window* target) {
219 aura::Window* parent = target->parent();
220 aura::Window* child = target;
221 while (parent) {
222 parent->StackChildAtTop(child);
223 if (parent == owner())
224 break;
225 parent = parent->parent();
226 child = child->parent();
227 }
228 }
229
230 bool ToplevelWindowEventFilter::HandleDrag(aura::Window* target,
231 aura::LocatedEvent* event) {
232 // This function only be triggered to move window
233 // by mouse drag or touch move event.
234 DCHECK(event->type() == ui::ET_MOUSE_DRAGGED ||
235 event->type() == ui::ET_TOUCH_MOVED);
236
237 int bounds_change = GetBoundsChangeForWindowComponent(window_component_);
238 if (bounds_change == kBoundsChange_None)
239 return false;
240
241 // Only a normal/default window can be moved/resized.
242 if (target->GetIntProperty(aura::client::kShowStateKey) !=
243 ui::SHOW_STATE_NORMAL &&
244 target->GetIntProperty(aura::client::kShowStateKey) !=
245 ui::SHOW_STATE_DEFAULT)
246 return false;
247
248 // Dragging a window moves the local coordinate frame, so do arithmetic
249 // in the parent coordinate frame.
250 gfx::Point event_location_in_parent(event->location());
251 aura::Window::ConvertPointToWindow(target, target->parent(),
252 &event_location_in_parent);
253 int delta_x = event_location_in_parent.x() - mouse_down_offset_in_parent_.x();
254 int delta_y = event_location_in_parent.y() - mouse_down_offset_in_parent_.y();
255
256 // The minimize size constraint may limit how much we change the window
257 // position. For example, dragging the left edge to the right should stop
258 // repositioning the window when the minimize size is reached.
259 gfx::Size size = GetSizeForDrag(bounds_change, target, &delta_x, &delta_y);
260 gfx::Point origin = GetOriginForDrag(bounds_change, delta_x, delta_y);
261
262 target->SetBounds(gfx::Rect(origin, size));
263 return true;
264 }
265
266 void ToplevelWindowEventFilter::UpdateLocationFromEvent(
267 aura::Window* target,
268 aura::LocatedEvent* event) {
269 mouse_down_bounds_ = target->bounds();
270 mouse_down_offset_in_parent_ = event->location();
271 aura::Window::ConvertPointToWindow(target, target->parent(),
272 &mouse_down_offset_in_parent_);
273 }
274
275 void ToplevelWindowEventFilter::UpdateWindowComponentForEvent(
276 aura::Window* target,
277 aura::LocatedEvent* event) {
278 window_component_ =
279 target->delegate()->GetNonClientComponent(event->location());
280 }
281
282 gfx::Point ToplevelWindowEventFilter::GetOriginForDrag(
283 int bounds_change,
284 int delta_x,
285 int delta_y) const {
286 gfx::Point origin = mouse_down_bounds_.origin();
287 if (bounds_change & kBoundsChange_Repositions) {
288 int pos_change_direction =
289 GetPositionChangeDirectionForWindowComponent(window_component_);
290 if (pos_change_direction & kBoundsChangeDirection_Horizontal)
291 origin.Offset(delta_x, 0);
292 if (pos_change_direction & kBoundsChangeDirection_Vertical)
293 origin.Offset(0, delta_y);
294 }
295 return origin;
296 }
297
298 gfx::Size ToplevelWindowEventFilter::GetSizeForDrag(
299 int bounds_change,
300 aura::Window* target,
301 int* delta_x,
302 int* delta_y) const {
303 gfx::Size size = mouse_down_bounds_.size();
304 if (bounds_change & kBoundsChange_Resizes) {
305 gfx::Size min_size = target->delegate()->GetMinimumSize();
306 int size_change_direction =
307 GetSizeChangeDirectionForWindowComponent(window_component_);
308 size.SetSize(
309 GetWidthForDrag(size_change_direction, min_size.width(), delta_x),
310 GetHeightForDrag(size_change_direction, min_size.height(), delta_y));
311 }
312 return size;
313 }
314
315 int ToplevelWindowEventFilter::GetWidthForDrag(int size_change_direction,
316 int min_width,
317 int* delta_x) const {
318 int width = mouse_down_bounds_.width();
319 if (size_change_direction & kBoundsChangeDirection_Horizontal) {
320 // Along the right edge, positive delta_x increases the window size.
321 int x_multiplier = IsRightEdge(window_component_) ? 1 : -1;
322 width += x_multiplier * (*delta_x);
323
324 // Ensure we don't shrink past the minimum width and clamp delta_x
325 // for the window origin computation.
326 if (width < min_width) {
327 width = min_width;
328 *delta_x = -x_multiplier * (mouse_down_bounds_.width() - min_width);
329 }
330 }
331 return width;
332 }
333
334 int ToplevelWindowEventFilter::GetHeightForDrag(int size_change_direction,
335 int min_height,
336 int* delta_y) const {
337 int height = mouse_down_bounds_.height();
338 if (size_change_direction & kBoundsChangeDirection_Vertical) {
339 // Along the bottom edge, positive delta_y increases the window size.
340 int y_multiplier = IsBottomEdge(window_component_) ? 1 : -1;
341 height += y_multiplier * (*delta_y);
342
343 // Ensure we don't shrink past the minimum height and clamp delta_y
344 // for the window origin computation.
345 if (height < min_height) {
346 height = min_height;
347 *delta_y = -y_multiplier * (mouse_down_bounds_.height() - min_height);
348 }
349 }
350 return height;
351 }
352
353 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura_shell/toplevel_window_event_filter.h ('k') | ui/aura_shell/toplevel_window_event_filter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698