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 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "ash/ash_switches.h" | 12 #include "ash/ash_switches.h" |
| 13 #include "ash/display/display_controller.h" |
13 #include "ash/root_window_controller.h" | 14 #include "ash/root_window_controller.h" |
14 #include "ash/screen_ash.h" | 15 #include "ash/screen_ash.h" |
15 #include "ash/shell.h" | 16 #include "ash/shell.h" |
16 #include "ash/shell_window_ids.h" | 17 #include "ash/shell_window_ids.h" |
17 #include "ash/wm/coordinate_conversion.h" | 18 #include "ash/wm/coordinate_conversion.h" |
18 #include "ash/wm/default_window_resizer.h" | 19 #include "ash/wm/default_window_resizer.h" |
| 20 #include "ash/wm/dock/docked_window_layout_manager.h" |
19 #include "ash/wm/dock/docked_window_resizer.h" | 21 #include "ash/wm/dock/docked_window_resizer.h" |
20 #include "ash/wm/drag_window_resizer.h" | 22 #include "ash/wm/drag_window_resizer.h" |
21 #include "ash/wm/panels/panel_window_resizer.h" | 23 #include "ash/wm/panels/panel_window_resizer.h" |
22 #include "ash/wm/property_util.h" | 24 #include "ash/wm/property_util.h" |
23 #include "ash/wm/window_settings.h" | 25 #include "ash/wm/window_settings.h" |
24 #include "ash/wm/window_util.h" | 26 #include "ash/wm/window_util.h" |
25 #include "ash/wm/workspace/phantom_window_controller.h" | 27 #include "ash/wm/workspace/phantom_window_controller.h" |
26 #include "ash/wm/workspace/snap_sizer.h" | 28 #include "ash/wm/workspace/snap_sizer.h" |
27 #include "base/command_line.h" | 29 #include "base/command_line.h" |
| 30 #include "base/memory/weak_ptr.h" |
28 #include "ui/aura/client/aura_constants.h" | 31 #include "ui/aura/client/aura_constants.h" |
29 #include "ui/aura/client/screen_position_client.h" | 32 #include "ui/aura/client/screen_position_client.h" |
30 #include "ui/aura/client/window_types.h" | 33 #include "ui/aura/client/window_types.h" |
31 #include "ui/aura/root_window.h" | 34 #include "ui/aura/root_window.h" |
32 #include "ui/aura/window.h" | 35 #include "ui/aura/window.h" |
33 #include "ui/aura/window_delegate.h" | 36 #include "ui/aura/window_delegate.h" |
34 #include "ui/base/hit_test.h" | 37 #include "ui/base/hit_test.h" |
35 #include "ui/compositor/layer.h" | 38 #include "ui/compositor/layer.h" |
36 #include "ui/gfx/screen.h" | 39 #include "ui/gfx/screen.h" |
37 #include "ui/gfx/transform.h" | 40 #include "ui/gfx/transform.h" |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 if (!did_move_or_resize_) { | 382 if (!did_move_or_resize_) { |
380 if (!details_.restore_bounds.IsEmpty()) | 383 if (!details_.restore_bounds.IsEmpty()) |
381 ClearRestoreBounds(window()); | 384 ClearRestoreBounds(window()); |
382 RestackWindows(); | 385 RestackWindows(); |
383 } | 386 } |
384 did_move_or_resize_ = true; | 387 did_move_or_resize_ = true; |
385 } | 388 } |
386 | 389 |
387 gfx::Point location_in_screen = location_in_parent; | 390 gfx::Point location_in_screen = location_in_parent; |
388 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); | 391 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); |
389 const bool in_original_root = | 392 |
390 wm::GetRootWindowAt(location_in_screen) == window()->GetRootWindow(); | 393 aura::RootWindow* root = NULL; |
| 394 gfx::Display display = |
| 395 ScreenAsh::FindDisplayContainingPoint(location_in_screen); |
| 396 // Track the last screen that the pointer was on to keep the snap phantom |
| 397 // window there. |
| 398 if (display.is_valid()) { |
| 399 root = Shell::GetInstance()->display_controller()-> |
| 400 GetRootWindowForDisplayId(display.id()); |
| 401 } |
| 402 if (!attached_windows_.empty()) |
| 403 LayoutAttachedWindows(&bounds); |
| 404 if (bounds != window()->bounds()) { |
| 405 // SetBounds needs to be called to update the layout which affects where the |
| 406 // phantom window is drawn. Keep track if the window was destroyed during |
| 407 // the drag and quit early if so. |
| 408 base::WeakPtr<WorkspaceWindowResizer> resizer( |
| 409 weak_ptr_factory_.GetWeakPtr()); |
| 410 window()->SetBounds(bounds); |
| 411 if (!resizer) |
| 412 return; |
| 413 } |
| 414 const bool in_original_root = !root || root == window()->GetRootWindow(); |
391 // Hide a phantom window for snapping if the cursor is in another root window. | 415 // Hide a phantom window for snapping if the cursor is in another root window. |
392 if (in_original_root && wm::CanResizeWindow(window())) { | 416 if (in_original_root) { |
393 UpdateSnapPhantomWindow(location_in_parent, bounds); | 417 UpdateSnapPhantomWindow(location_in_parent, bounds); |
394 } else { | 418 } else { |
395 snap_type_ = SNAP_NONE; | 419 snap_type_ = SNAP_NONE; |
396 snap_phantom_window_controller_.reset(); | 420 snap_phantom_window_controller_.reset(); |
| 421 snap_sizer_.reset(); |
| 422 UpdateDockedState(false); |
397 } | 423 } |
398 | |
399 if (!attached_windows_.empty()) | |
400 LayoutAttachedWindows(&bounds); | |
401 if (bounds != window()->bounds()) | |
402 window()->SetBounds(bounds); | |
403 } | 424 } |
404 | 425 |
405 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 426 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
406 wm::GetWindowSettings(details_.window)->set_bounds_changed_by_user(true); | 427 wm::GetWindowSettings(details_.window)->set_bounds_changed_by_user(true); |
407 snap_phantom_window_controller_.reset(); | 428 snap_phantom_window_controller_.reset(); |
408 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 429 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
409 return; | 430 return; |
410 | 431 |
411 // When the window is not in the normal show state, we do not snap the window. | 432 // When the window is not in the normal show state, we do not snap the window. |
412 // This happens when the user minimizes or maximizes the window by keyboard | 433 // This happens when the user minimizes or maximizes the window by keyboard |
413 // shortcut while dragging it. If the window is the result of dragging a tab | 434 // shortcut while dragging it. If the window is the result of dragging a tab |
414 // out of a maximized window, it's already in the normal show state when this | 435 // out of a maximized window, it's already in the normal show state when this |
415 // is called, so it does not matter. | 436 // is called, so it does not matter. |
416 if (wm::IsWindowNormal(window()) && | 437 if (wm::IsWindowNormal(window()) && |
417 (window()->type() != aura::client::WINDOW_TYPE_PANEL || | 438 (window()->type() != aura::client::WINDOW_TYPE_PANEL || |
418 !wm::GetWindowSettings(window())->panel_attached()) && | 439 !wm::GetWindowSettings(window())->panel_attached()) && |
419 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { | 440 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { |
420 if (!GetRestoreBoundsInScreen(window())) { | 441 if (!GetRestoreBoundsInScreen(window())) { |
421 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( | 442 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( |
422 window()->parent(), details_.initial_bounds_in_parent); | 443 window()->parent(), details_.initial_bounds_in_parent); |
423 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? | 444 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? |
424 initial_bounds : | 445 initial_bounds : |
425 details_.restore_bounds); | 446 details_.restore_bounds); |
426 } | 447 } |
427 window()->SetBounds(snap_sizer_->target_bounds()); | 448 DCHECK(snap_sizer_); |
| 449 if (wm::CanResizeWindow(window()) && |
| 450 !dock_layout_->is_dragged_window_docked() && |
| 451 !snap_sizer_->target_bounds().IsEmpty()) { |
| 452 window()->SetBounds(snap_sizer_->target_bounds()); |
| 453 } |
428 return; | 454 return; |
429 } | 455 } |
430 } | 456 } |
431 | 457 |
432 void WorkspaceWindowResizer::RevertDrag() { | 458 void WorkspaceWindowResizer::RevertDrag() { |
433 snap_phantom_window_controller_.reset(); | 459 snap_phantom_window_controller_.reset(); |
434 | 460 |
435 if (!did_move_or_resize_) | 461 if (!did_move_or_resize_) |
436 return; | 462 return; |
437 | 463 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 WorkspaceWindowResizer::WorkspaceWindowResizer( | 497 WorkspaceWindowResizer::WorkspaceWindowResizer( |
472 const Details& details, | 498 const Details& details, |
473 const std::vector<aura::Window*>& attached_windows) | 499 const std::vector<aura::Window*>& attached_windows) |
474 : details_(details), | 500 : details_(details), |
475 attached_windows_(attached_windows), | 501 attached_windows_(attached_windows), |
476 did_move_or_resize_(false), | 502 did_move_or_resize_(false), |
477 total_min_(0), | 503 total_min_(0), |
478 total_initial_size_(0), | 504 total_initial_size_(0), |
479 snap_type_(SNAP_NONE), | 505 snap_type_(SNAP_NONE), |
480 num_mouse_moves_since_bounds_change_(0), | 506 num_mouse_moves_since_bounds_change_(0), |
481 magnetism_window_(NULL) { | 507 magnetism_window_(NULL), |
| 508 weak_ptr_factory_(this) { |
482 DCHECK(details_.is_resizable); | 509 DCHECK(details_.is_resizable); |
483 | 510 |
484 Shell* shell = Shell::GetInstance(); | 511 Shell* shell = Shell::GetInstance(); |
485 shell->cursor_manager()->LockCursor(); | 512 shell->cursor_manager()->LockCursor(); |
486 | 513 |
| 514 aura::Window* dock_container = Shell::GetContainer( |
| 515 window()->GetRootWindow(), kShellWindowId_DockedContainer); |
| 516 dock_layout_ = static_cast<DockedWindowLayoutManager*>( |
| 517 dock_container->layout_manager()); |
| 518 |
487 // Only support attaching to the right/bottom. | 519 // Only support attaching to the right/bottom. |
488 DCHECK(attached_windows_.empty() || | 520 DCHECK(attached_windows_.empty() || |
489 (details.window_component == HTRIGHT || | 521 (details.window_component == HTRIGHT || |
490 details.window_component == HTBOTTOM)); | 522 details.window_component == HTBOTTOM)); |
491 | 523 |
492 // TODO: figure out how to deal with window going off the edge. | 524 // TODO: figure out how to deal with window going off the edge. |
493 | 525 |
494 // Calculate sizes so that we can maintain the ratios if we need to resize. | 526 // Calculate sizes so that we can maintain the ratios if we need to resize. |
495 int total_available = 0; | 527 int total_available = 0; |
496 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 528 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 NOTREACHED(); | 883 NOTREACHED(); |
852 } | 884 } |
853 return 0; | 885 return 0; |
854 } | 886 } |
855 | 887 |
856 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 888 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
857 const gfx::Rect& bounds) { | 889 const gfx::Rect& bounds) { |
858 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 890 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
859 return; | 891 return; |
860 | 892 |
861 if (!wm::CanSnapWindow(window())) | |
862 return; | |
863 | |
864 if (window()->type() == aura::client::WINDOW_TYPE_PANEL && | |
865 wm::GetWindowSettings(window())->panel_attached()) { | |
866 return; | |
867 } | |
868 | |
869 SnapType last_type = snap_type_; | 893 SnapType last_type = snap_type_; |
870 snap_type_ = GetSnapType(location); | 894 snap_type_ = GetSnapType(location); |
871 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 895 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
872 snap_phantom_window_controller_.reset(); | 896 snap_phantom_window_controller_.reset(); |
873 snap_sizer_.reset(); | 897 snap_sizer_.reset(); |
| 898 UpdateDockedState(false); |
874 if (snap_type_ == SNAP_NONE) | 899 if (snap_type_ == SNAP_NONE) |
875 return; | 900 return; |
876 } | 901 } |
| 902 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? |
| 903 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| 904 |
877 if (!snap_sizer_) { | 905 if (!snap_sizer_) { |
878 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? | |
879 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | |
880 snap_sizer_.reset(new SnapSizer(window(), | 906 snap_sizer_.reset(new SnapSizer(window(), |
881 location, | 907 location, |
882 edge, | 908 edge, |
883 internal::SnapSizer::OTHER_INPUT)); | 909 internal::SnapSizer::OTHER_INPUT)); |
884 } else { | 910 } else { |
885 snap_sizer_->Update(location); | 911 snap_sizer_->Update(location); |
886 } | 912 } |
| 913 |
| 914 const bool can_dock = dock_layout_->CanDockWindow(window(), snap_type_); |
| 915 if (!wm::CanSnapWindow(window()) && !can_dock) |
| 916 return; |
| 917 |
| 918 // Update phantom window with snapped or docked guide bounds. |
| 919 // Windows that cannot be snapped or are less wide than kMaxDockWidth can get |
| 920 // docked without going through a snapping sequence. |
| 921 gfx::Rect phantom_bounds; |
| 922 if (!can_dock || |
| 923 window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth) |
| 924 phantom_bounds = snap_sizer_->target_bounds(); |
| 925 const bool is_docked = can_dock && |
| 926 (phantom_bounds.IsEmpty() || snap_sizer_->end_of_sequence()); |
| 927 UpdateDockedState(is_docked); |
| 928 if (is_docked) { |
| 929 phantom_bounds = ScreenAsh::ConvertRectFromScreen( |
| 930 window()->parent(), dock_layout_->dragged_bounds()); |
| 931 } |
| 932 |
| 933 if (phantom_bounds.IsEmpty()) { |
| 934 snap_phantom_window_controller_.reset(); |
| 935 return; |
| 936 } |
| 937 |
887 if (!snap_phantom_window_controller_) { | 938 if (!snap_phantom_window_controller_) { |
888 snap_phantom_window_controller_.reset( | 939 snap_phantom_window_controller_.reset( |
889 new PhantomWindowController(window())); | 940 new PhantomWindowController(window())); |
890 } | 941 } |
891 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 942 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
892 window()->parent(), snap_sizer_->target_bounds())); | 943 window()->parent(), phantom_bounds)); |
893 } | 944 } |
894 | 945 |
895 void WorkspaceWindowResizer::RestackWindows() { | 946 void WorkspaceWindowResizer::RestackWindows() { |
896 if (attached_windows_.empty()) | 947 if (attached_windows_.empty()) |
897 return; | 948 return; |
898 // Build a map from index in children to window, returning if there is a | 949 // Build a map from index in children to window, returning if there is a |
899 // window with a different parent. | 950 // window with a different parent. |
900 typedef std::map<size_t, aura::Window*> IndexToWindowMap; | 951 typedef std::map<size_t, aura::Window*> IndexToWindowMap; |
901 IndexToWindowMap map; | 952 IndexToWindowMap map; |
902 aura::Window* parent = window()->parent(); | 953 aura::Window* parent = window()->parent(); |
(...skipping 13 matching lines...) Expand all Loading... |
916 parent->StackChildAtTop(map.rbegin()->second); | 967 parent->StackChildAtTop(map.rbegin()->second); |
917 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 968 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
918 i != map.rend(); ) { | 969 i != map.rend(); ) { |
919 aura::Window* window = i->second; | 970 aura::Window* window = i->second; |
920 ++i; | 971 ++i; |
921 if (i != map.rend()) | 972 if (i != map.rend()) |
922 parent->StackChildBelow(i->second, window); | 973 parent->StackChildBelow(i->second, window); |
923 } | 974 } |
924 } | 975 } |
925 | 976 |
926 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 977 SnapType WorkspaceWindowResizer::GetSnapType( |
927 const gfx::Point& location) const { | 978 const gfx::Point& location) const { |
928 // TODO: this likely only wants total display area, not the area of a single | 979 // TODO: this likely only wants total display area, not the area of a single |
929 // display. | 980 // display. |
930 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); | 981 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
931 if (location.x() <= area.x()) | 982 if (location.x() <= area.x()) |
932 return SNAP_LEFT_EDGE; | 983 return SNAP_LEFT; |
933 if (location.x() >= area.right() - 1) | 984 if (location.x() >= area.right() - 1) |
934 return SNAP_RIGHT_EDGE; | 985 return SNAP_RIGHT; |
935 return SNAP_NONE; | 986 return SNAP_NONE; |
936 } | 987 } |
937 | 988 |
| 989 void WorkspaceWindowResizer::UpdateDockedState(bool is_docked) { |
| 990 if (is_docked && |
| 991 dock_layout_->GetAlignmentOfWindow(window()) != DOCKED_ALIGNMENT_NONE) { |
| 992 if (!dock_layout_->is_dragged_window_docked()) |
| 993 dock_layout_->DockDraggedWindow(window()); |
| 994 } else { |
| 995 if (dock_layout_->is_dragged_window_docked()) |
| 996 dock_layout_->UndockDraggedWindow(); |
| 997 } |
| 998 } |
| 999 |
938 } // namespace internal | 1000 } // namespace internal |
939 } // namespace ash | 1001 } // namespace ash |
OLD | NEW |