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

Side by Side Diff: ash/wm/workspace/workspace_window_resizer.cc

Issue 11411344: Extract the code for supporing extended desktop from WorkspaceWindowResizer into DragWindowResizer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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
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 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "ash/display/display_controller.h" 12 #include "ash/display/display_controller.h"
13 #include "ash/display/mouse_cursor_event_filter.h"
14 #include "ash/screen_ash.h" 13 #include "ash/screen_ash.h"
15 #include "ash/shell.h" 14 #include "ash/shell.h"
16 #include "ash/shell_window_ids.h" 15 #include "ash/shell_window_ids.h"
17 #include "ash/wm/coordinate_conversion.h" 16 #include "ash/wm/coordinate_conversion.h"
18 #include "ash/wm/cursor_manager.h" 17 #include "ash/wm/cursor_manager.h"
19 #include "ash/wm/default_window_resizer.h" 18 #include "ash/wm/default_window_resizer.h"
20 #include "ash/wm/drag_window_controller.h" 19 #include "ash/wm/drag_window_resizer.h"
21 #include "ash/wm/property_util.h" 20 #include "ash/wm/property_util.h"
22 #include "ash/wm/window_util.h" 21 #include "ash/wm/window_util.h"
23 #include "ash/wm/workspace/phantom_window_controller.h" 22 #include "ash/wm/workspace/phantom_window_controller.h"
24 #include "ash/wm/workspace/snap_sizer.h" 23 #include "ash/wm/workspace/snap_sizer.h"
25 #include "ui/aura/client/aura_constants.h" 24 #include "ui/aura/client/aura_constants.h"
26 #include "ui/aura/root_window.h" 25 #include "ui/aura/root_window.h"
27 #include "ui/aura/window.h" 26 #include "ui/aura/window.h"
28 #include "ui/aura/window_delegate.h" 27 #include "ui/aura/window_delegate.h"
29 #include "ui/base/hit_test.h" 28 #include "ui/base/hit_test.h"
30 #include "ui/compositor/layer.h" 29 #include "ui/compositor/layer.h"
31 #include "ui/gfx/screen.h" 30 #include "ui/gfx/screen.h"
32 #include "ui/gfx/transform.h" 31 #include "ui/gfx/transform.h"
33 32
34 namespace ash { 33 namespace ash {
35 34
36 scoped_ptr<WindowResizer> CreateWindowResizer(aura::Window* window, 35 scoped_ptr<WindowResizer> CreateWindowResizer(aura::Window* window,
37 const gfx::Point& point_in_parent, 36 const gfx::Point& point_in_parent,
38 int window_component) { 37 int window_component) {
39 DCHECK(window); 38 DCHECK(window);
40 // No need to return a resizer when the window cannot get resized. 39 // No need to return a resizer when the window cannot get resized.
41 if (!wm::CanResizeWindow(window) && window_component != HTCAPTION) 40 if (!wm::CanResizeWindow(window) && window_component != HTCAPTION)
42 return scoped_ptr<WindowResizer>(); 41 return scoped_ptr<WindowResizer>();
43 42
43 WindowResizer::Details details(window, point_in_parent, window_component);
44 if (!details.is_resizable)
45 return scoped_ptr<WindowResizer>();
46
47 WindowResizer* window_resizer = NULL;
44 if (window->parent() && 48 if (window->parent() &&
45 window->parent()->id() == internal::kShellWindowId_WorkspaceContainer) { 49 window->parent()->id() == internal::kShellWindowId_WorkspaceContainer) {
46 // Allow dragging maximized windows if it's not tracked by workspace. This 50 // Allow dragging maximized windows if it's not tracked by workspace. This
47 // is set by tab dragging code. 51 // is set by tab dragging code.
48 if (!wm::IsWindowNormal(window) && 52 if (!wm::IsWindowNormal(window) &&
49 (window_component != HTCAPTION || GetTrackedByWorkspace(window))) 53 (window_component != HTCAPTION || GetTrackedByWorkspace(window)))
50 return scoped_ptr<WindowResizer>(); 54 return scoped_ptr<WindowResizer>();
51 return make_scoped_ptr<WindowResizer>( 55 window_resizer = new internal::WorkspaceWindowResizer(
52 internal::WorkspaceWindowResizer::Create(window, 56 details, std::vector<aura::Window*>());
53 point_in_parent,
54 window_component,
55 std::vector<aura::Window*>()));
56 } else if (wm::IsWindowNormal(window)) { 57 } else if (wm::IsWindowNormal(window)) {
57 return make_scoped_ptr<WindowResizer>(DefaultWindowResizer::Create( 58 window_resizer = new DefaultWindowResizer(details);
58 window,
59 point_in_parent,
60 window_component));
61 } else {
62 return scoped_ptr<WindowResizer>();
63 } 59 }
60 if (window_resizer)
61 window_resizer = new internal::DragWindowResizer(window_resizer, details);
62 return make_scoped_ptr<WindowResizer>(window_resizer);
64 } 63 }
65 64
66 namespace internal { 65 namespace internal {
67 66
68 namespace { 67 namespace {
69 68
70 // Duration of the animation when snapping the window into place. 69 // Duration of the animation when snapping the window into place.
71 const int kSnapDurationMS = 100; 70 const int kSnapDurationMS = 100;
72 71
73 // The maximum opacity of the drag phantom window.
74 const float kMaxOpacity = 0.8f;
75
76 // Returns true if should snap to the edge. 72 // Returns true if should snap to the edge.
77 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { 73 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) {
78 return distance_from_edge < grid_size && 74 return distance_from_edge < grid_size &&
79 distance_from_edge > -grid_size * 2; 75 distance_from_edge > -grid_size * 2;
80 } 76 }
81 77
82 // Returns true if Ash has more than one root window.
83 bool HasSecondaryRootWindow() {
84 return Shell::GetAllRootWindows().size() > 1;
85 }
86
87 // When there are two root windows, returns one of the root windows which is not
88 // |root_window|. Returns NULL if only one root window exists.
89 aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) {
90 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
91 if (root_windows.size() < 2)
92 return NULL;
93 DCHECK_EQ(2U, root_windows.size());
94 if (root_windows[0] == root_window)
95 return root_windows[1];
96 return root_windows[0];
97 }
98
99 // Returns the coordinate along the secondary axis to snap to. 78 // Returns the coordinate along the secondary axis to snap to.
100 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, 79 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge,
101 int leading, 80 int leading,
102 int trailing, 81 int trailing,
103 int none) { 82 int none) {
104 switch (edge) { 83 switch (edge) {
105 case SECONDARY_MAGNETISM_EDGE_LEADING: 84 case SECONDARY_MAGNETISM_EDGE_LEADING:
106 return leading; 85 return leading;
107 case SECONDARY_MAGNETISM_EDGE_TRAILING: 86 case SECONDARY_MAGNETISM_EDGE_TRAILING:
108 return trailing; 87 return trailing;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 } 279 }
301 280
302 private: 281 private:
303 int size_; 282 int size_;
304 int min_; 283 int min_;
305 int max_; 284 int max_;
306 }; 285 };
307 286
308 WorkspaceWindowResizer::~WorkspaceWindowResizer() { 287 WorkspaceWindowResizer::~WorkspaceWindowResizer() {
309 Shell* shell = Shell::GetInstance(); 288 Shell* shell = Shell::GetInstance();
310 shell->mouse_cursor_filter()->set_mouse_warp_mode(
311 MouseCursorEventFilter::WARP_ALWAYS);
312 shell->mouse_cursor_filter()->HideSharedEdgeIndicator();
313 shell->cursor_manager()->UnlockCursor(); 289 shell->cursor_manager()->UnlockCursor();
314
315 if (destroyed_)
316 *destroyed_ = true;
317 } 290 }
318 291
319 // static 292 // static
320 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( 293 WorkspaceWindowResizer* WorkspaceWindowResizer::Create(
321 aura::Window* window, 294 aura::Window* window,
322 const gfx::Point& location_in_parent, 295 const gfx::Point& location_in_parent,
323 int window_component, 296 int window_component,
324 const std::vector<aura::Window*>& attached_windows) { 297 const std::vector<aura::Window*>& attached_windows) {
325 Details details(window, location_in_parent, window_component); 298 Details details(window, location_in_parent, window_component);
326 return details.is_resizable ? 299 return details.is_resizable ?
(...skipping 28 matching lines...) Expand all
355 // Hide a phantom window for snapping if the cursor is in another root window. 328 // Hide a phantom window for snapping if the cursor is in another root window.
356 if (in_original_root && wm::CanResizeWindow(window())) { 329 if (in_original_root && wm::CanResizeWindow(window())) {
357 UpdateSnapPhantomWindow(location_in_parent, bounds); 330 UpdateSnapPhantomWindow(location_in_parent, bounds);
358 } else { 331 } else {
359 snap_type_ = SNAP_NONE; 332 snap_type_ = SNAP_NONE;
360 snap_phantom_window_controller_.reset(); 333 snap_phantom_window_controller_.reset();
361 } 334 }
362 335
363 if (!attached_windows_.empty()) 336 if (!attached_windows_.empty())
364 LayoutAttachedWindows(&bounds); 337 LayoutAttachedWindows(&bounds);
365 if (bounds != window()->bounds()) { 338 if (bounds != window()->bounds())
366 bool destroyed = false;
367 destroyed_ = &destroyed;
368 window()->SetBounds(bounds); 339 window()->SetBounds(bounds);
369 if (destroyed)
370 return;
371 destroyed_ = NULL;
372 }
373 // Show a phantom window for dragging in another root window.
374 if (HasSecondaryRootWindow())
375 UpdateDragWindow(bounds, in_original_root);
376 else
377 drag_window_controller_.reset();
378
379 } 340 }
380 341
381 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { 342 void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
382 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); 343 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true);
383 window()->layer()->SetOpacity(details_.initial_opacity);
384 drag_window_controller_.reset();
385 snap_phantom_window_controller_.reset(); 344 snap_phantom_window_controller_.reset();
386 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 345 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
387 return; 346 return;
388 347
389 // When the window is not in the normal show state, we do not snap thw window. 348 // When the window is not in the normal show state, we do not snap thw window.
390 // This happens when the user minimizes or maximizes the window by keyboard 349 // This happens when the user minimizes or maximizes the window by keyboard
391 // shortcut while dragging it. If the window is the result of dragging a tab 350 // shortcut while dragging it. If the window is the result of dragging a tab
392 // out of a maximized window, it's already in the normal show state when this 351 // out of a maximized window, it's already in the normal show state when this
393 // is called, so it does not matter. 352 // is called, so it does not matter.
394 if (wm::IsWindowNormal(window()) && 353 if (wm::IsWindowNormal(window()) &&
395 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { 354 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) {
396 if (!GetRestoreBoundsInScreen(window())) { 355 if (!GetRestoreBoundsInScreen(window())) {
397 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( 356 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen(
398 window()->parent(), details_.initial_bounds_in_parent); 357 window()->parent(), details_.initial_bounds_in_parent);
399 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? 358 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ?
400 initial_bounds : 359 initial_bounds :
401 details_.restore_bounds); 360 details_.restore_bounds);
402 } 361 }
403 window()->SetBounds(snap_sizer_->target_bounds()); 362 window()->SetBounds(snap_sizer_->target_bounds());
404 return; 363 return;
405 } 364 }
406 gfx::Rect bounds(GetFinalBounds(window()->bounds()));
407
408 // Check if the destination is another display.
409 gfx::Point last_mouse_location_in_screen = last_mouse_location_;
410 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen);
411 gfx::Screen* screen = Shell::GetScreen();
412 const gfx::Display dst_display =
413 screen->GetDisplayNearestPoint(last_mouse_location_in_screen);
414
415 if (dst_display.id() !=
416 screen->GetDisplayNearestWindow(window()->GetRootWindow()).id()) {
417 // Don't animate when moving to another display.
418 const gfx::Rect dst_bounds =
419 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds);
420 window()->SetBoundsInScreen(dst_bounds, dst_display);
421 }
422 } 365 }
423 366
424 void WorkspaceWindowResizer::RevertDrag() { 367 void WorkspaceWindowResizer::RevertDrag() {
425 window()->layer()->SetOpacity(details_.initial_opacity);
426 drag_window_controller_.reset();
427 snap_phantom_window_controller_.reset(); 368 snap_phantom_window_controller_.reset();
428 Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator();
429 369
430 if (!did_move_or_resize_) 370 if (!did_move_or_resize_)
431 return; 371 return;
432 372
433 window()->SetBounds(details_.initial_bounds_in_parent); 373 window()->SetBounds(details_.initial_bounds_in_parent);
434 if (!details_.restore_bounds.IsEmpty()) 374 if (!details_.restore_bounds.IsEmpty())
435 SetRestoreBoundsInScreen(details_.window, details_.restore_bounds); 375 SetRestoreBoundsInScreen(details_.window, details_.restore_bounds);
436 376
437 if (details_.window_component == HTRIGHT) { 377 if (details_.window_component == HTRIGHT) {
438 int last_x = details_.initial_bounds_in_parent.right(); 378 int last_x = details_.initial_bounds_in_parent.right();
(...skipping 23 matching lines...) Expand all
462 WorkspaceWindowResizer::WorkspaceWindowResizer( 402 WorkspaceWindowResizer::WorkspaceWindowResizer(
463 const Details& details, 403 const Details& details,
464 const std::vector<aura::Window*>& attached_windows) 404 const std::vector<aura::Window*>& attached_windows)
465 : details_(details), 405 : details_(details),
466 attached_windows_(attached_windows), 406 attached_windows_(attached_windows),
467 did_move_or_resize_(false), 407 did_move_or_resize_(false),
468 total_min_(0), 408 total_min_(0),
469 total_initial_size_(0), 409 total_initial_size_(0),
470 snap_type_(SNAP_NONE), 410 snap_type_(SNAP_NONE),
471 num_mouse_moves_since_bounds_change_(0), 411 num_mouse_moves_since_bounds_change_(0),
472 destroyed_(NULL),
473 magnetism_window_(NULL) { 412 magnetism_window_(NULL) {
474 DCHECK(details_.is_resizable); 413 DCHECK(details_.is_resizable);
475 414
476 Shell* shell = Shell::GetInstance(); 415 Shell* shell = Shell::GetInstance();
477 shell->cursor_manager()->LockCursor(); 416 shell->cursor_manager()->LockCursor();
478 417
479 // The pointer should be confined in one display during resizing a window
480 // because the window cannot span two displays at the same time anyway. The
481 // exception is window/tab dragging operation. During that operation,
482 // |mouse_warp_mode_| should be set to WARP_DRAG so that the user could move a
483 // window/tab to another display.
484 MouseCursorEventFilter* mouse_cursor_filter = shell->mouse_cursor_filter();
485 mouse_cursor_filter->set_mouse_warp_mode(
486 ShouldAllowMouseWarp() ?
487 MouseCursorEventFilter::WARP_DRAG : MouseCursorEventFilter::WARP_NONE);
488 if (ShouldAllowMouseWarp()) {
489 mouse_cursor_filter->ShowSharedEdgeIndicator(
490 details.window->GetRootWindow());
491 }
492
493 // Only support attaching to the right/bottom. 418 // Only support attaching to the right/bottom.
494 DCHECK(attached_windows_.empty() || 419 DCHECK(attached_windows_.empty() ||
495 (details.window_component == HTRIGHT || 420 (details.window_component == HTRIGHT ||
496 details.window_component == HTBOTTOM)); 421 details.window_component == HTBOTTOM));
497 422
498 // TODO: figure out how to deal with window going off the edge. 423 // TODO: figure out how to deal with window going off the edge.
499 424
500 // Calculate sizes so that we can maintain the ratios if we need to resize. 425 // Calculate sizes so that we can maintain the ratios if we need to resize.
501 int total_available = 0; 426 int total_available = 0;
502 for (size_t i = 0; i < attached_windows_.size(); ++i) { 427 for (size_t i = 0; i < attached_windows_.size(); ++i) {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 case HTRIGHT: 736 case HTRIGHT:
812 return x; 737 return x;
813 case HTBOTTOM: 738 case HTBOTTOM:
814 return y; 739 return y;
815 default: 740 default:
816 NOTREACHED(); 741 NOTREACHED();
817 } 742 }
818 return 0; 743 return 0;
819 } 744 }
820 745
821 void WorkspaceWindowResizer::UpdateDragWindow(const gfx::Rect& bounds,
822 bool in_original_root) {
823 if (!did_move_or_resize_ || details_.window_component != HTCAPTION ||
824 !ShouldAllowMouseWarp()) {
825 return;
826 }
827
828 // It's available. Show a phantom window on the display if needed.
829 aura::RootWindow* another_root =
830 GetAnotherRootWindow(window()->GetRootWindow());
831 const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen());
832 const gfx::Rect bounds_in_screen =
833 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds);
834 gfx::Rect bounds_in_another_root =
835 gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen);
836
837 const float fraction_in_another_window =
838 (bounds_in_another_root.width() * bounds_in_another_root.height()) /
839 static_cast<float>(bounds.width() * bounds.height());
840 const float phantom_opacity =
841 !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window);
842 const float window_opacity =
843 in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window));
844
845 if (fraction_in_another_window > 0) {
846 if (!drag_window_controller_.get()) {
847 drag_window_controller_.reset(
848 new DragWindowController(window()));
849 // Always show the drag phantom on the |another_root| window.
850 drag_window_controller_->SetDestinationDisplay(
851 Shell::GetScreen()->GetDisplayMatching(
852 another_root->GetBoundsInScreen()));
853 drag_window_controller_->Show();
854 } else {
855 // No animation.
856 drag_window_controller_->SetBounds(bounds_in_screen);
857 }
858 drag_window_controller_->SetOpacity(phantom_opacity);
859 window()->layer()->SetOpacity(window_opacity);
860 } else {
861 drag_window_controller_.reset();
862 window()->layer()->SetOpacity(1.0f);
863 }
864 }
865
866 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, 746 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
867 const gfx::Rect& bounds) { 747 const gfx::Rect& bounds) {
868 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 748 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
869 return; 749 return;
870 750
871 if (!wm::CanSnapWindow(window())) 751 if (!wm::CanSnapWindow(window()))
872 return; 752 return;
873 753
874 SnapType last_type = snap_type_; 754 SnapType last_type = snap_type_;
875 snap_type_ = GetSnapType(location); 755 snap_type_ = GetSnapType(location);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 // TODO: this likely only wants total display area, not the area of a single 813 // TODO: this likely only wants total display area, not the area of a single
934 // display. 814 // display.
935 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); 815 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window()));
936 if (location.x() <= area.x()) 816 if (location.x() <= area.x())
937 return SNAP_LEFT_EDGE; 817 return SNAP_LEFT_EDGE;
938 if (location.x() >= area.right() - 1) 818 if (location.x() >= area.right() - 1)
939 return SNAP_RIGHT_EDGE; 819 return SNAP_RIGHT_EDGE;
940 return SNAP_NONE; 820 return SNAP_NONE;
941 } 821 }
942 822
943 bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const {
944 return (details_.window_component == HTCAPTION) &&
945 (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) &&
946 (window()->type() == aura::client::WINDOW_TYPE_NORMAL);
947 }
948
949 } // namespace internal 823 } // namespace internal
950 } // namespace ash 824 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698