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

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: Fix win_aura error 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* window_resizer = NULL;
44 if (window->parent() && 44 if (window->parent() &&
45 window->parent()->id() == internal::kShellWindowId_WorkspaceContainer) { 45 window->parent()->id() == internal::kShellWindowId_WorkspaceContainer) {
46 // Allow dragging maximized windows if it's not tracked by workspace. This 46 // Allow dragging maximized windows if it's not tracked by workspace. This
47 // is set by tab dragging code. 47 // is set by tab dragging code.
48 if (!wm::IsWindowNormal(window) && 48 if (!wm::IsWindowNormal(window) &&
49 (window_component != HTCAPTION || GetTrackedByWorkspace(window))) 49 (window_component != HTCAPTION || GetTrackedByWorkspace(window)))
50 return scoped_ptr<WindowResizer>(); 50 return scoped_ptr<WindowResizer>();
51 return make_scoped_ptr<WindowResizer>( 51 window_resizer = internal::WorkspaceWindowResizer::Create(
52 internal::WorkspaceWindowResizer::Create(window,
53 point_in_parent,
54 window_component,
55 std::vector<aura::Window*>()));
56 } else if (wm::IsWindowNormal(window)) {
57 return make_scoped_ptr<WindowResizer>(DefaultWindowResizer::Create(
58 window, 52 window,
59 point_in_parent, 53 point_in_parent,
60 window_component)); 54 window_component,
61 } else { 55 std::vector<aura::Window*>());
62 return scoped_ptr<WindowResizer>(); 56 } else if (wm::IsWindowNormal(window)) {
57 window_resizer = DefaultWindowResizer::Create(
58 window, point_in_parent, window_component);
63 } 59 }
60 if (window_resizer) {
61 window_resizer = internal::DragWindowResizer::Create(
62 window_resizer, window, point_in_parent, window_component);
63 }
64 return make_scoped_ptr<WindowResizer>(window_resizer);
64 } 65 }
65 66
66 namespace internal { 67 namespace internal {
67 68
68 namespace { 69 namespace {
69 70
70 // Duration of the animation when snapping the window into place. 71 // Duration of the animation when snapping the window into place.
71 const int kSnapDurationMS = 100; 72 const int kSnapDurationMS = 100;
72 73
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. 74 // Returns true if should snap to the edge.
77 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) { 75 bool ShouldSnapToEdge(int distance_from_edge, int grid_size) {
78 return distance_from_edge < grid_size && 76 return distance_from_edge < grid_size &&
79 distance_from_edge > -grid_size * 2; 77 distance_from_edge > -grid_size * 2;
80 } 78 }
81 79
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. 80 // Returns the coordinate along the secondary axis to snap to.
100 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, 81 int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge,
101 int leading, 82 int leading,
102 int trailing, 83 int trailing,
103 int none) { 84 int none) {
104 switch (edge) { 85 switch (edge) {
105 case SECONDARY_MAGNETISM_EDGE_LEADING: 86 case SECONDARY_MAGNETISM_EDGE_LEADING:
106 return leading; 87 return leading;
107 case SECONDARY_MAGNETISM_EDGE_TRAILING: 88 case SECONDARY_MAGNETISM_EDGE_TRAILING:
108 return trailing; 89 return trailing;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 } 281 }
301 282
302 private: 283 private:
303 int size_; 284 int size_;
304 int min_; 285 int min_;
305 int max_; 286 int max_;
306 }; 287 };
307 288
308 WorkspaceWindowResizer::~WorkspaceWindowResizer() { 289 WorkspaceWindowResizer::~WorkspaceWindowResizer() {
309 Shell* shell = Shell::GetInstance(); 290 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(); 291 shell->cursor_manager()->UnlockCursor();
314
315 if (destroyed_)
316 *destroyed_ = true;
317 } 292 }
318 293
319 // static 294 // static
320 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( 295 WorkspaceWindowResizer* WorkspaceWindowResizer::Create(
321 aura::Window* window, 296 aura::Window* window,
322 const gfx::Point& location_in_parent, 297 const gfx::Point& location_in_parent,
323 int window_component, 298 int window_component,
324 const std::vector<aura::Window*>& attached_windows) { 299 const std::vector<aura::Window*>& attached_windows) {
325 Details details(window, location_in_parent, window_component); 300 Details details(window, location_in_parent, window_component);
326 return details.is_resizable ? 301 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. 330 // Hide a phantom window for snapping if the cursor is in another root window.
356 if (in_original_root && wm::CanResizeWindow(window())) { 331 if (in_original_root && wm::CanResizeWindow(window())) {
357 UpdateSnapPhantomWindow(location_in_parent, bounds); 332 UpdateSnapPhantomWindow(location_in_parent, bounds);
358 } else { 333 } else {
359 snap_type_ = SNAP_NONE; 334 snap_type_ = SNAP_NONE;
360 snap_phantom_window_controller_.reset(); 335 snap_phantom_window_controller_.reset();
361 } 336 }
362 337
363 if (!attached_windows_.empty()) 338 if (!attached_windows_.empty())
364 LayoutAttachedWindows(&bounds); 339 LayoutAttachedWindows(&bounds);
365 if (bounds != window()->bounds()) { 340 if (bounds != window()->bounds())
366 bool destroyed = false;
367 destroyed_ = &destroyed;
368 window()->SetBounds(bounds); 341 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 } 342 }
380 343
381 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { 344 void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
382 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); 345 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true);
383 window()->layer()->SetOpacity(details_.initial_opacity);
384 drag_window_controller_.reset();
385 snap_phantom_window_controller_.reset(); 346 snap_phantom_window_controller_.reset();
386 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 347 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
387 return; 348 return;
388 349
389 // When the window is not in the normal show state, we do not snap thw window. 350 // 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 351 // 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 352 // 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 353 // out of a maximized window, it's already in the normal show state when this
393 // is called, so it does not matter. 354 // is called, so it does not matter.
394 if (wm::IsWindowNormal(window()) && 355 if (wm::IsWindowNormal(window()) &&
395 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { 356 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) {
396 if (!GetRestoreBoundsInScreen(window())) { 357 if (!GetRestoreBoundsInScreen(window())) {
397 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( 358 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen(
398 window()->parent(), details_.initial_bounds_in_parent); 359 window()->parent(), details_.initial_bounds_in_parent);
399 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? 360 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ?
400 initial_bounds : 361 initial_bounds :
401 details_.restore_bounds); 362 details_.restore_bounds);
402 } 363 }
403 window()->SetBounds(snap_sizer_->target_bounds()); 364 window()->SetBounds(snap_sizer_->target_bounds());
404 return; 365 return;
405 } 366 }
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 } 367 }
423 368
424 void WorkspaceWindowResizer::RevertDrag() { 369 void WorkspaceWindowResizer::RevertDrag() {
425 window()->layer()->SetOpacity(details_.initial_opacity);
426 drag_window_controller_.reset();
427 snap_phantom_window_controller_.reset(); 370 snap_phantom_window_controller_.reset();
428 Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator();
429 371
430 if (!did_move_or_resize_) 372 if (!did_move_or_resize_)
431 return; 373 return;
432 374
433 window()->SetBounds(details_.initial_bounds_in_parent); 375 window()->SetBounds(details_.initial_bounds_in_parent);
434 if (!details_.restore_bounds.IsEmpty()) 376 if (!details_.restore_bounds.IsEmpty())
435 SetRestoreBoundsInScreen(details_.window, details_.restore_bounds); 377 SetRestoreBoundsInScreen(details_.window, details_.restore_bounds);
436 378
437 if (details_.window_component == HTRIGHT) { 379 if (details_.window_component == HTRIGHT) {
438 int last_x = details_.initial_bounds_in_parent.right(); 380 int last_x = details_.initial_bounds_in_parent.right();
(...skipping 23 matching lines...) Expand all
462 WorkspaceWindowResizer::WorkspaceWindowResizer( 404 WorkspaceWindowResizer::WorkspaceWindowResizer(
463 const Details& details, 405 const Details& details,
464 const std::vector<aura::Window*>& attached_windows) 406 const std::vector<aura::Window*>& attached_windows)
465 : details_(details), 407 : details_(details),
466 attached_windows_(attached_windows), 408 attached_windows_(attached_windows),
467 did_move_or_resize_(false), 409 did_move_or_resize_(false),
468 total_min_(0), 410 total_min_(0),
469 total_initial_size_(0), 411 total_initial_size_(0),
470 snap_type_(SNAP_NONE), 412 snap_type_(SNAP_NONE),
471 num_mouse_moves_since_bounds_change_(0), 413 num_mouse_moves_since_bounds_change_(0),
472 destroyed_(NULL),
473 magnetism_window_(NULL) { 414 magnetism_window_(NULL) {
474 DCHECK(details_.is_resizable); 415 DCHECK(details_.is_resizable);
475 416
476 Shell* shell = Shell::GetInstance(); 417 Shell* shell = Shell::GetInstance();
477 shell->cursor_manager()->LockCursor(); 418 shell->cursor_manager()->LockCursor();
478 419
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. 420 // Only support attaching to the right/bottom.
494 DCHECK(attached_windows_.empty() || 421 DCHECK(attached_windows_.empty() ||
495 (details.window_component == HTRIGHT || 422 (details.window_component == HTRIGHT ||
496 details.window_component == HTBOTTOM)); 423 details.window_component == HTBOTTOM));
497 424
498 // TODO: figure out how to deal with window going off the edge. 425 // TODO: figure out how to deal with window going off the edge.
499 426
500 // Calculate sizes so that we can maintain the ratios if we need to resize. 427 // Calculate sizes so that we can maintain the ratios if we need to resize.
501 int total_available = 0; 428 int total_available = 0;
502 for (size_t i = 0; i < attached_windows_.size(); ++i) { 429 for (size_t i = 0; i < attached_windows_.size(); ++i) {
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 case HTRIGHT: 743 case HTRIGHT:
817 return x; 744 return x;
818 case HTBOTTOM: 745 case HTBOTTOM:
819 return y; 746 return y;
820 default: 747 default:
821 NOTREACHED(); 748 NOTREACHED();
822 } 749 }
823 return 0; 750 return 0;
824 } 751 }
825 752
826 void WorkspaceWindowResizer::UpdateDragWindow(const gfx::Rect& bounds,
827 bool in_original_root) {
828 if (!did_move_or_resize_ || details_.window_component != HTCAPTION ||
829 !ShouldAllowMouseWarp()) {
830 return;
831 }
832
833 // It's available. Show a phantom window on the display if needed.
834 aura::RootWindow* another_root =
835 GetAnotherRootWindow(window()->GetRootWindow());
836 const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen());
837 const gfx::Rect bounds_in_screen =
838 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds);
839 gfx::Rect bounds_in_another_root =
840 gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen);
841
842 const float fraction_in_another_window =
843 (bounds_in_another_root.width() * bounds_in_another_root.height()) /
844 static_cast<float>(bounds.width() * bounds.height());
845 const float phantom_opacity =
846 !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window);
847 const float window_opacity =
848 in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window));
849
850 if (fraction_in_another_window > 0) {
851 if (!drag_window_controller_.get()) {
852 drag_window_controller_.reset(
853 new DragWindowController(window()));
854 // Always show the drag phantom on the |another_root| window.
855 drag_window_controller_->SetDestinationDisplay(
856 Shell::GetScreen()->GetDisplayMatching(
857 another_root->GetBoundsInScreen()));
858 drag_window_controller_->Show();
859 } else {
860 // No animation.
861 drag_window_controller_->SetBounds(bounds_in_screen);
862 }
863 drag_window_controller_->SetOpacity(phantom_opacity);
864 window()->layer()->SetOpacity(window_opacity);
865 } else {
866 drag_window_controller_.reset();
867 window()->layer()->SetOpacity(1.0f);
868 }
869 }
870
871 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, 753 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
872 const gfx::Rect& bounds) { 754 const gfx::Rect& bounds) {
873 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 755 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
874 return; 756 return;
875 757
876 if (!wm::CanSnapWindow(window())) 758 if (!wm::CanSnapWindow(window()))
877 return; 759 return;
878 760
879 SnapType last_type = snap_type_; 761 SnapType last_type = snap_type_;
880 snap_type_ = GetSnapType(location); 762 snap_type_ = GetSnapType(location);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 // TODO: this likely only wants total display area, not the area of a single 820 // TODO: this likely only wants total display area, not the area of a single
939 // display. 821 // display.
940 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); 822 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window()));
941 if (location.x() <= area.x()) 823 if (location.x() <= area.x())
942 return SNAP_LEFT_EDGE; 824 return SNAP_LEFT_EDGE;
943 if (location.x() >= area.right() - 1) 825 if (location.x() >= area.right() - 1)
944 return SNAP_RIGHT_EDGE; 826 return SNAP_RIGHT_EDGE;
945 return SNAP_NONE; 827 return SNAP_NONE;
946 } 828 }
947 829
948 bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const {
949 return (details_.window_component == HTCAPTION) &&
950 (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) &&
951 (window()->type() == aura::client::WINDOW_TYPE_NORMAL);
952 }
953
954 } // namespace internal 830 } // namespace internal
955 } // namespace ash 831 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/workspace/workspace_window_resizer.h ('k') | ash/wm/workspace/workspace_window_resizer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698