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 22 matching lines...) Expand all Loading... | |
33 | 33 |
34 // Duration of the animation when snapping the window into place. | 34 // Duration of the animation when snapping the window into place. |
35 const int kSnapDurationMS = 100; | 35 const int kSnapDurationMS = 100; |
36 | 36 |
37 // Returns true if should snap to the edge. | 37 // Returns true if should snap to the edge. |
38 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { | 38 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { |
39 return distance_from_edge <= grid_size / 2 && | 39 return distance_from_edge <= grid_size / 2 && |
40 distance_from_edge > -grid_size * 2; | 40 distance_from_edge > -grid_size * 2; |
41 } | 41 } |
42 | 42 |
43 bool HasSecondaryRootWindow() { | |
44 return Shell::GetAllRootWindows().size() > 1; | |
45 } | |
46 | |
47 aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) { | |
48 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | |
49 if (root_windows.size() < 2) | |
50 return NULL; // an extended display is not connected. | |
51 DCHECK_EQ(2U, root_windows.size()); | |
52 if (root_windows[0] == root_window) | |
53 return root_windows[1]; | |
54 return root_windows[0]; | |
55 } | |
56 | |
43 } // namespace | 57 } // namespace |
44 | 58 |
45 // static | 59 // static |
46 const int WorkspaceWindowResizer::kMinOnscreenSize = 20; | 60 const int WorkspaceWindowResizer::kMinOnscreenSize = 20; |
47 | 61 |
48 // static | 62 // static |
49 const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; | 63 const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; |
50 | 64 |
51 WorkspaceWindowResizer::~WorkspaceWindowResizer() { | 65 WorkspaceWindowResizer::~WorkspaceWindowResizer() { |
52 Shell* shell = Shell::GetInstance(); | 66 Shell* shell = Shell::GetInstance(); |
53 if (details_.window_component == HTCAPTION) | 67 if (details_.window_component == HTCAPTION) |
54 shell->display_controller()->set_allow_warp_during_lock(false); | 68 shell->display_controller()->set_allow_warp_during_lock(false); |
55 shell->cursor_manager()->UnlockCursor(); | 69 shell->cursor_manager()->UnlockCursor(); |
56 } | 70 } |
57 | 71 |
58 // static | 72 // static |
59 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( | 73 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
60 aura::Window* window, | 74 aura::Window* window, |
61 const gfx::Point& location_in_parent, | 75 const gfx::Point& location_in_parent, |
62 int window_component, | 76 int window_component, |
63 const std::vector<aura::Window*>& attached_windows) { | 77 const std::vector<aura::Window*>& attached_windows) { |
64 Details details(window, location_in_parent, window_component); | 78 Details details(window, location_in_parent, window_component); |
65 return details.is_resizable ? | 79 return details.is_resizable ? |
66 new WorkspaceWindowResizer(details, attached_windows) : NULL; | 80 new WorkspaceWindowResizer(details, attached_windows) : NULL; |
67 } | 81 } |
68 | 82 |
69 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_screen, | 83 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_screen, |
70 int event_flags) { | 84 int event_flags) { |
71 // TODO(yusukes): Implement dragging a window from one display to another. | |
72 aura::RootWindow* current_root = Shell::GetRootWindowAt(location_in_screen); | 85 aura::RootWindow* current_root = Shell::GetRootWindowAt(location_in_screen); |
73 if (current_root != window()->GetRootWindow()) | 86 const bool in_original_root = (window()->GetRootWindow() == current_root); |
74 return; | |
75 | 87 |
76 gfx::Point location_in_root = location_in_screen; | 88 gfx::Point location_in_root = location_in_screen; |
77 aura::client::GetScreenPositionClient(current_root)-> | 89 aura::client::GetScreenPositionClient(current_root)-> |
78 ConvertPointFromScreen(current_root, &location_in_root); | 90 ConvertPointFromScreen(current_root, &location_in_root); |
79 | 91 |
80 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? | 92 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? |
81 0 : ash::Shell::GetInstance()->GetGridSize(); | 93 0 : ash::Shell::GetInstance()->GetGridSize(); |
82 gfx::Rect bounds = | 94 gfx::Rect bounds = // in |window()->GetRootWindow()|'s coordinates. |
83 CalculateBoundsForDrag(details_, location_in_root, grid_size); | 95 CalculateBoundsForDrag(details_, location_in_screen, grid_size); |
84 | 96 |
85 if (wm::IsWindowNormal(details_.window)) | 97 if (wm::IsWindowNormal(details_.window)) |
86 AdjustBoundsForMainWindow(&bounds, grid_size); | 98 AdjustBoundsForMainWindow(&bounds, grid_size); |
87 if (bounds != details_.window->bounds()) { | 99 if (bounds != details_.window->bounds()) { |
88 if (!did_move_or_resize_) | 100 if (!did_move_or_resize_) |
89 RestackWindows(); | 101 RestackWindows(); |
90 did_move_or_resize_ = true; | 102 did_move_or_resize_ = true; |
91 } | 103 } |
92 UpdatePhantomWindow(location_in_root, bounds, grid_size); | 104 |
105 // Hide a phantom window for snapping if the cursor is in another root window. | |
106 if (in_original_root) | |
107 UpdatePhantomWindow(location_in_root, bounds, grid_size); | |
108 else | |
109 phantom_window_controller_.reset(); | |
110 | |
111 // Show a phantom window for dragging in another root window. | |
112 aura::RootWindow* another_root = | |
113 GetAnotherRootWindow(window()->GetRootWindow()); | |
114 gfx::Rect bounds_in_screen = | |
115 ScreenAsh::ConvertRectToScreen(window()->GetRootWindow(), bounds); | |
116 UpdateDragPhantomWindow(another_root, bounds_in_screen); | |
117 | |
93 if (!attached_windows_.empty()) | 118 if (!attached_windows_.empty()) |
94 LayoutAttachedWindows(bounds, grid_size); | 119 LayoutAttachedWindows(bounds, grid_size); |
95 if (bounds != details_.window->bounds()) | 120 if (bounds != details_.window->bounds()) |
96 details_.window->SetBounds(bounds); | 121 details_.window->SetBounds(bounds); |
97 // WARNING: we may have been deleted. | 122 // WARNING: we may have been deleted. |
98 } | 123 } |
99 | 124 |
100 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 125 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
126 drag_phantom_window_controller_.reset(); | |
101 phantom_window_controller_.reset(); | 127 phantom_window_controller_.reset(); |
102 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 128 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
103 return; | 129 return; |
104 | 130 |
105 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { | 131 if (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE) { |
106 if (!GetRestoreBoundsInScreen(details_.window)) | 132 if (!GetRestoreBoundsInScreen(details_.window)) |
107 SetRestoreBoundsInParent(details_.window, details_.initial_bounds); | 133 SetRestoreBoundsInParent(details_.window, details_.initial_bounds); |
108 details_.window->SetBounds(snap_sizer_->target_bounds()); | 134 details_.window->SetBounds(snap_sizer_->target_bounds()); |
109 return; | 135 return; |
110 } | 136 } |
111 | 137 |
112 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? | 138 int grid_size = event_flags & ui::EF_CONTROL_DOWN ? |
113 0 : ash::Shell::GetInstance()->GetGridSize(); | 139 0 : ash::Shell::GetInstance()->GetGridSize(); |
114 if (grid_size <= 1) | 140 if (grid_size <= 1) |
115 return; | 141 return; |
116 | 142 |
117 gfx::Rect bounds(GetFinalBounds(details_.window->bounds(), grid_size)); | 143 gfx::Rect bounds(GetFinalBounds(details_.window->bounds(), grid_size)); |
118 if (bounds == details_.window->bounds()) | 144 if (bounds == details_.window->bounds()) |
119 return; | 145 return; |
120 | 146 |
121 if (bounds.size() != details_.window->bounds().size()) { | 147 if (bounds.size() != details_.window->bounds().size()) { |
122 // Don't attempt to animate a size change. | 148 // Don't attempt to animate a size change. |
123 details_.window->SetBounds(bounds); | 149 details_.window->SetBounds(bounds); |
124 return; | 150 return; |
125 } | 151 } |
126 // TODO(oshima|yusukes): This is temporary solution until better drag & move | 152 // TODO(oshima|yusukes): This is temporary solution until better drag & move |
Yusuke Sato
2012/08/01 17:44:06
The UX team told us that we should determine the d
| |
127 // is implemented. (crbug.com/136816). | 153 // is implemented. (crbug.com/136816). |
128 gfx::Rect dst_bounds = | 154 gfx::Rect dst_bounds = |
129 ScreenAsh::ConvertRectToScreen(details_.window->parent(), bounds); | 155 ScreenAsh::ConvertRectToScreen(details_.window->parent(), bounds); |
130 gfx::Display dst_display = gfx::Screen::GetDisplayMatching(dst_bounds); | 156 gfx::Display dst_display = gfx::Screen::GetDisplayMatching(dst_bounds); |
131 if (dst_display.id() != | 157 if (dst_display.id() != |
132 gfx::Screen::GetDisplayNearestWindow(details_.window).id()) { | 158 gfx::Screen::GetDisplayNearestWindow(details_.window).id()) { |
133 // Don't animate when moving to another display. | 159 // Don't animate when moving to another display. |
134 details_.window->SetBoundsInScreen(dst_bounds); | 160 details_.window->SetBoundsInScreen(dst_bounds); |
135 } else { | 161 } else { |
136 ui::ScopedLayerAnimationSettings scoped_setter( | 162 ui::ScopedLayerAnimationSettings scoped_setter( |
137 details_.window->layer()->GetAnimator()); | 163 details_.window->layer()->GetAnimator()); |
138 // Use a small duration since the grid is small. | 164 // Use a small duration since the grid is small. |
139 scoped_setter.SetTransitionDuration( | 165 scoped_setter.SetTransitionDuration( |
140 base::TimeDelta::FromMilliseconds(kSnapDurationMS)); | 166 base::TimeDelta::FromMilliseconds(kSnapDurationMS)); |
141 details_.window->SetBounds(bounds); | 167 details_.window->SetBounds(bounds); |
142 } | 168 } |
143 } | 169 } |
144 | 170 |
145 void WorkspaceWindowResizer::RevertDrag() { | 171 void WorkspaceWindowResizer::RevertDrag() { |
172 drag_phantom_window_controller_.reset(); | |
146 phantom_window_controller_.reset(); | 173 phantom_window_controller_.reset(); |
147 | 174 |
148 if (!did_move_or_resize_) | 175 if (!did_move_or_resize_) |
149 return; | 176 return; |
150 | 177 |
151 details_.window->SetBounds(details_.initial_bounds); | 178 details_.window->SetBounds(details_.initial_bounds); |
152 if (details_.window_component == HTRIGHT) { | 179 if (details_.window_component == HTRIGHT) { |
153 int last_x = details_.initial_bounds.right(); | 180 int last_x = details_.initial_bounds.right(); |
154 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 181 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
155 gfx::Rect bounds(attached_windows_[i]->bounds()); | 182 gfx::Rect bounds(attached_windows_[i]->bounds()); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 if (i == attached_windows_.size()) | 330 if (i == attached_windows_.size()) |
304 size = end - current; | 331 size = end - current; |
305 current += size; | 332 current += size; |
306 sizes->push_back(size); | 333 sizes->push_back(size); |
307 } | 334 } |
308 } | 335 } |
309 } | 336 } |
310 | 337 |
311 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( | 338 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
312 gfx::Rect* bounds, int grid_size) const { | 339 gfx::Rect* bounds, int grid_size) const { |
313 // Always keep kMinOnscreenHeight on the bottom. | 340 // Always keep kMinOnscreenHeight on the bottom except when an extended |
341 // display is available and a window is being dragged. | |
314 gfx::Rect work_area( | 342 gfx::Rect work_area( |
315 ScreenAsh::GetDisplayWorkAreaBoundsInParent(details_.window)); | 343 ScreenAsh::GetDisplayWorkAreaBoundsInParent(details_.window)); |
316 int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, | 344 int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, |
317 grid_size); | 345 grid_size); |
318 if (bounds->y() > max_y) | 346 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && |
347 bounds->y() > max_y) { | |
319 bounds->set_y(max_y); | 348 bounds->set_y(max_y); |
349 } | |
320 | 350 |
321 // Don't allow dragging above the top of the display. | 351 // Don't allow dragging above the top of the display except when an extended |
322 if (bounds->y() <= work_area.y()) | 352 // display is available and a window is being dragged. |
353 if ((details_.window_component != HTCAPTION || !HasSecondaryRootWindow()) && | |
354 bounds->y() <= work_area.y()) { | |
323 bounds->set_y(work_area.y()); | 355 bounds->set_y(work_area.y()); |
356 } | |
324 | 357 |
325 if (grid_size >= 0 && details_.window_component == HTCAPTION) | 358 if (grid_size >= 0 && details_.window_component == HTCAPTION) |
326 SnapToWorkAreaEdges(work_area, bounds, grid_size); | 359 SnapToWorkAreaEdges(work_area, bounds, grid_size); |
327 | 360 |
328 if (attached_windows_.empty()) | 361 if (attached_windows_.empty()) |
329 return; | 362 return; |
330 | 363 |
331 if (details_.window_component == HTRIGHT) { | 364 if (details_.window_component == HTRIGHT) { |
332 bounds->set_width(std::min(bounds->width(), | 365 bounds->set_width(std::min(bounds->width(), |
333 work_area.right() - total_min_ - bounds->x())); | 366 work_area.right() - total_min_ - bounds->x())); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 case HTRIGHT: | 415 case HTRIGHT: |
383 return x; | 416 return x; |
384 case HTBOTTOM: | 417 case HTBOTTOM: |
385 return y; | 418 return y; |
386 default: | 419 default: |
387 NOTREACHED(); | 420 NOTREACHED(); |
388 } | 421 } |
389 return 0; | 422 return 0; |
390 } | 423 } |
391 | 424 |
425 void WorkspaceWindowResizer::UpdateDragPhantomWindow( | |
426 aura::RootWindow* another_root, | |
427 const gfx::Rect& window_bounds_in_screen) { | |
428 if (!another_root) { | |
429 // An extended display is not available. | |
430 drag_phantom_window_controller_.reset(); | |
431 return; | |
432 } | |
433 | |
434 // It's available. Show a phantom window on the display if needed. | |
435 const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen()); | |
436 const gfx::Rect phantom( | |
437 root_bounds_in_screen.Intersect(window_bounds_in_screen)); | |
438 | |
439 if (!phantom.IsEmpty()) { | |
440 if (!drag_phantom_window_controller_.get()) { | |
441 drag_phantom_window_controller_.reset( | |
442 new PhantomWindowController(window())); | |
443 drag_phantom_window_controller_->Show(phantom); | |
444 } else { | |
445 drag_phantom_window_controller_->SetBounds(phantom); // no animation | |
446 } | |
447 } else { | |
448 drag_phantom_window_controller_.reset(); | |
449 } | |
450 } | |
451 | |
392 void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location, | 452 void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location, |
393 const gfx::Rect& bounds, | 453 const gfx::Rect& bounds, |
394 int grid_size) { | 454 int grid_size) { |
395 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 455 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
396 return; | 456 return; |
397 | 457 |
398 SnapType last_type = snap_type_; | 458 SnapType last_type = snap_type_; |
399 snap_type_ = GetSnapType(location); | 459 snap_type_ = GetSnapType(location); |
400 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 460 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
401 phantom_window_controller_.reset(); | 461 phantom_window_controller_.reset(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(details_.window)); | 517 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(details_.window)); |
458 if (location.x() <= area.x()) | 518 if (location.x() <= area.x()) |
459 return SNAP_LEFT_EDGE; | 519 return SNAP_LEFT_EDGE; |
460 if (location.x() >= area.right() - 1) | 520 if (location.x() >= area.right() - 1) |
461 return SNAP_RIGHT_EDGE; | 521 return SNAP_RIGHT_EDGE; |
462 return SNAP_NONE; | 522 return SNAP_NONE; |
463 } | 523 } |
464 | 524 |
465 } // namespace internal | 525 } // namespace internal |
466 } // namespace ash | 526 } // namespace ash |
OLD | NEW |