| 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/display/display_controller.h" | 12 #include "ash/display/display_controller.h" |
| 13 #include "ash/display/mouse_cursor_event_filter.h" | 13 #include "ash/display/mouse_cursor_event_filter.h" |
| 14 #include "ash/screen_ash.h" | 14 #include "ash/screen_ash.h" |
| 15 #include "ash/shell.h" | 15 #include "ash/shell.h" |
| 16 #include "ash/shell_window_ids.h" | 16 #include "ash/shell_window_ids.h" |
| 17 #include "ash/wm/coordinate_conversion.h" | 17 #include "ash/wm/coordinate_conversion.h" |
| 18 #include "ash/wm/cursor_manager.h" | 18 #include "ash/wm/cursor_manager.h" |
| 19 #include "ash/wm/default_window_resizer.h" | 19 #include "ash/wm/default_window_resizer.h" |
| 20 #include "ash/wm/drag_window_controller.h" |
| 20 #include "ash/wm/property_util.h" | 21 #include "ash/wm/property_util.h" |
| 21 #include "ash/wm/window_util.h" | 22 #include "ash/wm/window_util.h" |
| 22 #include "ash/wm/workspace/phantom_window_controller.h" | 23 #include "ash/wm/workspace/phantom_window_controller.h" |
| 23 #include "ash/wm/workspace/snap_sizer.h" | 24 #include "ash/wm/workspace/snap_sizer.h" |
| 24 #include "ui/aura/client/aura_constants.h" | 25 #include "ui/aura/client/aura_constants.h" |
| 25 #include "ui/aura/root_window.h" | 26 #include "ui/aura/root_window.h" |
| 26 #include "ui/aura/window.h" | 27 #include "ui/aura/window.h" |
| 27 #include "ui/aura/window_delegate.h" | 28 #include "ui/aura/window_delegate.h" |
| 28 #include "ui/base/hit_test.h" | 29 #include "ui/base/hit_test.h" |
| 29 #include "ui/compositor/layer.h" | 30 #include "ui/compositor/layer.h" |
| 30 #include "ui/gfx/screen.h" | 31 #include "ui/gfx/screen.h" |
| 31 #include "ui/gfx/transform.h" | 32 #include "ui/gfx/transform.h" |
| 32 #include "ui/views/corewm/window_util.h" | |
| 33 | 33 |
| 34 namespace ash { | 34 namespace ash { |
| 35 | 35 |
| 36 scoped_ptr<WindowResizer> CreateWindowResizer(aura::Window* window, | 36 scoped_ptr<WindowResizer> CreateWindowResizer(aura::Window* window, |
| 37 const gfx::Point& point_in_parent, | 37 const gfx::Point& point_in_parent, |
| 38 int window_component) { | 38 int window_component) { |
| 39 DCHECK(window); | 39 DCHECK(window); |
| 40 // No need to return a resizer when the window cannot get resized. | 40 // No need to return a resizer when the window cannot get resized. |
| 41 if (!wm::CanResizeWindow(window) && window_component != HTCAPTION) | 41 if (!wm::CanResizeWindow(window) && window_component != HTCAPTION) |
| 42 return scoped_ptr<WindowResizer>(); | 42 return scoped_ptr<WindowResizer>(); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 int max_; | 305 int max_; |
| 306 }; | 306 }; |
| 307 | 307 |
| 308 WorkspaceWindowResizer::~WorkspaceWindowResizer() { | 308 WorkspaceWindowResizer::~WorkspaceWindowResizer() { |
| 309 Shell* shell = Shell::GetInstance(); | 309 Shell* shell = Shell::GetInstance(); |
| 310 shell->mouse_cursor_filter()->set_mouse_warp_mode( | 310 shell->mouse_cursor_filter()->set_mouse_warp_mode( |
| 311 MouseCursorEventFilter::WARP_ALWAYS); | 311 MouseCursorEventFilter::WARP_ALWAYS); |
| 312 shell->mouse_cursor_filter()->HideSharedEdgeIndicator(); | 312 shell->mouse_cursor_filter()->HideSharedEdgeIndicator(); |
| 313 shell->cursor_manager()->UnlockCursor(); | 313 shell->cursor_manager()->UnlockCursor(); |
| 314 | 314 |
| 315 // Delete phantom controllers first so that they will never see the deleted | |
| 316 // |layer_|. | |
| 317 snap_phantom_window_controller_.reset(); | |
| 318 drag_phantom_window_controller_.reset(); | |
| 319 | |
| 320 if (layer_) | |
| 321 views::corewm::DeepDeleteLayers(layer_); | |
| 322 | |
| 323 if (destroyed_) | 315 if (destroyed_) |
| 324 *destroyed_ = true; | 316 *destroyed_ = true; |
| 325 } | 317 } |
| 326 | 318 |
| 327 // static | 319 // static |
| 328 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( | 320 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
| 329 aura::Window* window, | 321 aura::Window* window, |
| 330 const gfx::Point& location_in_parent, | 322 const gfx::Point& location_in_parent, |
| 331 int window_component, | 323 int window_component, |
| 332 const std::vector<aura::Window*>& attached_windows) { | 324 const std::vector<aura::Window*>& attached_windows) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 if (bounds != window()->bounds()) { | 365 if (bounds != window()->bounds()) { |
| 374 bool destroyed = false; | 366 bool destroyed = false; |
| 375 destroyed_ = &destroyed; | 367 destroyed_ = &destroyed; |
| 376 window()->SetBounds(bounds); | 368 window()->SetBounds(bounds); |
| 377 if (destroyed) | 369 if (destroyed) |
| 378 return; | 370 return; |
| 379 destroyed_ = NULL; | 371 destroyed_ = NULL; |
| 380 } | 372 } |
| 381 // Show a phantom window for dragging in another root window. | 373 // Show a phantom window for dragging in another root window. |
| 382 if (HasSecondaryRootWindow()) | 374 if (HasSecondaryRootWindow()) |
| 383 UpdateDragPhantomWindow(bounds, in_original_root); | 375 UpdateDragWindow(bounds, in_original_root); |
| 384 else | 376 else |
| 385 drag_phantom_window_controller_.reset(); | 377 drag_window_controller_.reset(); |
| 386 | 378 |
| 387 } | 379 } |
| 388 | 380 |
| 389 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 381 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
| 390 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); | 382 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); |
| 391 window()->layer()->SetOpacity(details_.initial_opacity); | 383 window()->layer()->SetOpacity(details_.initial_opacity); |
| 392 drag_phantom_window_controller_.reset(); | 384 drag_window_controller_.reset(); |
| 393 snap_phantom_window_controller_.reset(); | 385 snap_phantom_window_controller_.reset(); |
| 394 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 386 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| 395 return; | 387 return; |
| 396 | 388 |
| 397 // When the window is not in the normal show state, we do not snap thw window. | 389 // When the window is not in the normal show state, we do not snap thw window. |
| 398 // This happens when the user minimizes or maximizes the window by keyboard | 390 // This happens when the user minimizes or maximizes the window by keyboard |
| 399 // shortcut while dragging it. If the window is the result of dragging a tab | 391 // shortcut while dragging it. If the window is the result of dragging a tab |
| 400 // out of a maximized window, it's already in the normal show state when this | 392 // out of a maximized window, it's already in the normal show state when this |
| 401 // is called, so it does not matter. | 393 // is called, so it does not matter. |
| 402 if (wm::IsWindowNormal(window()) && | 394 if (wm::IsWindowNormal(window()) && |
| (...skipping 21 matching lines...) Expand all Loading... |
| 424 screen->GetDisplayNearestWindow(window()->GetRootWindow()).id()) { | 416 screen->GetDisplayNearestWindow(window()->GetRootWindow()).id()) { |
| 425 // Don't animate when moving to another display. | 417 // Don't animate when moving to another display. |
| 426 const gfx::Rect dst_bounds = | 418 const gfx::Rect dst_bounds = |
| 427 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); | 419 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); |
| 428 window()->SetBoundsInScreen(dst_bounds, dst_display); | 420 window()->SetBoundsInScreen(dst_bounds, dst_display); |
| 429 } | 421 } |
| 430 } | 422 } |
| 431 | 423 |
| 432 void WorkspaceWindowResizer::RevertDrag() { | 424 void WorkspaceWindowResizer::RevertDrag() { |
| 433 window()->layer()->SetOpacity(details_.initial_opacity); | 425 window()->layer()->SetOpacity(details_.initial_opacity); |
| 434 drag_phantom_window_controller_.reset(); | 426 drag_window_controller_.reset(); |
| 435 snap_phantom_window_controller_.reset(); | 427 snap_phantom_window_controller_.reset(); |
| 436 Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator(); | 428 Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator(); |
| 437 | 429 |
| 438 if (!did_move_or_resize_) | 430 if (!did_move_or_resize_) |
| 439 return; | 431 return; |
| 440 | 432 |
| 441 window()->SetBounds(details_.initial_bounds_in_parent); | 433 window()->SetBounds(details_.initial_bounds_in_parent); |
| 442 if (!details_.restore_bounds.IsEmpty()) | 434 if (!details_.restore_bounds.IsEmpty()) |
| 443 SetRestoreBoundsInScreen(details_.window, details_.restore_bounds); | 435 SetRestoreBoundsInScreen(details_.window, details_.restore_bounds); |
| 444 | 436 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 470 WorkspaceWindowResizer::WorkspaceWindowResizer( | 462 WorkspaceWindowResizer::WorkspaceWindowResizer( |
| 471 const Details& details, | 463 const Details& details, |
| 472 const std::vector<aura::Window*>& attached_windows) | 464 const std::vector<aura::Window*>& attached_windows) |
| 473 : details_(details), | 465 : details_(details), |
| 474 attached_windows_(attached_windows), | 466 attached_windows_(attached_windows), |
| 475 did_move_or_resize_(false), | 467 did_move_or_resize_(false), |
| 476 total_min_(0), | 468 total_min_(0), |
| 477 total_initial_size_(0), | 469 total_initial_size_(0), |
| 478 snap_type_(SNAP_NONE), | 470 snap_type_(SNAP_NONE), |
| 479 num_mouse_moves_since_bounds_change_(0), | 471 num_mouse_moves_since_bounds_change_(0), |
| 480 layer_(NULL), | |
| 481 destroyed_(NULL), | 472 destroyed_(NULL), |
| 482 magnetism_window_(NULL) { | 473 magnetism_window_(NULL) { |
| 483 DCHECK(details_.is_resizable); | 474 DCHECK(details_.is_resizable); |
| 484 | 475 |
| 485 Shell* shell = Shell::GetInstance(); | 476 Shell* shell = Shell::GetInstance(); |
| 486 shell->cursor_manager()->LockCursor(); | 477 shell->cursor_manager()->LockCursor(); |
| 487 | 478 |
| 488 // The pointer should be confined in one display during resizing a window | 479 // The pointer should be confined in one display during resizing a window |
| 489 // because the window cannot span two displays at the same time anyway. The | 480 // because the window cannot span two displays at the same time anyway. The |
| 490 // exception is window/tab dragging operation. During that operation, | 481 // exception is window/tab dragging operation. During that operation, |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 case HTRIGHT: | 811 case HTRIGHT: |
| 821 return x; | 812 return x; |
| 822 case HTBOTTOM: | 813 case HTBOTTOM: |
| 823 return y; | 814 return y; |
| 824 default: | 815 default: |
| 825 NOTREACHED(); | 816 NOTREACHED(); |
| 826 } | 817 } |
| 827 return 0; | 818 return 0; |
| 828 } | 819 } |
| 829 | 820 |
| 830 void WorkspaceWindowResizer::UpdateDragPhantomWindow(const gfx::Rect& bounds, | 821 void WorkspaceWindowResizer::UpdateDragWindow(const gfx::Rect& bounds, |
| 831 bool in_original_root) { | 822 bool in_original_root) { |
| 832 if (!did_move_or_resize_ || details_.window_component != HTCAPTION || | 823 if (!did_move_or_resize_ || details_.window_component != HTCAPTION || |
| 833 !ShouldAllowMouseWarp()) { | 824 !ShouldAllowMouseWarp()) { |
| 834 return; | 825 return; |
| 835 } | 826 } |
| 836 | 827 |
| 837 // It's available. Show a phantom window on the display if needed. | 828 // It's available. Show a phantom window on the display if needed. |
| 838 aura::RootWindow* another_root = | 829 aura::RootWindow* another_root = |
| 839 GetAnotherRootWindow(window()->GetRootWindow()); | 830 GetAnotherRootWindow(window()->GetRootWindow()); |
| 840 const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen()); | 831 const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen()); |
| 841 const gfx::Rect bounds_in_screen = | 832 const gfx::Rect bounds_in_screen = |
| 842 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); | 833 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); |
| 843 gfx::Rect bounds_in_another_root = | 834 gfx::Rect bounds_in_another_root = |
| 844 gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen); | 835 gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen); |
| 845 | 836 |
| 846 const float fraction_in_another_window = | 837 const float fraction_in_another_window = |
| 847 (bounds_in_another_root.width() * bounds_in_another_root.height()) / | 838 (bounds_in_another_root.width() * bounds_in_another_root.height()) / |
| 848 static_cast<float>(bounds.width() * bounds.height()); | 839 static_cast<float>(bounds.width() * bounds.height()); |
| 849 const float phantom_opacity = | 840 const float phantom_opacity = |
| 850 !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window); | 841 !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window); |
| 851 const float window_opacity = | 842 const float window_opacity = |
| 852 in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window)); | 843 in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window)); |
| 853 | 844 |
| 854 if (fraction_in_another_window > 0) { | 845 if (fraction_in_another_window > 0) { |
| 855 if (!drag_phantom_window_controller_.get()) { | 846 if (!drag_window_controller_.get()) { |
| 856 drag_phantom_window_controller_.reset( | 847 drag_window_controller_.reset( |
| 857 new PhantomWindowController(window())); | 848 new DragWindowController(window())); |
| 858 drag_phantom_window_controller_->set_style( | |
| 859 PhantomWindowController::STYLE_DRAGGING); | |
| 860 // Always show the drag phantom on the |another_root| window. | 849 // Always show the drag phantom on the |another_root| window. |
| 861 drag_phantom_window_controller_->SetDestinationDisplay( | 850 drag_window_controller_->SetDestinationDisplay( |
| 862 Shell::GetScreen()->GetDisplayMatching( | 851 Shell::GetScreen()->GetDisplayMatching( |
| 863 another_root->GetBoundsInScreen())); | 852 another_root->GetBoundsInScreen())); |
| 864 if (!layer_) | 853 drag_window_controller_->Show(); |
| 865 RecreateWindowLayers(); | |
| 866 drag_phantom_window_controller_->Show(bounds_in_screen, layer_); | |
| 867 } else { | 854 } else { |
| 868 // No animation. | 855 // No animation. |
| 869 drag_phantom_window_controller_->SetBounds(bounds_in_screen); | 856 drag_window_controller_->SetBounds(bounds_in_screen); |
| 870 } | 857 } |
| 871 drag_phantom_window_controller_->SetOpacity(phantom_opacity); | 858 drag_window_controller_->SetOpacity(phantom_opacity); |
| 872 window()->layer()->SetOpacity(window_opacity); | 859 window()->layer()->SetOpacity(window_opacity); |
| 873 } else { | 860 } else { |
| 874 drag_phantom_window_controller_.reset(); | 861 drag_window_controller_.reset(); |
| 875 window()->layer()->SetOpacity(1.0f); | 862 window()->layer()->SetOpacity(1.0f); |
| 876 } | 863 } |
| 877 } | 864 } |
| 878 | 865 |
| 879 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 866 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
| 880 const gfx::Rect& bounds) { | 867 const gfx::Rect& bounds) { |
| 881 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 868 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| 882 return; | 869 return; |
| 883 | 870 |
| 884 if (!wm::CanSnapWindow(window())) | 871 if (!wm::CanSnapWindow(window())) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 900 edge, | 887 edge, |
| 901 internal::SnapSizer::OTHER_INPUT)); | 888 internal::SnapSizer::OTHER_INPUT)); |
| 902 } else { | 889 } else { |
| 903 snap_sizer_->Update(location); | 890 snap_sizer_->Update(location); |
| 904 } | 891 } |
| 905 if (!snap_phantom_window_controller_.get()) { | 892 if (!snap_phantom_window_controller_.get()) { |
| 906 snap_phantom_window_controller_.reset( | 893 snap_phantom_window_controller_.reset( |
| 907 new PhantomWindowController(window())); | 894 new PhantomWindowController(window())); |
| 908 } | 895 } |
| 909 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 896 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
| 910 window()->parent(), snap_sizer_->target_bounds()), NULL); | 897 window()->parent(), snap_sizer_->target_bounds())); |
| 911 } | 898 } |
| 912 | 899 |
| 913 void WorkspaceWindowResizer::RestackWindows() { | 900 void WorkspaceWindowResizer::RestackWindows() { |
| 914 if (attached_windows_.empty()) | 901 if (attached_windows_.empty()) |
| 915 return; | 902 return; |
| 916 // Build a map from index in children to window, returning if there is a | 903 // Build a map from index in children to window, returning if there is a |
| 917 // window with a different parent. | 904 // window with a different parent. |
| 918 typedef std::map<size_t, aura::Window*> IndexToWindowMap; | 905 typedef std::map<size_t, aura::Window*> IndexToWindowMap; |
| 919 IndexToWindowMap map; | 906 IndexToWindowMap map; |
| 920 aura::Window* parent = window()->parent(); | 907 aura::Window* parent = window()->parent(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 return SNAP_RIGHT_EDGE; | 939 return SNAP_RIGHT_EDGE; |
| 953 return SNAP_NONE; | 940 return SNAP_NONE; |
| 954 } | 941 } |
| 955 | 942 |
| 956 bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const { | 943 bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const { |
| 957 return (details_.window_component == HTCAPTION) && | 944 return (details_.window_component == HTCAPTION) && |
| 958 (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) && | 945 (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) && |
| 959 (window()->type() == aura::client::WINDOW_TYPE_NORMAL); | 946 (window()->type() == aura::client::WINDOW_TYPE_NORMAL); |
| 960 } | 947 } |
| 961 | 948 |
| 962 void WorkspaceWindowResizer::RecreateWindowLayers() { | |
| 963 DCHECK(!layer_); | |
| 964 layer_ = views::corewm::RecreateWindowLayers(window(), true); | |
| 965 layer_->set_delegate(window()->layer()->delegate()); | |
| 966 // Place the layer at (0, 0) of the PhantomWindowController's window. | |
| 967 gfx::Rect layer_bounds = layer_->bounds(); | |
| 968 layer_bounds.set_origin(gfx::Point(0, 0)); | |
| 969 layer_->SetBounds(layer_bounds); | |
| 970 layer_->SetVisible(false); | |
| 971 // Detach it from the current container. | |
| 972 layer_->parent()->Remove(layer_); | |
| 973 } | |
| 974 | |
| 975 } // namespace internal | 949 } // namespace internal |
| 976 } // namespace ash | 950 } // namespace ash |
| OLD | NEW |