OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/workspace/workspace_window_resizer.h" | 5 #include "ash/wm/workspace/workspace_window_resizer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "ash/display/display_controller.h" | 10 #include "ash/display/display_controller.h" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // |location_in_parent| have the same value and both of them are in | 100 // |location_in_parent| have the same value and both of them are in |
101 // |window()->parent()|'s coordinates, but once the pointer enters the | 101 // |window()->parent()|'s coordinates, but once the pointer enters the |
102 // other root window, you will see an unexpected value on the former. See | 102 // other root window, you will see an unexpected value on the former. See |
103 // comments in wm::GetRootWindowRelativeToWindow() for details. | 103 // comments in wm::GetRootWindowRelativeToWindow() for details. |
104 | 104 |
105 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? | 105 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? |
106 0 : ash::Shell::GetInstance()->GetGridSize(); | 106 0 : ash::Shell::GetInstance()->GetGridSize(); |
107 gfx::Rect bounds = // in |window()->parent()|'s coordinates. | 107 gfx::Rect bounds = // in |window()->parent()|'s coordinates. |
108 CalculateBoundsForDrag(details_, location_in_parent, grid_size); | 108 CalculateBoundsForDrag(details_, location_in_parent, grid_size); |
109 | 109 |
110 if (wm::IsWindowNormal(details_.window)) | 110 if (wm::IsWindowNormal(window())) |
111 AdjustBoundsForMainWindow(&bounds, grid_size); | 111 AdjustBoundsForMainWindow(&bounds, grid_size); |
112 if (bounds != details_.window->bounds()) { | 112 if (bounds != window()->bounds()) { |
113 if (!did_move_or_resize_) | 113 if (!did_move_or_resize_) |
114 RestackWindows(); | 114 RestackWindows(); |
115 did_move_or_resize_ = true; | 115 did_move_or_resize_ = true; |
116 } | 116 } |
117 | 117 |
118 const bool in_original_root = (window()->GetRootWindow() == current_root); | 118 const bool in_original_root = (window()->GetRootWindow() == current_root); |
119 // Hide a phantom window for snapping if the cursor is in another root window. | 119 // Hide a phantom window for snapping if the cursor is in another root window. |
120 if (in_original_root) | 120 if (in_original_root) |
121 UpdateSnapPhantomWindow(location_in_parent, bounds, grid_size); | 121 UpdateSnapPhantomWindow(location_in_parent, bounds, grid_size); |
122 else | 122 else |
123 snap_phantom_window_controller_.reset(); | 123 snap_phantom_window_controller_.reset(); |
124 | 124 |
125 // Show a phantom window for dragging in another root window. | 125 // Show a phantom window for dragging in another root window. |
126 if (HasSecondaryRootWindow()) | 126 if (HasSecondaryRootWindow()) |
127 UpdateDragPhantomWindow(bounds, in_original_root); | 127 UpdateDragPhantomWindow(bounds, in_original_root); |
128 else | 128 else |
129 drag_phantom_window_controller_.reset(); | 129 drag_phantom_window_controller_.reset(); |
130 | 130 |
131 if (!attached_windows_.empty()) | 131 if (!attached_windows_.empty()) |
132 LayoutAttachedWindows(bounds, grid_size); | 132 LayoutAttachedWindows(bounds, grid_size); |
133 if (bounds != details_.window->bounds()) | 133 if (bounds != window()->bounds()) |
134 details_.window->SetBounds(bounds); | 134 window()->SetBounds(bounds); |
135 // WARNING: we may have been deleted. | 135 // WARNING: we may have been deleted. |
136 } | 136 } |
137 | 137 |
138 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 138 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
139 window()->layer()->SetOpacity(details_.initial_opacity); | 139 window()->layer()->SetOpacity(details_.initial_opacity); |
140 drag_phantom_window_controller_.reset(); | 140 drag_phantom_window_controller_.reset(); |
141 snap_phantom_window_controller_.reset(); | 141 snap_phantom_window_controller_.reset(); |
142 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 142 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
143 return; | 143 return; |
144 | 144 |
145 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { | 145 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { |
146 if (!GetRestoreBoundsInScreen(details_.window)) | 146 if (!GetRestoreBoundsInScreen(window())) |
147 SetRestoreBoundsInParent(details_.window, details_.initial_bounds); | 147 SetRestoreBoundsInParent(window(), details_.initial_bounds); |
148 details_.window->SetBounds(snap_sizer_->target_bounds()); | 148 window()->SetBounds(snap_sizer_->target_bounds()); |
149 return; | 149 return; |
150 } | 150 } |
151 | 151 |
152 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? | 152 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? |
153 0 : ash::Shell::GetInstance()->GetGridSize(); | 153 0 : ash::Shell::GetInstance()->GetGridSize(); |
154 gfx::Rect bounds(GetFinalBounds(details_.window->bounds(), grid_size)); | 154 gfx::Rect bounds(GetFinalBounds(window()->bounds(), grid_size)); |
155 | 155 |
156 // Check if the destination is another display. | 156 // Check if the destination is another display. |
157 gfx::Point last_mouse_location_in_screen = last_mouse_location_; | 157 gfx::Point last_mouse_location_in_screen = last_mouse_location_; |
158 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); | 158 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); |
159 const gfx::Display dst_display = | 159 const gfx::Display dst_display = |
160 gfx::Screen::GetDisplayNearestPoint(last_mouse_location_in_screen); | 160 gfx::Screen::GetDisplayNearestPoint(last_mouse_location_in_screen); |
161 | 161 |
162 if (dst_display.id() != | 162 if (dst_display.id() != |
163 gfx::Screen::GetDisplayNearestWindow(window()->GetRootWindow()).id()) { | 163 gfx::Screen::GetDisplayNearestWindow(window()->GetRootWindow()).id()) { |
164 // Don't animate when moving to another display. | 164 // Don't animate when moving to another display. |
165 const gfx::Rect dst_bounds = | 165 const gfx::Rect dst_bounds = |
166 ScreenAsh::ConvertRectToScreen(details_.window->parent(), bounds); | 166 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); |
167 details_.window->SetBoundsInScreen(dst_bounds, dst_display); | 167 window()->SetBoundsInScreen(dst_bounds, dst_display); |
168 return; | 168 return; |
169 } | 169 } |
170 | 170 |
171 if (grid_size <= 1 || bounds == details_.window->bounds()) | 171 if (grid_size <= 1 || bounds == window()->bounds()) |
172 return; | 172 return; |
173 | 173 |
174 if (bounds.size() != details_.window->bounds().size()) { | 174 if (bounds.size() != window()->bounds().size()) { |
175 // Don't attempt to animate a size change. | 175 // Don't attempt to animate a size change. |
176 details_.window->SetBounds(bounds); | 176 window()->SetBounds(bounds); |
177 return; | 177 return; |
178 } | 178 } |
179 | 179 |
180 ui::ScopedLayerAnimationSettings scoped_setter( | 180 ui::ScopedLayerAnimationSettings scoped_setter( |
181 details_.window->layer()->GetAnimator()); | 181 window()->layer()->GetAnimator()); |
182 // Use a small duration since the grid is small. | 182 // Use a small duration since the grid is small. |
183 scoped_setter.SetTransitionDuration( | 183 scoped_setter.SetTransitionDuration( |
184 base::TimeDelta::FromMilliseconds(kSnapDurationMS)); | 184 base::TimeDelta::FromMilliseconds(kSnapDurationMS)); |
185 details_.window->SetBounds(bounds); | 185 window()->SetBounds(bounds); |
186 } | 186 } |
187 | 187 |
188 void WorkspaceWindowResizer::RevertDrag() { | 188 void WorkspaceWindowResizer::RevertDrag() { |
189 window()->layer()->SetOpacity(details_.initial_opacity); | 189 window()->layer()->SetOpacity(details_.initial_opacity); |
190 drag_phantom_window_controller_.reset(); | 190 drag_phantom_window_controller_.reset(); |
191 snap_phantom_window_controller_.reset(); | 191 snap_phantom_window_controller_.reset(); |
192 | 192 |
193 if (!did_move_or_resize_) | 193 if (!did_move_or_resize_) |
194 return; | 194 return; |
195 | 195 |
196 details_.window->SetBounds(details_.initial_bounds); | 196 window()->SetBounds(details_.initial_bounds); |
197 if (details_.window_component == HTRIGHT) { | 197 if (details_.window_component == HTRIGHT) { |
198 int last_x = details_.initial_bounds.right(); | 198 int last_x = details_.initial_bounds.right(); |
199 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 199 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
200 gfx::Rect bounds(attached_windows_[i]->bounds()); | 200 gfx::Rect bounds(attached_windows_[i]->bounds()); |
201 bounds.set_x(last_x); | 201 bounds.set_x(last_x); |
202 bounds.set_width(initial_size_[i]); | 202 bounds.set_width(initial_size_[i]); |
203 attached_windows_[i]->SetBounds(bounds); | 203 attached_windows_[i]->SetBounds(bounds); |
204 last_x = attached_windows_[i]->bounds().right(); | 204 last_x = attached_windows_[i]->bounds().right(); |
205 } | 205 } |
206 } else { | 206 } else { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 sizes->push_back(size); | 355 sizes->push_back(size); |
356 } | 356 } |
357 } | 357 } |
358 } | 358 } |
359 | 359 |
360 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( | 360 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
361 gfx::Rect* bounds, int grid_size) const { | 361 gfx::Rect* bounds, int grid_size) const { |
362 // Always keep kMinOnscreenHeight on the bottom except when an extended | 362 // Always keep kMinOnscreenHeight on the bottom except when an extended |
363 // display is available and a window is being dragged. | 363 // display is available and a window is being dragged. |
364 gfx::Rect work_area( | 364 gfx::Rect work_area( |
365 ScreenAsh::GetDisplayWorkAreaBoundsInParent(details_.window)); | 365 ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
366 int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, | 366 int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, |
367 grid_size); | 367 grid_size); |
368 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && | 368 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
369 bounds->y() > max_y) { | 369 bounds->y() > max_y) { |
370 bounds->set_y(max_y); | 370 bounds->set_y(max_y); |
371 } | 371 } |
372 | 372 |
373 // Don't allow dragging above the top of the display except when an extended | 373 // Don't allow dragging above the top of the display except when an extended |
374 // display is available and a window is being dragged. | 374 // display is available and a window is being dragged. |
375 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && | 375 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 bounds->height() < (bottom_edge - top_edge)) { | 414 bounds->height() < (bottom_edge - top_edge)) { |
415 // Only snap to the bottom if the window is smaller than the work area. | 415 // Only snap to the bottom if the window is smaller than the work area. |
416 // Doing otherwise can lead to window snapping in weird ways as it bounces | 416 // Doing otherwise can lead to window snapping in weird ways as it bounces |
417 // between snapping to top then bottom. | 417 // between snapping to top then bottom. |
418 bounds->set_y(bottom_edge - bounds->height()); | 418 bounds->set_y(bottom_edge - bounds->height()); |
419 } | 419 } |
420 } | 420 } |
421 | 421 |
422 bool WorkspaceWindowResizer::TouchesBottomOfScreen() const { | 422 bool WorkspaceWindowResizer::TouchesBottomOfScreen() const { |
423 gfx::Rect work_area( | 423 gfx::Rect work_area( |
424 ScreenAsh::GetDisplayWorkAreaBoundsInParent(details_.window)); | 424 ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
425 return (attached_windows_.empty() && | 425 return (attached_windows_.empty() && |
426 details_.window->bounds().bottom() == work_area.bottom()) || | 426 window()->bounds().bottom() == work_area.bottom()) || |
427 (!attached_windows_.empty() && | 427 (!attached_windows_.empty() && |
428 attached_windows_.back()->bounds().bottom() == work_area.bottom()); | 428 attached_windows_.back()->bounds().bottom() == work_area.bottom()); |
429 } | 429 } |
430 | 430 |
431 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { | 431 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { |
432 return PrimaryAxisCoordinate(size.width(), size.height()); | 432 return PrimaryAxisCoordinate(size.width(), size.height()); |
433 } | 433 } |
434 | 434 |
435 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { | 435 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { |
436 switch (details_.window_component) { | 436 switch (details_.window_component) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 501 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
502 snap_phantom_window_controller_.reset(); | 502 snap_phantom_window_controller_.reset(); |
503 snap_sizer_.reset(); | 503 snap_sizer_.reset(); |
504 if (snap_type_ == SNAP_NONE) | 504 if (snap_type_ == SNAP_NONE) |
505 return; | 505 return; |
506 } | 506 } |
507 if (!snap_sizer_.get()) { | 507 if (!snap_sizer_.get()) { |
508 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? | 508 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? |
509 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | 509 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
510 snap_sizer_.reset( | 510 snap_sizer_.reset( |
511 new SnapSizer(details_.window, location, edge, grid_size)); | 511 new SnapSizer(window(), location, edge, grid_size)); |
512 } else { | 512 } else { |
513 snap_sizer_->Update(location); | 513 snap_sizer_->Update(location); |
514 } | 514 } |
515 if (!snap_phantom_window_controller_.get()) { | 515 if (!snap_phantom_window_controller_.get()) { |
516 snap_phantom_window_controller_.reset( | 516 snap_phantom_window_controller_.reset( |
517 new PhantomWindowController(details_.window)); | 517 new PhantomWindowController(window())); |
518 } | 518 } |
519 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 519 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
520 details_.window->parent(), snap_sizer_->target_bounds())); | 520 window()->parent(), snap_sizer_->target_bounds())); |
521 } | 521 } |
522 | 522 |
523 void WorkspaceWindowResizer::RestackWindows() { | 523 void WorkspaceWindowResizer::RestackWindows() { |
524 if (attached_windows_.empty()) | 524 if (attached_windows_.empty()) |
525 return; | 525 return; |
526 // Build a map from index in children to window, returning if there is a | 526 // Build a map from index in children to window, returning if there is a |
527 // window with a different parent. | 527 // window with a different parent. |
528 typedef std::map<size_t, aura::Window*> IndexToWindowMap; | 528 typedef std::map<size_t, aura::Window*> IndexToWindowMap; |
529 IndexToWindowMap map; | 529 IndexToWindowMap map; |
530 aura::Window* parent = details_.window->parent(); | 530 aura::Window* parent = window()->parent(); |
531 const aura::Window::Windows& windows(parent->children()); | 531 const aura::Window::Windows& windows(parent->children()); |
532 map[std::find(windows.begin(), windows.end(), details_.window) - | 532 map[std::find(windows.begin(), windows.end(), window()) - |
533 windows.begin()] = details_.window; | 533 windows.begin()] = window(); |
534 for (std::vector<aura::Window*>::const_iterator i = | 534 for (std::vector<aura::Window*>::const_iterator i = |
535 attached_windows_.begin(); i != attached_windows_.end(); ++i) { | 535 attached_windows_.begin(); i != attached_windows_.end(); ++i) { |
536 if ((*i)->parent() != parent) | 536 if ((*i)->parent() != parent) |
537 return; | 537 return; |
538 size_t index = | 538 size_t index = |
539 std::find(windows.begin(), windows.end(), *i) - windows.begin(); | 539 std::find(windows.begin(), windows.end(), *i) - windows.begin(); |
540 map[index] = *i; | 540 map[index] = *i; |
541 } | 541 } |
542 | 542 |
543 // Reorder the windows starting at the topmost. | 543 // Reorder the windows starting at the topmost. |
544 parent->StackChildAtTop(map.rbegin()->second); | 544 parent->StackChildAtTop(map.rbegin()->second); |
545 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 545 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
546 i != map.rend(); ) { | 546 i != map.rend(); ) { |
547 aura::Window* window = i->second; | 547 aura::Window* window = i->second; |
548 ++i; | 548 ++i; |
549 if (i != map.rend()) | 549 if (i != map.rend()) |
550 parent->StackChildBelow(i->second, window); | 550 parent->StackChildBelow(i->second, window); |
551 } | 551 } |
552 } | 552 } |
553 | 553 |
554 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 554 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( |
555 const gfx::Point& location) const { | 555 const gfx::Point& location) const { |
556 // TODO: this likely only wants total display area, not the area of a single | 556 // TODO: this likely only wants total display area, not the area of a single |
557 // display. | 557 // display. |
558 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(details_.window)); | 558 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); |
559 if (location.x() <= area.x()) | 559 if (location.x() <= area.x()) |
560 return SNAP_LEFT_EDGE; | 560 return SNAP_LEFT_EDGE; |
561 if (location.x() >= area.right() - 1) | 561 if (location.x() >= area.right() - 1) |
562 return SNAP_RIGHT_EDGE; | 562 return SNAP_RIGHT_EDGE; |
563 return SNAP_NONE; | 563 return SNAP_NONE; |
564 } | 564 } |
565 | 565 |
566 bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const { | 566 bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const { |
567 return (details_.window_component == HTCAPTION) && | 567 return (details_.window_component == HTCAPTION) && |
568 (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) && | 568 (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) && |
569 (window()->type() == aura::client::WINDOW_TYPE_NORMAL); | 569 (window()->type() == aura::client::WINDOW_TYPE_NORMAL); |
570 } | 570 } |
571 | 571 |
572 } // namespace internal | 572 } // namespace internal |
573 } // namespace ash | 573 } // namespace ash |
OLD | NEW |