Chromium Code Reviews| 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" |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 | 329 |
| 329 private: | 330 private: |
| 330 int size_; | 331 int size_; |
| 331 int min_; | 332 int min_; |
| 332 int max_; | 333 int max_; |
| 333 }; | 334 }; |
| 334 | 335 |
| 335 WorkspaceWindowResizer::~WorkspaceWindowResizer() { | 336 WorkspaceWindowResizer::~WorkspaceWindowResizer() { |
| 336 Shell* shell = Shell::GetInstance(); | 337 Shell* shell = Shell::GetInstance(); |
| 337 shell->cursor_manager()->UnlockCursor(); | 338 shell->cursor_manager()->UnlockCursor(); |
| 339 if (destroyed_) | |
| 340 *destroyed_ = true; | |
| 338 } | 341 } |
| 339 | 342 |
| 340 // static | 343 // static |
| 341 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( | 344 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
| 342 aura::Window* window, | 345 aura::Window* window, |
| 343 const gfx::Point& location_in_parent, | 346 const gfx::Point& location_in_parent, |
| 344 int window_component, | 347 int window_component, |
| 345 aura::client::WindowMoveSource source, | 348 aura::client::WindowMoveSource source, |
| 346 const std::vector<aura::Window*>& attached_windows) { | 349 const std::vector<aura::Window*>& attached_windows) { |
| 347 Details details(window, location_in_parent, window_component, source); | 350 Details details(window, location_in_parent, window_component, source); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 377 if (!did_move_or_resize_) { | 380 if (!did_move_or_resize_) { |
| 378 if (!details_.restore_bounds.IsEmpty()) | 381 if (!details_.restore_bounds.IsEmpty()) |
| 379 ClearRestoreBounds(window()); | 382 ClearRestoreBounds(window()); |
| 380 RestackWindows(); | 383 RestackWindows(); |
| 381 } | 384 } |
| 382 did_move_or_resize_ = true; | 385 did_move_or_resize_ = true; |
| 383 } | 386 } |
| 384 | 387 |
| 385 gfx::Point location_in_screen = location_in_parent; | 388 gfx::Point location_in_screen = location_in_parent; |
| 386 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); | 389 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); |
| 387 const bool in_original_root = | 390 |
| 388 wm::GetRootWindowAt(location_in_screen) == window()->GetRootWindow(); | 391 aura::RootWindow* root = NULL; |
| 392 gfx::Display display = | |
| 393 ScreenAsh::FindDisplayContainingPoint(location_in_screen); | |
| 394 // Keep the snap phantom on screen when pointer gets off screen. | |
|
flackr
2013/09/06 02:18:43
This comment sort of describes what we're doing wh
varkha
2013/09/09 15:38:42
Done.
| |
| 395 if (display.is_valid()) { | |
| 396 root = Shell::GetInstance()->display_controller()-> | |
| 397 GetRootWindowForDisplayId(display.id()); | |
| 398 } | |
| 399 bool destroyed = false; | |
|
flackr
2013/09/06 02:18:43
FYI, I'm not especially fond of this pattern, I pu
varkha
2013/09/09 15:38:42
Done.
| |
| 400 destroyed_ = &destroyed; | |
| 401 if (!attached_windows_.empty()) | |
| 402 LayoutAttachedWindows(&bounds); | |
|
flackr
2013/09/06 02:18:43
Presumably this cannot delete the resizer since yo
varkha
2013/09/09 15:38:42
Done.
| |
| 403 if (bounds != window()->bounds()) | |
| 404 window()->SetBounds(bounds); | |
| 405 if (destroyed) | |
| 406 return; | |
| 407 destroyed_ = NULL; | |
| 408 | |
| 409 const bool in_original_root = !root || root == window()->GetRootWindow(); | |
| 389 // Hide a phantom window for snapping if the cursor is in another root window. | 410 // Hide a phantom window for snapping if the cursor is in another root window. |
| 390 if (in_original_root && wm::CanResizeWindow(window())) { | 411 if (in_original_root) { |
| 391 UpdateSnapPhantomWindow(location_in_parent, bounds); | 412 UpdateSnapPhantomWindow(location_in_parent, bounds); |
| 392 } else { | 413 } else { |
| 393 snap_type_ = SNAP_NONE; | 414 snap_type_ = SNAP_NONE; |
| 394 snap_phantom_window_controller_.reset(); | 415 snap_phantom_window_controller_.reset(); |
|
flackr
2013/09/06 02:18:43
Should snap_sizer_ be reset here too since we're n
varkha
2013/09/09 15:38:42
Done.
| |
| 395 } | 416 } |
| 396 | |
| 397 if (!attached_windows_.empty()) | |
| 398 LayoutAttachedWindows(&bounds); | |
| 399 if (bounds != window()->bounds()) | |
| 400 window()->SetBounds(bounds); | |
| 401 } | 417 } |
| 402 | 418 |
| 403 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 419 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
| 404 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); | 420 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); |
| 405 snap_phantom_window_controller_.reset(); | 421 snap_phantom_window_controller_.reset(); |
| 406 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 422 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| 407 return; | 423 return; |
| 408 | 424 |
| 409 // When the window is not in the normal show state, we do not snap the window. | 425 // 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 | 426 // 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 | 427 // 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 | 428 // out of a maximized window, it's already in the normal show state when this |
| 413 // is called, so it does not matter. | 429 // is called, so it does not matter. |
| 414 if (wm::IsWindowNormal(window()) && | 430 if (wm::IsWindowNormal(window()) && |
| 415 (window()->type() != aura::client::WINDOW_TYPE_PANEL || | 431 (window()->type() != aura::client::WINDOW_TYPE_PANEL || |
| 416 !window()->GetProperty(kPanelAttachedKey)) && | 432 !window()->GetProperty(kPanelAttachedKey)) && |
| 417 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { | 433 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { |
| 418 if (!GetRestoreBoundsInScreen(window())) { | 434 if (!GetRestoreBoundsInScreen(window())) { |
| 419 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( | 435 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( |
| 420 window()->parent(), details_.initial_bounds_in_parent); | 436 window()->parent(), details_.initial_bounds_in_parent); |
| 421 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? | 437 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? |
| 422 initial_bounds : | 438 initial_bounds : |
| 423 details_.restore_bounds); | 439 details_.restore_bounds); |
| 424 } | 440 } |
| 425 window()->SetBounds(snap_sizer_->target_bounds()); | 441 if (snap_sizer_ && wm::CanResizeWindow(window()) && |
|
flackr
2013/09/06 02:18:43
Is it possible that snap_sizer_ will not be instan
varkha
2013/09/09 15:38:42
Done.
| |
| 442 !snap_sizer_->ShouldDockWindow() && | |
| 443 !snap_sizer_->target_bounds().IsEmpty()) { | |
| 444 window()->SetBounds(snap_sizer_->target_bounds()); | |
| 445 } | |
| 426 return; | 446 return; |
| 427 } | 447 } |
| 428 } | 448 } |
| 429 | 449 |
| 430 void WorkspaceWindowResizer::RevertDrag() { | 450 void WorkspaceWindowResizer::RevertDrag() { |
| 431 snap_phantom_window_controller_.reset(); | 451 snap_phantom_window_controller_.reset(); |
| 432 | 452 |
| 433 if (!did_move_or_resize_) | 453 if (!did_move_or_resize_) |
| 434 return; | 454 return; |
| 435 | 455 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 WorkspaceWindowResizer::WorkspaceWindowResizer( | 489 WorkspaceWindowResizer::WorkspaceWindowResizer( |
| 470 const Details& details, | 490 const Details& details, |
| 471 const std::vector<aura::Window*>& attached_windows) | 491 const std::vector<aura::Window*>& attached_windows) |
| 472 : details_(details), | 492 : details_(details), |
| 473 attached_windows_(attached_windows), | 493 attached_windows_(attached_windows), |
| 474 did_move_or_resize_(false), | 494 did_move_or_resize_(false), |
| 475 total_min_(0), | 495 total_min_(0), |
| 476 total_initial_size_(0), | 496 total_initial_size_(0), |
| 477 snap_type_(SNAP_NONE), | 497 snap_type_(SNAP_NONE), |
| 478 num_mouse_moves_since_bounds_change_(0), | 498 num_mouse_moves_since_bounds_change_(0), |
| 479 magnetism_window_(NULL) { | 499 magnetism_window_(NULL), |
| 500 destroyed_(NULL) { | |
| 480 DCHECK(details_.is_resizable); | 501 DCHECK(details_.is_resizable); |
| 481 | 502 |
| 482 Shell* shell = Shell::GetInstance(); | 503 Shell* shell = Shell::GetInstance(); |
| 483 shell->cursor_manager()->LockCursor(); | 504 shell->cursor_manager()->LockCursor(); |
| 484 | 505 |
| 485 // Only support attaching to the right/bottom. | 506 // Only support attaching to the right/bottom. |
| 486 DCHECK(attached_windows_.empty() || | 507 DCHECK(attached_windows_.empty() || |
| 487 (details.window_component == HTRIGHT || | 508 (details.window_component == HTRIGHT || |
| 488 details.window_component == HTBOTTOM)); | 509 details.window_component == HTBOTTOM)); |
| 489 | 510 |
| 490 // TODO: figure out how to deal with window going off the edge. | 511 // TODO: figure out how to deal with window going off the edge. |
| 491 | 512 |
| 492 // Calculate sizes so that we can maintain the ratios if we need to resize. | 513 // Calculate sizes so that we can maintain the ratios if we need to resize. |
| 493 int total_available = 0; | 514 int total_available = 0; |
| 494 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 515 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 495 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); | 516 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); |
| 496 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); | 517 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); |
| 497 initial_size_.push_back(initial_size); | 518 initial_size_.push_back(initial_size); |
| 498 // If current size is smaller than the min, use the current size as the min. | 519 // If current size is smaller than the min, use the current size as the min. |
| 499 // This way we don't snap on resize. | 520 // This way we don't snap on resize. |
| 500 int min_size = std::min(initial_size, | 521 int min_size = std::min(initial_size, |
| 501 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); | 522 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); |
| 502 total_min_ += min_size; | 523 total_min_ += min_size; |
| 503 total_initial_size_ += initial_size; | 524 total_initial_size_ += initial_size; |
| 504 total_available += std::max(min_size, initial_size) - min_size; | 525 total_available += std::max(min_size, initial_size) - min_size; |
| 505 } | 526 } |
| 527 snap_type_ = GetSnapType(details_.initial_location_in_parent); | |
| 506 } | 528 } |
| 507 | 529 |
| 508 gfx::Rect WorkspaceWindowResizer::GetFinalBounds( | 530 gfx::Rect WorkspaceWindowResizer::GetFinalBounds( |
| 509 const gfx::Rect& bounds) const { | 531 const gfx::Rect& bounds) const { |
| 510 if (snap_phantom_window_controller_.get() && | 532 if (snap_phantom_window_controller_.get() && |
| 511 snap_phantom_window_controller_->IsShowing()) { | 533 snap_phantom_window_controller_->IsShowing()) { |
| 512 return snap_phantom_window_controller_->bounds_in_screen(); | 534 return snap_phantom_window_controller_->bounds_in_screen(); |
| 513 } | 535 } |
| 514 return bounds; | 536 return bounds; |
| 515 } | 537 } |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 848 NOTREACHED(); | 870 NOTREACHED(); |
| 849 } | 871 } |
| 850 return 0; | 872 return 0; |
| 851 } | 873 } |
| 852 | 874 |
| 853 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 875 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
| 854 const gfx::Rect& bounds) { | 876 const gfx::Rect& bounds) { |
| 855 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 877 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
| 856 return; | 878 return; |
| 857 | 879 |
| 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_; | 880 SnapType last_type = snap_type_; |
| 867 snap_type_ = GetSnapType(location); | 881 snap_type_ = GetSnapType(location); |
| 868 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 882 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
| 869 snap_phantom_window_controller_.reset(); | 883 snap_phantom_window_controller_.reset(); |
| 884 if (snap_type_ == SNAP_NONE && snap_type_ != last_type) { | |
| 885 // Create and delete a SnapSizer to maintain docked state. | |
| 886 snap_sizer_.reset(new SnapSizer( | |
| 887 window(), | |
| 888 details_.initial_location_in_parent, | |
| 889 (last_type == SNAP_LEFT) ? | |
| 890 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE, | |
| 891 internal::SnapSizer::WORKSPACE_DRAG_INPUT)); | |
| 892 } | |
| 870 snap_sizer_.reset(); | 893 snap_sizer_.reset(); |
| 871 if (snap_type_ == SNAP_NONE) | 894 if (snap_type_ == SNAP_NONE) |
| 872 return; | 895 return; |
| 873 } | 896 } |
| 897 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? | |
| 898 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | |
| 899 | |
| 874 if (!snap_sizer_) { | 900 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(), | 901 snap_sizer_.reset(new SnapSizer(window(), |
| 878 location, | 902 location, |
| 879 edge, | 903 edge, |
| 880 internal::SnapSizer::OTHER_INPUT)); | 904 internal::SnapSizer::WORKSPACE_DRAG_INPUT)); |
| 881 } else { | 905 } else { |
| 882 snap_sizer_->Update(location); | 906 snap_sizer_->Update(location); |
| 883 } | 907 } |
| 908 | |
| 909 // Update phantom window when it is used for side-maximizing. | |
| 910 // In case of docking it will be called directly by the chained resizer. | |
| 911 if (!wm::CanSnapWindow(window()) && !SnapSizer::CanDockWindow(window(), edge)) | |
| 912 return; | |
| 913 | |
| 914 LOG(INFO) << "SNAP BOUNDS " << snap_sizer_->target_bounds().ToString(); | |
| 915 | |
| 916 if (snap_sizer_->target_bounds().IsEmpty()) { | |
| 917 snap_phantom_window_controller_.reset(); | |
| 918 return; | |
| 919 } | |
| 884 if (!snap_phantom_window_controller_) { | 920 if (!snap_phantom_window_controller_) { |
| 885 snap_phantom_window_controller_.reset( | 921 snap_phantom_window_controller_.reset( |
| 886 new PhantomWindowController(window())); | 922 new PhantomWindowController(window())); |
| 887 } | 923 } |
| 888 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 924 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
| 889 window()->parent(), snap_sizer_->target_bounds())); | 925 window()->parent(), snap_sizer_->target_bounds())); |
| 890 } | 926 } |
| 891 | 927 |
| 892 void WorkspaceWindowResizer::RestackWindows() { | 928 void WorkspaceWindowResizer::RestackWindows() { |
| 893 if (attached_windows_.empty()) | 929 if (attached_windows_.empty()) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 913 parent->StackChildAtTop(map.rbegin()->second); | 949 parent->StackChildAtTop(map.rbegin()->second); |
| 914 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 950 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
| 915 i != map.rend(); ) { | 951 i != map.rend(); ) { |
| 916 aura::Window* window = i->second; | 952 aura::Window* window = i->second; |
| 917 ++i; | 953 ++i; |
| 918 if (i != map.rend()) | 954 if (i != map.rend()) |
| 919 parent->StackChildBelow(i->second, window); | 955 parent->StackChildBelow(i->second, window); |
| 920 } | 956 } |
| 921 } | 957 } |
| 922 | 958 |
| 923 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 959 SnapType WorkspaceWindowResizer::GetSnapType( |
| 924 const gfx::Point& location) const { | 960 const gfx::Point& location) const { |
| 925 // TODO: this likely only wants total display area, not the area of a single | 961 // TODO: this likely only wants total display area, not the area of a single |
| 926 // display. | 962 // display. |
| 927 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); | 963 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
| 928 if (location.x() <= area.x()) | 964 if (location.x() <= area.x()) |
| 929 return SNAP_LEFT_EDGE; | 965 return SNAP_LEFT; |
| 930 if (location.x() >= area.right() - 1) | 966 if (location.x() >= area.right() - 1) |
| 931 return SNAP_RIGHT_EDGE; | 967 return SNAP_RIGHT; |
| 932 return SNAP_NONE; | 968 return SNAP_NONE; |
| 933 } | 969 } |
| 934 | 970 |
| 935 } // namespace internal | 971 } // namespace internal |
| 936 } // namespace ash | 972 } // namespace ash |
| OLD | NEW |