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 // Track the last screen that the pointer was on to keep the snap phantom | |
395 // window there. | |
396 if (display.is_valid()) { | |
397 root = Shell::GetInstance()->display_controller()-> | |
398 GetRootWindowForDisplayId(display.id()); | |
399 } | |
400 if (!attached_windows_.empty()) | |
401 LayoutAttachedWindows(&bounds); | |
402 if (bounds != window()->bounds()) { | |
403 // SetBounds needs to be called to update the layout which affects where the | |
404 // phantom window is drawn. Keep track if the window was destroyed during | |
405 // the drag and quit early if so. | |
406 bool destroyed = false; | |
flackr
2013/09/09 19:06:58
Please update this to use a weak_ptr as in https:/
varkha
2013/09/09 20:37:54
Done.
| |
407 destroyed_ = &destroyed; | |
408 window()->SetBounds(bounds); | |
409 if (destroyed) | |
410 return; | |
411 destroyed_ = NULL; | |
412 } | |
413 const bool in_original_root = !root || root == window()->GetRootWindow(); | |
389 // Hide a phantom window for snapping if the cursor is in another root window. | 414 // Hide a phantom window for snapping if the cursor is in another root window. |
390 if (in_original_root && wm::CanResizeWindow(window())) { | 415 if (in_original_root) { |
391 UpdateSnapPhantomWindow(location_in_parent, bounds); | 416 UpdateSnapPhantomWindow(location_in_parent, bounds); |
392 } else { | 417 } else { |
393 snap_type_ = SNAP_NONE; | 418 snap_type_ = SNAP_NONE; |
394 snap_phantom_window_controller_.reset(); | 419 snap_phantom_window_controller_.reset(); |
420 snap_sizer_.reset(); | |
395 } | 421 } |
396 | |
397 if (!attached_windows_.empty()) | |
398 LayoutAttachedWindows(&bounds); | |
399 if (bounds != window()->bounds()) | |
400 window()->SetBounds(bounds); | |
401 } | 422 } |
402 | 423 |
403 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { | 424 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { |
404 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); | 425 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); |
405 snap_phantom_window_controller_.reset(); | 426 snap_phantom_window_controller_.reset(); |
406 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 427 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
407 return; | 428 return; |
408 | 429 |
409 // When the window is not in the normal show state, we do not snap the window. | 430 // 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 | 431 // 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 | 432 // 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 | 433 // out of a maximized window, it's already in the normal show state when this |
413 // is called, so it does not matter. | 434 // is called, so it does not matter. |
414 if (wm::IsWindowNormal(window()) && | 435 if (wm::IsWindowNormal(window()) && |
415 (window()->type() != aura::client::WINDOW_TYPE_PANEL || | 436 (window()->type() != aura::client::WINDOW_TYPE_PANEL || |
416 !window()->GetProperty(kPanelAttachedKey)) && | 437 !window()->GetProperty(kPanelAttachedKey)) && |
417 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { | 438 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { |
418 if (!GetRestoreBoundsInScreen(window())) { | 439 if (!GetRestoreBoundsInScreen(window())) { |
419 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( | 440 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( |
420 window()->parent(), details_.initial_bounds_in_parent); | 441 window()->parent(), details_.initial_bounds_in_parent); |
421 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? | 442 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? |
422 initial_bounds : | 443 initial_bounds : |
423 details_.restore_bounds); | 444 details_.restore_bounds); |
424 } | 445 } |
425 window()->SetBounds(snap_sizer_->target_bounds()); | 446 DCHECK(snap_sizer_); |
447 if (wm::CanResizeWindow(window()) && | |
448 !snap_sizer_->ShouldDockWindow() && | |
449 !snap_sizer_->target_bounds().IsEmpty()) { | |
450 window()->SetBounds(snap_sizer_->target_bounds()); | |
451 } | |
426 return; | 452 return; |
427 } | 453 } |
428 } | 454 } |
429 | 455 |
430 void WorkspaceWindowResizer::RevertDrag() { | 456 void WorkspaceWindowResizer::RevertDrag() { |
431 snap_phantom_window_controller_.reset(); | 457 snap_phantom_window_controller_.reset(); |
432 | 458 |
433 if (!did_move_or_resize_) | 459 if (!did_move_or_resize_) |
434 return; | 460 return; |
435 | 461 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
469 WorkspaceWindowResizer::WorkspaceWindowResizer( | 495 WorkspaceWindowResizer::WorkspaceWindowResizer( |
470 const Details& details, | 496 const Details& details, |
471 const std::vector<aura::Window*>& attached_windows) | 497 const std::vector<aura::Window*>& attached_windows) |
472 : details_(details), | 498 : details_(details), |
473 attached_windows_(attached_windows), | 499 attached_windows_(attached_windows), |
474 did_move_or_resize_(false), | 500 did_move_or_resize_(false), |
475 total_min_(0), | 501 total_min_(0), |
476 total_initial_size_(0), | 502 total_initial_size_(0), |
477 snap_type_(SNAP_NONE), | 503 snap_type_(SNAP_NONE), |
478 num_mouse_moves_since_bounds_change_(0), | 504 num_mouse_moves_since_bounds_change_(0), |
479 magnetism_window_(NULL) { | 505 magnetism_window_(NULL), |
506 destroyed_(NULL) { | |
480 DCHECK(details_.is_resizable); | 507 DCHECK(details_.is_resizable); |
481 | 508 |
482 Shell* shell = Shell::GetInstance(); | 509 Shell* shell = Shell::GetInstance(); |
483 shell->cursor_manager()->LockCursor(); | 510 shell->cursor_manager()->LockCursor(); |
484 | 511 |
485 // Only support attaching to the right/bottom. | 512 // Only support attaching to the right/bottom. |
486 DCHECK(attached_windows_.empty() || | 513 DCHECK(attached_windows_.empty() || |
487 (details.window_component == HTRIGHT || | 514 (details.window_component == HTRIGHT || |
488 details.window_component == HTBOTTOM)); | 515 details.window_component == HTBOTTOM)); |
489 | 516 |
490 // TODO: figure out how to deal with window going off the edge. | 517 // TODO: figure out how to deal with window going off the edge. |
491 | 518 |
492 // Calculate sizes so that we can maintain the ratios if we need to resize. | 519 // Calculate sizes so that we can maintain the ratios if we need to resize. |
493 int total_available = 0; | 520 int total_available = 0; |
494 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 521 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
495 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); | 522 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); |
496 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); | 523 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); |
497 initial_size_.push_back(initial_size); | 524 initial_size_.push_back(initial_size); |
498 // If current size is smaller than the min, use the current size as the min. | 525 // If current size is smaller than the min, use the current size as the min. |
499 // This way we don't snap on resize. | 526 // This way we don't snap on resize. |
500 int min_size = std::min(initial_size, | 527 int min_size = std::min(initial_size, |
501 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); | 528 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); |
502 total_min_ += min_size; | 529 total_min_ += min_size; |
503 total_initial_size_ += initial_size; | 530 total_initial_size_ += initial_size; |
504 total_available += std::max(min_size, initial_size) - min_size; | 531 total_available += std::max(min_size, initial_size) - min_size; |
505 } | 532 } |
533 snap_type_ = GetSnapType(details_.initial_location_in_parent); | |
506 } | 534 } |
507 | 535 |
508 gfx::Rect WorkspaceWindowResizer::GetFinalBounds( | 536 gfx::Rect WorkspaceWindowResizer::GetFinalBounds( |
509 const gfx::Rect& bounds) const { | 537 const gfx::Rect& bounds) const { |
510 if (snap_phantom_window_controller_.get() && | 538 if (snap_phantom_window_controller_.get() && |
511 snap_phantom_window_controller_->IsShowing()) { | 539 snap_phantom_window_controller_->IsShowing()) { |
512 return snap_phantom_window_controller_->bounds_in_screen(); | 540 return snap_phantom_window_controller_->bounds_in_screen(); |
513 } | 541 } |
514 return bounds; | 542 return bounds; |
515 } | 543 } |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
848 NOTREACHED(); | 876 NOTREACHED(); |
849 } | 877 } |
850 return 0; | 878 return 0; |
851 } | 879 } |
852 | 880 |
853 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 881 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
854 const gfx::Rect& bounds) { | 882 const gfx::Rect& bounds) { |
855 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 883 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) |
856 return; | 884 return; |
857 | 885 |
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_; | 886 SnapType last_type = snap_type_; |
867 snap_type_ = GetSnapType(location); | 887 snap_type_ = GetSnapType(location); |
868 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 888 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
869 snap_phantom_window_controller_.reset(); | 889 snap_phantom_window_controller_.reset(); |
890 if (snap_type_ == SNAP_NONE && snap_type_ != last_type) { | |
891 // Create and delete a SnapSizer to maintain docked state. | |
892 snap_sizer_.reset(new SnapSizer( | |
893 window(), | |
894 details_.initial_location_in_parent, | |
895 (last_type == SNAP_LEFT) ? | |
896 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE, | |
897 internal::SnapSizer::WORKSPACE_DRAG_INPUT)); | |
898 } | |
870 snap_sizer_.reset(); | 899 snap_sizer_.reset(); |
871 if (snap_type_ == SNAP_NONE) | 900 if (snap_type_ == SNAP_NONE) |
872 return; | 901 return; |
873 } | 902 } |
903 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? | |
904 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | |
905 | |
874 if (!snap_sizer_) { | 906 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(), | 907 snap_sizer_.reset(new SnapSizer(window(), |
878 location, | 908 location, |
879 edge, | 909 edge, |
880 internal::SnapSizer::OTHER_INPUT)); | 910 internal::SnapSizer::WORKSPACE_DRAG_INPUT)); |
881 } else { | 911 } else { |
882 snap_sizer_->Update(location); | 912 snap_sizer_->Update(location); |
883 } | 913 } |
914 | |
915 // Update phantom window when it is used for side-maximizing. | |
916 // In case of docking it will be called directly by the chained resizer. | |
917 if (!wm::CanSnapWindow(window()) && !SnapSizer::CanDockWindow(window(), edge)) | |
918 return; | |
919 | |
920 if (snap_sizer_->target_bounds().IsEmpty()) { | |
921 snap_phantom_window_controller_.reset(); | |
922 return; | |
923 } | |
884 if (!snap_phantom_window_controller_) { | 924 if (!snap_phantom_window_controller_) { |
885 snap_phantom_window_controller_.reset( | 925 snap_phantom_window_controller_.reset( |
886 new PhantomWindowController(window())); | 926 new PhantomWindowController(window())); |
887 } | 927 } |
888 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 928 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
889 window()->parent(), snap_sizer_->target_bounds())); | 929 window()->parent(), snap_sizer_->target_bounds())); |
890 } | 930 } |
891 | 931 |
892 void WorkspaceWindowResizer::RestackWindows() { | 932 void WorkspaceWindowResizer::RestackWindows() { |
893 if (attached_windows_.empty()) | 933 if (attached_windows_.empty()) |
(...skipping 19 matching lines...) Expand all Loading... | |
913 parent->StackChildAtTop(map.rbegin()->second); | 953 parent->StackChildAtTop(map.rbegin()->second); |
914 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 954 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
915 i != map.rend(); ) { | 955 i != map.rend(); ) { |
916 aura::Window* window = i->second; | 956 aura::Window* window = i->second; |
917 ++i; | 957 ++i; |
918 if (i != map.rend()) | 958 if (i != map.rend()) |
919 parent->StackChildBelow(i->second, window); | 959 parent->StackChildBelow(i->second, window); |
920 } | 960 } |
921 } | 961 } |
922 | 962 |
923 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 963 SnapType WorkspaceWindowResizer::GetSnapType( |
924 const gfx::Point& location) const { | 964 const gfx::Point& location) const { |
925 // TODO: this likely only wants total display area, not the area of a single | 965 // TODO: this likely only wants total display area, not the area of a single |
926 // display. | 966 // display. |
927 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); | 967 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); |
928 if (location.x() <= area.x()) | 968 if (location.x() <= area.x()) |
929 return SNAP_LEFT_EDGE; | 969 return SNAP_LEFT; |
930 if (location.x() >= area.right() - 1) | 970 if (location.x() >= area.right() - 1) |
931 return SNAP_RIGHT_EDGE; | 971 return SNAP_RIGHT; |
932 return SNAP_NONE; | 972 return SNAP_NONE; |
933 } | 973 } |
934 | 974 |
935 } // namespace internal | 975 } // namespace internal |
936 } // namespace ash | 976 } // namespace ash |
OLD | NEW |