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 "ash/shell.h" | 7 #include "ash/shell.h" |
8 #include "ash/wm/property_util.h" | 8 #include "ash/wm/property_util.h" |
9 #include "ash/wm/root_window_event_filter.h" | 9 #include "ash/wm/root_window_event_filter.h" |
10 #include "ash/wm/window_util.h" | 10 #include "ash/wm/window_util.h" |
11 #include "ash/wm/workspace/phantom_window_controller.h" | 11 #include "ash/wm/workspace/phantom_window_controller.h" |
| 12 #include "ash/wm/workspace/snap_sizer.h" |
12 #include "ui/aura/window.h" | 13 #include "ui/aura/window.h" |
13 #include "ui/aura/window_delegate.h" | 14 #include "ui/aura/window_delegate.h" |
14 #include "ui/aura/window_property.h" | 15 #include "ui/aura/window_property.h" |
15 #include "ui/base/hit_test.h" | 16 #include "ui/base/hit_test.h" |
16 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" | 17 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" |
17 #include "ui/gfx/compositor/layer.h" | 18 #include "ui/gfx/compositor/layer.h" |
18 #include "ui/gfx/screen.h" | 19 #include "ui/gfx/screen.h" |
19 #include "ui/gfx/transform.h" | 20 #include "ui/gfx/transform.h" |
20 | 21 |
21 DECLARE_WINDOW_PROPERTY_TYPE(int) | 22 DECLARE_WINDOW_PROPERTY_TYPE(int) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 int GetWidthBeforeObscured(aura::Window* window) { | 59 int GetWidthBeforeObscured(aura::Window* window) { |
59 return window->GetProperty(kWidthBeforeObscuredKey); | 60 return window->GetProperty(kWidthBeforeObscuredKey); |
60 } | 61 } |
61 | 62 |
62 void ClearWidthBeforeObscured(aura::Window* window) { | 63 void ClearWidthBeforeObscured(aura::Window* window) { |
63 window->SetProperty(kWidthBeforeObscuredKey, 0); | 64 window->SetProperty(kWidthBeforeObscuredKey, 0); |
64 } | 65 } |
65 | 66 |
66 } // namespace | 67 } // namespace |
67 | 68 |
68 WorkspaceWindowResizer::PhantomPlacement::PhantomPlacement() : type(TYPE_NONE) { | |
69 } | |
70 | |
71 WorkspaceWindowResizer::PhantomPlacement::~PhantomPlacement() { | |
72 } | |
73 | |
74 // static | 69 // static |
75 const int WorkspaceWindowResizer::kMinOnscreenSize = 20; | 70 const int WorkspaceWindowResizer::kMinOnscreenSize = 20; |
76 | 71 |
77 WorkspaceWindowResizer::~WorkspaceWindowResizer() { | 72 WorkspaceWindowResizer::~WorkspaceWindowResizer() { |
78 if (root_filter_) | 73 if (root_filter_) |
79 root_filter_->UnlockCursor(); | 74 root_filter_->UnlockCursor(); |
80 } | 75 } |
81 | 76 |
82 // static | 77 // static |
83 gfx::Rect WorkspaceWindowResizer::GetBoundsForWindowAlongEdge( | |
84 aura::Window* window, | |
85 WorkspaceWindowResizer::EdgeType edge, | |
86 int grid_size) { | |
87 gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window)); | |
88 int y = WindowResizer::AlignToGridRoundUp(work_area.y(), grid_size); | |
89 int max_y = | |
90 WindowResizer::AlignToGridRoundDown(work_area.bottom(), grid_size); | |
91 if (edge == LEFT_EDGE) { | |
92 int x = WindowResizer::AlignToGridRoundUp(work_area.x(), grid_size); | |
93 int mid_x = WindowResizer::AlignToGridRoundUp( | |
94 work_area.x() + work_area.width() / 2, grid_size); | |
95 return gfx::Rect(x, y, mid_x - x, max_y - y); | |
96 } | |
97 int x = WindowResizer::AlignToGridRoundUp( | |
98 work_area.x() + work_area.width() / 2, grid_size); | |
99 int max_x = WindowResizer::AlignToGridRoundDown(work_area.right(), grid_size); | |
100 return gfx::Rect(x , y, max_x - x, max_y - y); | |
101 } | |
102 | |
103 // static | |
104 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( | 78 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
105 aura::Window* window, | 79 aura::Window* window, |
106 const gfx::Point& location, | 80 const gfx::Point& location, |
107 int window_component, | 81 int window_component, |
108 int grid_size, | 82 int grid_size, |
109 const std::vector<aura::Window*>& attached_windows) { | 83 const std::vector<aura::Window*>& attached_windows) { |
110 Details details(window, location, window_component, grid_size); | 84 Details details(window, location, window_component, grid_size); |
111 return details.is_resizable ? | 85 return details.is_resizable ? |
112 new WorkspaceWindowResizer(details, attached_windows) : NULL; | 86 new WorkspaceWindowResizer(details, attached_windows) : NULL; |
113 } | 87 } |
(...skipping 11 matching lines...) Expand all Loading... |
125 else | 99 else |
126 LayoutAttachedWindowsVertically(bounds); | 100 LayoutAttachedWindowsVertically(bounds); |
127 } | 101 } |
128 if (bounds != details_.window->bounds()) | 102 if (bounds != details_.window->bounds()) |
129 details_.window->SetBounds(bounds); | 103 details_.window->SetBounds(bounds); |
130 // WARNING: we may have been deleted. | 104 // WARNING: we may have been deleted. |
131 } | 105 } |
132 | 106 |
133 void WorkspaceWindowResizer::CompleteDrag() { | 107 void WorkspaceWindowResizer::CompleteDrag() { |
134 if (phantom_window_controller_.get()) { | 108 if (phantom_window_controller_.get()) { |
135 if (phantom_placement_.type == TYPE_DESTINATION) | 109 if (snap_type_ == SNAP_DESTINATION) |
136 phantom_window_controller_->DelayedClose(kSnapDurationMS); | 110 phantom_window_controller_->DelayedClose(kSnapDurationMS); |
137 phantom_window_controller_.reset(); | 111 phantom_window_controller_.reset(); |
138 } | 112 } |
139 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 113 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
140 return; | 114 return; |
141 | 115 |
142 if (phantom_placement_.type == TYPE_LEFT_EDGE || | 116 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { |
143 phantom_placement_.type == TYPE_RIGHT_EDGE) { | |
144 if (!GetRestoreBounds(details_.window)) | 117 if (!GetRestoreBounds(details_.window)) |
145 SetRestoreBounds(details_.window, details_.initial_bounds); | 118 SetRestoreBounds(details_.window, details_.initial_bounds); |
146 details_.window->SetBounds(phantom_placement_.bounds); | 119 details_.window->SetBounds(snap_sizer_->target_bounds()); |
147 return; | 120 return; |
148 } | 121 } |
149 | 122 |
150 if (details_.grid_size <= 1) | 123 if (details_.grid_size <= 1) |
151 return; | 124 return; |
152 | 125 |
153 gfx::Rect bounds(GetFinalBounds()); | 126 gfx::Rect bounds(GetFinalBounds()); |
154 if (bounds == details_.window->bounds()) | 127 if (bounds == details_.window->bounds()) |
155 return; | 128 return; |
156 | 129 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 WorkspaceWindowResizer::WorkspaceWindowResizer( | 172 WorkspaceWindowResizer::WorkspaceWindowResizer( |
200 const Details& details, | 173 const Details& details, |
201 const std::vector<aura::Window*>& attached_windows) | 174 const std::vector<aura::Window*>& attached_windows) |
202 : details_(details), | 175 : details_(details), |
203 constrain_size_(wm::IsWindowNormal(details.window)), | 176 constrain_size_(wm::IsWindowNormal(details.window)), |
204 attached_windows_(attached_windows), | 177 attached_windows_(attached_windows), |
205 did_move_or_resize_(false), | 178 did_move_or_resize_(false), |
206 root_filter_(NULL), | 179 root_filter_(NULL), |
207 total_min_(0), | 180 total_min_(0), |
208 total_initial_size_(0), | 181 total_initial_size_(0), |
| 182 snap_type_(SNAP_NONE), |
209 num_mouse_moves_since_bounds_change_(0) { | 183 num_mouse_moves_since_bounds_change_(0) { |
210 DCHECK(details_.is_resizable); | 184 DCHECK(details_.is_resizable); |
211 root_filter_ = Shell::GetInstance()->root_filter(); | 185 root_filter_ = Shell::GetInstance()->root_filter(); |
212 if (root_filter_) | 186 if (root_filter_) |
213 root_filter_->LockCursor(); | 187 root_filter_->LockCursor(); |
214 | 188 |
215 // We should never be in a situation where we have an attached window and not | 189 // We should never be in a situation where we have an attached window and not |
216 // constrain the size. The only case we don't constrain size is for dragging | 190 // constrain the size. The only case we don't constrain size is for dragging |
217 // tabs, which should never have an attached window. | 191 // tabs, which should never have an attached window. |
218 DCHECK(attached_windows_.empty() || constrain_size_); | 192 DCHECK(attached_windows_.empty() || constrain_size_); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 default: | 430 default: |
457 NOTREACHED(); | 431 NOTREACHED(); |
458 } | 432 } |
459 return 0; | 433 return 0; |
460 } | 434 } |
461 | 435 |
462 void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location) { | 436 void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location) { |
463 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 437 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
464 return; | 438 return; |
465 | 439 |
466 PhantomPlacement last_placement = phantom_placement_; | 440 snap_type_ = GetSnapType(location); |
467 phantom_placement_ = GetPhantomPlacement(location); | 441 if (snap_type_ == SNAP_NONE) { |
468 if (phantom_placement_.type == TYPE_NONE) { | |
469 phantom_window_controller_.reset(); | 442 phantom_window_controller_.reset(); |
| 443 snap_sizer_.reset(); |
470 return; | 444 return; |
471 } | 445 } |
472 PhantomWindowController::Type phantom_type; | 446 PhantomWindowController::Type phantom_type; |
473 if (phantom_placement_.type == TYPE_LEFT_EDGE || | 447 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) |
474 phantom_placement_.type == TYPE_RIGHT_EDGE) { | |
475 phantom_type = PhantomWindowController::TYPE_EDGE; | 448 phantom_type = PhantomWindowController::TYPE_EDGE; |
476 UpdatePhantomWindowBoundsAlongEdge(last_placement); | 449 else |
477 } else { | |
478 phantom_type = PhantomWindowController::TYPE_DESTINATION; | 450 phantom_type = PhantomWindowController::TYPE_DESTINATION; |
479 } | |
480 if (phantom_window_controller_.get() && | 451 if (phantom_window_controller_.get() && |
481 phantom_window_controller_->type() != phantom_type) { | 452 phantom_window_controller_->type() != phantom_type) { |
482 phantom_window_controller_.reset(); | 453 phantom_window_controller_.reset(); |
| 454 snap_sizer_.reset(); |
| 455 } |
| 456 if (phantom_type == PhantomWindowController::TYPE_EDGE) { |
| 457 if (!snap_sizer_.get()) { |
| 458 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? |
| 459 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| 460 snap_sizer_.reset( |
| 461 new SnapSizer(details_.window, location, edge, details_.grid_size)); |
| 462 } else { |
| 463 snap_sizer_->Update(location); |
| 464 } |
483 } | 465 } |
484 if (!phantom_window_controller_.get()) { | 466 if (!phantom_window_controller_.get()) { |
485 phantom_window_controller_.reset( | 467 phantom_window_controller_.reset( |
486 new PhantomWindowController(details_.window, phantom_type, | 468 new PhantomWindowController(details_.window, phantom_type, |
487 kPhantomDelayMS)); | 469 kPhantomDelayMS)); |
488 } | 470 } |
489 phantom_window_controller_->Show(phantom_placement_.bounds); | 471 gfx::Rect bounds; |
| 472 if (snap_sizer_.get()) |
| 473 bounds = snap_sizer_->target_bounds(); |
| 474 else |
| 475 bounds = GetFinalBounds(); |
| 476 phantom_window_controller_->Show(bounds); |
490 } | 477 } |
491 | 478 |
492 void WorkspaceWindowResizer::UpdatePhantomWindowBoundsAlongEdge( | 479 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( |
493 const PhantomPlacement& last_placement) { | 480 const gfx::Point& location) const { |
494 if (last_placement.type == phantom_placement_.type) { | |
495 int grid_size = std::max(1, details_.grid_size); | |
496 if (++num_mouse_moves_since_bounds_change_ >= grid_size / 2) { | |
497 gfx::Rect area(gfx::Screen::GetMonitorAreaNearestWindow(details_.window)); | |
498 gfx::Rect bounds(last_placement.bounds); | |
499 if (last_placement.type == TYPE_LEFT_EDGE) { | |
500 bounds.set_width(std::min(WindowResizer::AlignToGridRoundDown( | |
501 area.width() - bounds.x(), grid_size), | |
502 bounds.width() + grid_size)); | |
503 } else { | |
504 int x = std::max( | |
505 WindowResizer::AlignToGridRoundUp(area.x(), grid_size), | |
506 bounds.x() - grid_size); | |
507 bounds.set_width(phantom_placement_.bounds.width() - x); | |
508 bounds.set_x(x); | |
509 } | |
510 phantom_placement_.bounds = bounds; | |
511 num_mouse_moves_since_bounds_change_ = 0; | |
512 } else { | |
513 phantom_placement_.bounds = last_placement.bounds; | |
514 } | |
515 } else { | |
516 num_mouse_moves_since_bounds_change_ = 0; | |
517 } | |
518 } | |
519 | |
520 WorkspaceWindowResizer::PhantomPlacement | |
521 WorkspaceWindowResizer::GetPhantomPlacement(const gfx::Point& location) { | |
522 // TODO: this likely only wants total monitor area, not the area of a single | 481 // TODO: this likely only wants total monitor area, not the area of a single |
523 // monitor. | 482 // monitor. |
524 PhantomPlacement placement; | |
525 gfx::Rect area(gfx::Screen::GetMonitorAreaNearestWindow(details_.window)); | 483 gfx::Rect area(gfx::Screen::GetMonitorAreaNearestWindow(details_.window)); |
526 if (location.x() <= area.x()) { | 484 if (location.x() <= area.x()) |
527 placement.type = TYPE_LEFT_EDGE; | 485 return SNAP_LEFT_EDGE; |
528 placement.bounds = GetBoundsForWindowAlongEdge( | 486 if (location.x() >= area.right() - 1) |
529 details_.window, LEFT_EDGE, details_.grid_size); | 487 return SNAP_RIGHT_EDGE; |
530 } else if (location.x() >= area.right() - 1) { | 488 if (details_.grid_size > 1 && wm::IsWindowNormal(details_.window)) |
531 placement.type = TYPE_RIGHT_EDGE; | 489 return SNAP_DESTINATION; |
532 placement.bounds = GetBoundsForWindowAlongEdge( | 490 return SNAP_NONE; |
533 details_.window, RIGHT_EDGE, details_.grid_size); | |
534 } else if (details_.grid_size > 1 && wm::IsWindowNormal(details_.window)) { | |
535 placement.bounds = GetFinalBounds(); | |
536 placement.type = TYPE_DESTINATION; | |
537 } | |
538 return placement; | |
539 } | 491 } |
540 | 492 |
541 } // namespace internal | 493 } // namespace internal |
542 } // namespace ash | 494 } // namespace ash |
OLD | NEW |