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" |
19 #include "ash/wm/dock/docked_window_resizer.h" | 20 #include "ash/wm/dock/docked_window_resizer.h" |
20 #include "ash/wm/drag_window_resizer.h" | 21 #include "ash/wm/drag_window_resizer.h" |
21 #include "ash/wm/panels/panel_window_resizer.h" | 22 #include "ash/wm/panels/panel_window_resizer.h" |
22 #include "ash/wm/property_util.h" | 23 #include "ash/wm/property_util.h" |
23 #include "ash/wm/window_properties.h" | 24 #include "ash/wm/window_properties.h" |
24 #include "ash/wm/window_util.h" | 25 #include "ash/wm/window_util.h" |
25 #include "ash/wm/workspace/phantom_window_controller.h" | 26 #include "ash/wm/workspace/phantom_window_controller.h" |
26 #include "ash/wm/workspace/snap_sizer.h" | 27 #include "ash/wm/workspace/snap_sizer.h" |
27 #include "base/command_line.h" | 28 #include "base/command_line.h" |
| 29 #include "base/memory/weak_ptr.h" |
28 #include "ui/aura/client/aura_constants.h" | 30 #include "ui/aura/client/aura_constants.h" |
29 #include "ui/aura/client/screen_position_client.h" | 31 #include "ui/aura/client/screen_position_client.h" |
30 #include "ui/aura/client/window_types.h" | 32 #include "ui/aura/client/window_types.h" |
31 #include "ui/aura/root_window.h" | 33 #include "ui/aura/root_window.h" |
32 #include "ui/aura/window.h" | 34 #include "ui/aura/window.h" |
33 #include "ui/aura/window_delegate.h" | 35 #include "ui/aura/window_delegate.h" |
34 #include "ui/base/hit_test.h" | 36 #include "ui/base/hit_test.h" |
35 #include "ui/compositor/layer.h" | 37 #include "ui/compositor/layer.h" |
36 #include "ui/gfx/screen.h" | 38 #include "ui/gfx/screen.h" |
37 #include "ui/gfx/transform.h" | 39 #include "ui/gfx/transform.h" |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); | 373 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); |
372 | 374 |
373 if (wm::IsWindowNormal(window())) | 375 if (wm::IsWindowNormal(window())) |
374 AdjustBoundsForMainWindow(sticky_size, &bounds); | 376 AdjustBoundsForMainWindow(sticky_size, &bounds); |
375 | 377 |
376 if (bounds != window()->bounds()) { | 378 if (bounds != window()->bounds()) { |
377 if (!did_move_or_resize_) { | 379 if (!did_move_or_resize_) { |
378 if (!details_.restore_bounds.IsEmpty()) | 380 if (!details_.restore_bounds.IsEmpty()) |
379 ClearRestoreBounds(window()); | 381 ClearRestoreBounds(window()); |
380 RestackWindows(); | 382 RestackWindows(); |
| 383 DCHECK(!snap_sizer_); |
| 384 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { |
| 385 // Create SnapSizer if a window is snapped to maintain docked state. |
| 386 snap_sizer_.reset(new SnapSizer( |
| 387 window(), |
| 388 details_.initial_location_in_parent, |
| 389 (snap_type_ == SNAP_LEFT) ? |
| 390 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE, |
| 391 internal::SnapSizer::WORKSPACE_DRAG_INPUT)); |
| 392 } |
381 } | 393 } |
382 did_move_or_resize_ = true; | 394 did_move_or_resize_ = true; |
383 } | 395 } |
384 | 396 |
385 gfx::Point location_in_screen = location_in_parent; | 397 gfx::Point location_in_screen = location_in_parent; |
386 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); | 398 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); |
387 const bool in_original_root = | 399 |
388 wm::GetRootWindowAt(location_in_screen) == window()->GetRootWindow(); | 400 aura::RootWindow* root = NULL; |
| 401 gfx::Display display = |
| 402 ScreenAsh::FindDisplayContainingPoint(location_in_screen); |
| 403 // Track the last screen that the pointer was on to keep the snap phantom |
| 404 // window there. |
| 405 if (display.is_valid()) { |
| 406 root = Shell::GetInstance()->display_controller()-> |
| 407 GetRootWindowForDisplayId(display.id()); |
| 408 } |
| 409 if (!attached_windows_.empty()) |
| 410 LayoutAttachedWindows(&bounds); |
| 411 if (bounds != window()->bounds()) { |
| 412 // SetBounds needs to be called to update the layout which affects where the |
| 413 // phantom window is drawn. Keep track if the window was destroyed during |
| 414 // the drag and quit early if so. |
| 415 base::WeakPtr<WorkspaceWindowResizer> resizer( |
| 416 weak_ptr_factory_.GetWeakPtr()); |
| 417 window()->SetBounds(bounds); |
| 418 if (!resizer) |
| 419 return; |
| 420 } |
| 421 const bool in_original_root = !root || root == window()->GetRootWindow(); |
389 // Hide a phantom window for snapping if the cursor is in another root window. | 422 // Hide a phantom window for snapping if the cursor is in another root window. |
390 if (in_original_root && wm::CanResizeWindow(window())) { | 423 if (in_original_root) { |
391 UpdateSnapPhantomWindow(location_in_parent, bounds); | 424 UpdateSnapPhantomWindow(location_in_parent, bounds); |
392 } else { | 425 } else { |
393 snap_type_ = SNAP_NONE; | 426 snap_type_ = SNAP_NONE; |
394 snap_phantom_window_controller_.reset(); | 427 snap_phantom_window_controller_.reset(); |
| 428 snap_sizer_.reset(); |
395 } | 429 } |
396 | |
397 if (!attached_windows_.empty()) | |
398 LayoutAttachedWindows(&bounds); | |
399 if (bounds != window()->bounds()) | |
400 window()->SetBounds(bounds); | |
401 } | 430 } |
402 | 431 |
403 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 432 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
404 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); | 433 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); |
405 snap_phantom_window_controller_.reset(); | 434 snap_phantom_window_controller_.reset(); |
406 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 435 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
407 return; | 436 return; |
408 | 437 |
409 // When the window is not in the normal show state, we do not snap the window. | 438 // When the window is not in the normal show state, we do not snap the window. |
410 // This happens when the user minimizes or maximizes the window by keyboard | 439 // This happens when the user minimizes or maximizes the window by keyboard |
411 // shortcut while dragging it. If the window is the result of dragging a tab | 440 // shortcut while dragging it. If the window is the result of dragging a tab |
412 // out of a maximized window, it's already in the normal show state when this | 441 // out of a maximized window, it's already in the normal show state when this |
413 // is called, so it does not matter. | 442 // is called, so it does not matter. |
414 if (wm::IsWindowNormal(window()) && | 443 if (wm::IsWindowNormal(window()) && |
415 (window()->type() != aura::client::WINDOW_TYPE_PANEL || | 444 (window()->type() != aura::client::WINDOW_TYPE_PANEL || |
416 !window()->GetProperty(kPanelAttachedKey)) && | 445 !window()->GetProperty(kPanelAttachedKey)) && |
417 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { | 446 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { |
418 if (!GetRestoreBoundsInScreen(window())) { | 447 if (!GetRestoreBoundsInScreen(window())) { |
419 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( | 448 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( |
420 window()->parent(), details_.initial_bounds_in_parent); | 449 window()->parent(), details_.initial_bounds_in_parent); |
421 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? | 450 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? |
422 initial_bounds : | 451 initial_bounds : |
423 details_.restore_bounds); | 452 details_.restore_bounds); |
424 } | 453 } |
425 window()->SetBounds(snap_sizer_->target_bounds()); | 454 DCHECK(snap_sizer_); |
| 455 if (wm::CanResizeWindow(window()) && |
| 456 !snap_sizer_->ShouldDockWindow() && |
| 457 !snap_sizer_->target_bounds().IsEmpty()) { |
| 458 window()->SetBounds(snap_sizer_->target_bounds()); |
| 459 } |
426 return; | 460 return; |
427 } | 461 } |
428 } | 462 } |
429 | 463 |
430 void WorkspaceWindowResizer::RevertDrag() { | 464 void WorkspaceWindowResizer::RevertDrag() { |
431 snap_phantom_window_controller_.reset(); | 465 snap_phantom_window_controller_.reset(); |
432 | 466 |
433 if (!did_move_or_resize_) | 467 if (!did_move_or_resize_) |
434 return; | 468 return; |
435 | 469 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 } | 501 } |
468 | 502 |
469 WorkspaceWindowResizer::WorkspaceWindowResizer( | 503 WorkspaceWindowResizer::WorkspaceWindowResizer( |
470 const Details& details, | 504 const Details& details, |
471 const std::vector<aura::Window*>& attached_windows) | 505 const std::vector<aura::Window*>& attached_windows) |
472 : details_(details), | 506 : details_(details), |
473 attached_windows_(attached_windows), | 507 attached_windows_(attached_windows), |
474 did_move_or_resize_(false), | 508 did_move_or_resize_(false), |
475 total_min_(0), | 509 total_min_(0), |
476 total_initial_size_(0), | 510 total_initial_size_(0), |
477 snap_type_(SNAP_NONE), | 511 snap_type_(GetSnapType(details_.initial_location_in_parent)), |
478 num_mouse_moves_since_bounds_change_(0), | 512 num_mouse_moves_since_bounds_change_(0), |
479 magnetism_window_(NULL) { | 513 magnetism_window_(NULL), |
| 514 weak_ptr_factory_(this) { |
480 DCHECK(details_.is_resizable); | 515 DCHECK(details_.is_resizable); |
481 | 516 |
482 Shell* shell = Shell::GetInstance(); | 517 Shell* shell = Shell::GetInstance(); |
483 shell->cursor_manager()->LockCursor(); | 518 shell->cursor_manager()->LockCursor(); |
484 | 519 |
485 // Only support attaching to the right/bottom. | 520 // Only support attaching to the right/bottom. |
486 DCHECK(attached_windows_.empty() || | 521 DCHECK(attached_windows_.empty() || |
487 (details.window_component == HTRIGHT || | 522 (details.window_component == HTRIGHT || |
488 details.window_component == HTBOTTOM)); | 523 details.window_component == HTBOTTOM)); |
489 | 524 |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 NOTREACHED(); | 883 NOTREACHED(); |
849 } | 884 } |
850 return 0; | 885 return 0; |
851 } | 886 } |
852 | 887 |
853 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 888 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
854 const gfx::Rect& bounds) { | 889 const gfx::Rect& bounds) { |
855 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 890 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
856 return; | 891 return; |
857 | 892 |
858 if (!wm::CanSnapWindow(window())) | |
859 return; | |
860 | |
861 if (window()->type() == aura::client::WINDOW_TYPE_PANEL && | |
862 window()->GetProperty(kPanelAttachedKey)) { | |
863 return; | |
864 } | |
865 | |
866 SnapType last_type = snap_type_; | 893 SnapType last_type = snap_type_; |
867 snap_type_ = GetSnapType(location); | 894 snap_type_ = GetSnapType(location); |
868 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 895 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
869 snap_phantom_window_controller_.reset(); | 896 snap_phantom_window_controller_.reset(); |
870 snap_sizer_.reset(); | 897 snap_sizer_.reset(); |
871 if (snap_type_ == SNAP_NONE) | 898 if (snap_type_ == SNAP_NONE) |
872 return; | 899 return; |
873 } | 900 } |
| 901 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? |
| 902 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| 903 |
874 if (!snap_sizer_) { | 904 if (!snap_sizer_) { |
875 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? | |
876 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | |
877 snap_sizer_.reset(new SnapSizer(window(), | 905 snap_sizer_.reset(new SnapSizer(window(), |
878 location, | 906 location, |
879 edge, | 907 edge, |
880 internal::SnapSizer::OTHER_INPUT)); | 908 internal::SnapSizer::WORKSPACE_DRAG_INPUT)); |
881 } else { | 909 } else { |
882 snap_sizer_->Update(location); | 910 snap_sizer_->Update(location); |
883 } | 911 } |
| 912 |
| 913 // Update phantom window when it is used for side-maximizing. |
| 914 // In case of docking it will be called directly by the chained resizer. |
| 915 if (!wm::CanSnapWindow(window()) && !SnapSizer::CanDockWindow(window(), edge)) |
| 916 return; |
| 917 |
| 918 if (snap_sizer_->target_bounds().IsEmpty()) { |
| 919 snap_phantom_window_controller_.reset(); |
| 920 return; |
| 921 } |
884 if (!snap_phantom_window_controller_) { | 922 if (!snap_phantom_window_controller_) { |
885 snap_phantom_window_controller_.reset( | 923 snap_phantom_window_controller_.reset( |
886 new PhantomWindowController(window())); | 924 new PhantomWindowController(window())); |
887 } | 925 } |
888 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 926 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
889 window()->parent(), snap_sizer_->target_bounds())); | 927 window()->parent(), snap_sizer_->target_bounds())); |
890 } | 928 } |
891 | 929 |
892 void WorkspaceWindowResizer::RestackWindows() { | 930 void WorkspaceWindowResizer::RestackWindows() { |
893 if (attached_windows_.empty()) | 931 if (attached_windows_.empty()) |
(...skipping 19 matching lines...) Expand all Loading... |
913 parent->StackChildAtTop(map.rbegin()->second); | 951 parent->StackChildAtTop(map.rbegin()->second); |
914 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 952 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
915 i != map.rend(); ) { | 953 i != map.rend(); ) { |
916 aura::Window* window = i->second; | 954 aura::Window* window = i->second; |
917 ++i; | 955 ++i; |
918 if (i != map.rend()) | 956 if (i != map.rend()) |
919 parent->StackChildBelow(i->second, window); | 957 parent->StackChildBelow(i->second, window); |
920 } | 958 } |
921 } | 959 } |
922 | 960 |
923 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 961 SnapType WorkspaceWindowResizer::GetSnapType( |
924 const gfx::Point& location) const { | 962 const gfx::Point& location) const { |
925 // TODO: this likely only wants total display area, not the area of a single | 963 // TODO: this likely only wants total display area, not the area of a single |
926 // display. | 964 // display. |
927 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); | 965 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
928 if (location.x() <= area.x()) | 966 if (location.x() <= area.x()) |
929 return SNAP_LEFT_EDGE; | 967 return SNAP_LEFT; |
930 if (location.x() >= area.right() - 1) | 968 if (location.x() >= area.right() - 1) |
931 return SNAP_RIGHT_EDGE; | 969 return SNAP_RIGHT; |
932 return SNAP_NONE; | 970 return SNAP_NONE; |
933 } | 971 } |
934 | 972 |
935 } // namespace internal | 973 } // namespace internal |
936 } // namespace ash | 974 } // namespace ash |
OLD | NEW |