| 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> |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 // classes using reparenting during drag operations it becomes challenging to | 60 // classes using reparenting during drag operations it becomes challenging to |
| 61 // implement proper transition from one resizer to another during or at the | 61 // implement proper transition from one resizer to another during or at the |
| 62 // end of the drag. This also causes http://crbug.com/247085. | 62 // end of the drag. This also causes http://crbug.com/247085. |
| 63 // It seems the only thing the panel or dock resizer needs to do is notify the | 63 // It seems the only thing the panel or dock resizer needs to do is notify the |
| 64 // layout manager when a docked window is being dragged. We should have a | 64 // layout manager when a docked window is being dragged. We should have a |
| 65 // better way of doing this, perhaps by having a way of observing drags or | 65 // better way of doing this, perhaps by having a way of observing drags or |
| 66 // having a generic drag window wrapper which informs a layout manager that a | 66 // having a generic drag window wrapper which informs a layout manager that a |
| 67 // drag has started or stopped. | 67 // drag has started or stopped. |
| 68 // It may be possible to refactor and eliminate chaining. | 68 // It may be possible to refactor and eliminate chaining. |
| 69 WindowResizer* window_resizer = NULL; | 69 WindowResizer* window_resizer = NULL; |
| 70 |
| 71 if (!window_state->IsNormalShowState()) { |
| 72 if (window->parent() && |
| 73 (window->parent()->id() == internal::kShellWindowId_DefaultContainer || |
| 74 window->parent()->id() == internal::kShellWindowId_DockedContainer || |
| 75 window->parent()->id() == internal::kShellWindowId_PanelContainer)) { |
| 76 // Allow dragging maximized windows only when dragged by a tab. |
| 77 if (!window_component != HTCAPTION || !window_state->is_dragged()) |
| 78 return scoped_ptr<WindowResizer>(); |
| 79 } else { |
| 80 return scoped_ptr<WindowResizer>(); |
| 81 } |
| 82 } |
| 83 |
| 84 scoped_ptr<DragDetails> details(new DragDetails( |
| 85 window, point_in_parent, window_component, source)); |
| 86 if (!details->is_resizable) |
| 87 return scoped_ptr<WindowResizer>(); |
| 88 window_state->set_drag_details(details.release()); |
| 89 |
| 70 if (window->parent() && | 90 if (window->parent() && |
| 71 (window->parent()->id() == internal::kShellWindowId_DefaultContainer || | 91 (window->parent()->id() == internal::kShellWindowId_DefaultContainer || |
| 72 window->parent()->id() == internal::kShellWindowId_DockedContainer || | 92 window->parent()->id() == internal::kShellWindowId_DockedContainer || |
| 73 window->parent()->id() == internal::kShellWindowId_PanelContainer)) { | 93 window->parent()->id() == internal::kShellWindowId_PanelContainer)) { |
| 74 // Allow dragging maximized windows if it's not tracked by workspace. This | |
| 75 // is set by tab dragging code. | |
| 76 if (!window_state->IsNormalShowState() && | |
| 77 (window_component != HTCAPTION || | |
| 78 !window_state->is_dragged())) { | |
| 79 return scoped_ptr<WindowResizer>(); | |
| 80 } | |
| 81 window_resizer = internal::WorkspaceWindowResizer::Create( | 94 window_resizer = internal::WorkspaceWindowResizer::Create( |
| 82 window, | 95 window_state, |
| 83 point_in_parent, | |
| 84 window_component, | |
| 85 source, | |
| 86 std::vector<aura::Window*>()); | 96 std::vector<aura::Window*>()); |
| 87 } else if (window_state->IsNormalShowState()) { | 97 } else { |
| 88 window_resizer = DefaultWindowResizer::Create( | 98 window_resizer = DefaultWindowResizer::Create(window_state); |
| 89 window, point_in_parent, window_component, source); | |
| 90 } | 99 } |
| 91 if (window_resizer) { | 100 if (window_resizer) { |
| 92 window_resizer = internal::DragWindowResizer::Create( | 101 window_resizer = internal::DragWindowResizer::Create(window_resizer, |
| 93 window_resizer, window, point_in_parent, window_component, source); | 102 window_state); |
| 94 } | 103 } |
| 95 if (window_resizer && window->type() == ui::wm::WINDOW_TYPE_PANEL) { | 104 if (window_resizer && window->type() == ui::wm::WINDOW_TYPE_PANEL) |
| 96 window_resizer = PanelWindowResizer::Create( | 105 window_resizer = PanelWindowResizer::Create(window_resizer, window_state); |
| 97 window_resizer, window, point_in_parent, window_component, source); | |
| 98 } | |
| 99 if (switches::UseDockedWindows() && | 106 if (switches::UseDockedWindows() && |
| 100 window_resizer && window->parent() && | 107 window_resizer && window->parent() && |
| 101 !views::corewm::GetTransientParent(window) && | 108 !views::corewm::GetTransientParent(window) && |
| 102 (window->parent()->id() == internal::kShellWindowId_DefaultContainer || | 109 (window->parent()->id() == internal::kShellWindowId_DefaultContainer || |
| 103 window->parent()->id() == internal::kShellWindowId_DockedContainer || | 110 window->parent()->id() == internal::kShellWindowId_DockedContainer || |
| 104 window->parent()->id() == internal::kShellWindowId_PanelContainer)) { | 111 window->parent()->id() == internal::kShellWindowId_PanelContainer)) { |
| 105 window_resizer = internal::DockedWindowResizer::Create( | 112 window_resizer = internal::DockedWindowResizer::Create(window_resizer, |
| 106 window_resizer, window, point_in_parent, window_component, source); | 113 window_state); |
| 107 } | 114 } |
| 108 window_state->set_window_resizer_(window_resizer); | 115 window_state->drag_details()->window_resizer = window_resizer; |
| 109 return make_scoped_ptr<WindowResizer>(window_resizer); | 116 return make_scoped_ptr<WindowResizer>(window_resizer); |
| 110 } | 117 } |
| 111 | 118 |
| 112 namespace internal { | 119 namespace internal { |
| 113 | 120 |
| 114 namespace { | 121 namespace { |
| 115 | 122 |
| 116 // Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset | 123 // Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset |
| 117 // when resizing a window using touchscreen. | 124 // when resizing a window using touchscreen. |
| 118 const int kScreenEdgeInsetForTouchResize = 32; | 125 const int kScreenEdgeInsetForTouchResize = 32; |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 if (did_lock_cursor_) { | 355 if (did_lock_cursor_) { |
| 349 Shell* shell = Shell::GetInstance(); | 356 Shell* shell = Shell::GetInstance(); |
| 350 shell->cursor_manager()->UnlockCursor(); | 357 shell->cursor_manager()->UnlockCursor(); |
| 351 } | 358 } |
| 352 if (instance_ == this) | 359 if (instance_ == this) |
| 353 instance_ = NULL; | 360 instance_ = NULL; |
| 354 } | 361 } |
| 355 | 362 |
| 356 // static | 363 // static |
| 357 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( | 364 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
| 358 aura::Window* window, | 365 wm::WindowState* window_state, |
| 359 const gfx::Point& location_in_parent, | |
| 360 int window_component, | |
| 361 aura::client::WindowMoveSource source, | |
| 362 const std::vector<aura::Window*>& attached_windows) { | 366 const std::vector<aura::Window*>& attached_windows) { |
| 363 Details details(window, location_in_parent, window_component, source); | 367 return new WorkspaceWindowResizer(window_state, attached_windows); |
| 364 return details.is_resizable ? | |
| 365 new WorkspaceWindowResizer(details, attached_windows) : NULL; | |
| 366 } | 368 } |
| 367 | 369 |
| 368 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, | 370 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, |
| 369 int event_flags) { | 371 int event_flags) { |
| 370 last_mouse_location_ = location_in_parent; | 372 last_mouse_location_ = location_in_parent; |
| 371 | 373 |
| 372 int sticky_size; | 374 int sticky_size; |
| 373 if (event_flags & ui::EF_CONTROL_DOWN) { | 375 if (event_flags & ui::EF_CONTROL_DOWN) { |
| 374 sticky_size = 0; | 376 sticky_size = 0; |
| 375 } else if (CommandLine::ForCurrentProcess()->HasSwitch( | 377 } else if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 376 switches::kAshEnableStickyEdges)) { | 378 switches::kAshEnableStickyEdges)) { |
| 377 sticky_size = kStickyDistancePixels; | 379 sticky_size = kStickyDistancePixels; |
| 378 } else if ((details_.bounds_change & kBoundsChange_Resizes) && | 380 } else if ((details().bounds_change & kBoundsChange_Resizes) && |
| 379 details_.source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 381 details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
| 380 sticky_size = kScreenEdgeInsetForTouchResize; | 382 sticky_size = kScreenEdgeInsetForTouchResize; |
| 381 } else { | 383 } else { |
| 382 sticky_size = kScreenEdgeInset; | 384 sticky_size = kScreenEdgeInset; |
| 383 } | 385 } |
| 384 // |bounds| is in |window()->parent()|'s coordinates. | 386 // |bounds| is in |GetTarget()->parent()|'s coordinates. |
| 385 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); | 387 gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); |
| 386 if (window_state()->IsNormalShowState()) | 388 if (window_state()->IsNormalShowState()) |
| 387 AdjustBoundsForMainWindow(sticky_size, &bounds); | 389 AdjustBoundsForMainWindow(sticky_size, &bounds); |
| 388 | 390 |
| 389 if (bounds != window()->bounds()) { | 391 if (bounds != GetTarget()->bounds()) { |
| 390 if (!did_move_or_resize_) { | 392 if (!did_move_or_resize_) { |
| 391 if (!details_.restore_bounds.IsEmpty()) | 393 if (!details().restore_bounds.IsEmpty()) |
| 392 window_state()->ClearRestoreBounds(); | 394 window_state()->ClearRestoreBounds(); |
| 393 RestackWindows(); | 395 RestackWindows(); |
| 394 } | 396 } |
| 395 did_move_or_resize_ = true; | 397 did_move_or_resize_ = true; |
| 396 } | 398 } |
| 397 | 399 |
| 398 gfx::Point location_in_screen = location_in_parent; | 400 gfx::Point location_in_screen = location_in_parent; |
| 399 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); | 401 wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen); |
| 400 | 402 |
| 401 aura::Window* root = NULL; | 403 aura::Window* root = NULL; |
| 402 gfx::Display display = | 404 gfx::Display display = |
| 403 ScreenAsh::FindDisplayContainingPoint(location_in_screen); | 405 ScreenAsh::FindDisplayContainingPoint(location_in_screen); |
| 404 // Track the last screen that the pointer was on to keep the snap phantom | 406 // Track the last screen that the pointer was on to keep the snap phantom |
| 405 // window there. | 407 // window there. |
| 406 if (display.is_valid()) { | 408 if (display.is_valid()) { |
| 407 root = Shell::GetInstance()->display_controller()-> | 409 root = Shell::GetInstance()->display_controller()-> |
| 408 GetRootWindowForDisplayId(display.id()); | 410 GetRootWindowForDisplayId(display.id()); |
| 409 } | 411 } |
| 410 if (!attached_windows_.empty()) | 412 if (!attached_windows_.empty()) |
| 411 LayoutAttachedWindows(&bounds); | 413 LayoutAttachedWindows(&bounds); |
| 412 if (bounds != window()->bounds()) { | 414 if (bounds != GetTarget()->bounds()) { |
| 413 // SetBounds needs to be called to update the layout which affects where the | 415 // SetBounds needs to be called to update the layout which affects where the |
| 414 // phantom window is drawn. Keep track if the window was destroyed during | 416 // phantom window is drawn. Keep track if the window was destroyed during |
| 415 // the drag and quit early if so. | 417 // the drag and quit early if so. |
| 416 base::WeakPtr<WorkspaceWindowResizer> resizer( | 418 base::WeakPtr<WorkspaceWindowResizer> resizer( |
| 417 weak_ptr_factory_.GetWeakPtr()); | 419 weak_ptr_factory_.GetWeakPtr()); |
| 418 window()->SetBounds(bounds); | 420 GetTarget()->SetBounds(bounds); |
| 419 if (!resizer) | 421 if (!resizer) |
| 420 return; | 422 return; |
| 421 } | 423 } |
| 422 const bool in_original_root = !root || root == window()->GetRootWindow(); | 424 const bool in_original_root = !root || root == GetTarget()->GetRootWindow(); |
| 423 // Hide a phantom window for snapping if the cursor is in another root window. | 425 // Hide a phantom window for snapping if the cursor is in another root window. |
| 424 if (in_original_root) { | 426 if (in_original_root) { |
| 425 UpdateSnapPhantomWindow(location_in_parent, bounds); | 427 UpdateSnapPhantomWindow(location_in_parent, bounds); |
| 426 } else { | 428 } else { |
| 427 snap_type_ = SNAP_NONE; | 429 snap_type_ = SNAP_NONE; |
| 428 snap_phantom_window_controller_.reset(); | 430 snap_phantom_window_controller_.reset(); |
| 429 snap_sizer_.reset(); | 431 snap_sizer_.reset(); |
| 430 SetDraggedWindowDocked(false); | 432 SetDraggedWindowDocked(false); |
| 431 } | 433 } |
| 432 } | 434 } |
| 433 | 435 |
| 434 void WorkspaceWindowResizer::CompleteDrag() { | 436 void WorkspaceWindowResizer::CompleteDrag() { |
| 435 window_state()->set_bounds_changed_by_user(true); | 437 window_state()->set_bounds_changed_by_user(true); |
| 436 snap_phantom_window_controller_.reset(); | 438 snap_phantom_window_controller_.reset(); |
| 437 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 439 if (!did_move_or_resize_ || details().window_component != HTCAPTION) |
| 438 return; | 440 return; |
| 439 | 441 |
| 440 bool snapped = false; | 442 bool snapped = false; |
| 441 // When the window is not in the normal show state, we do not snap the window. | 443 // When the window is not in the normal show state, we do not snap the window. |
| 442 // This happens when the user minimizes or maximizes the window by keyboard | 444 // This happens when the user minimizes or maximizes the window by keyboard |
| 443 // shortcut while dragging it. If the window is the result of dragging a tab | 445 // shortcut while dragging it. If the window is the result of dragging a tab |
| 444 // out of a maximized window, it's already in the normal show state when this | 446 // out of a maximized window, it's already in the normal show state when this |
| 445 // is called, so it does not matter. | 447 // is called, so it does not matter. |
| 446 if (window_state()->IsNormalShowState() && | 448 if (window_state()->IsNormalShowState() && |
| 447 (window()->type() != ui::wm::WINDOW_TYPE_PANEL || | 449 (GetTarget()->type() != ui::wm::WINDOW_TYPE_PANEL || |
| 448 !window_state()->panel_attached() || | 450 !window_state()->panel_attached() || |
| 449 dock_layout_->is_dragged_window_docked()) && | 451 dock_layout_->is_dragged_window_docked()) && |
| 450 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { | 452 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { |
| 451 if (!window_state()->HasRestoreBounds()) { | 453 if (!window_state()->HasRestoreBounds()) { |
| 452 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( | 454 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( |
| 453 window()->parent(), details_.initial_bounds_in_parent); | 455 GetTarget()->parent(), details().initial_bounds_in_parent); |
| 454 window_state()->SetRestoreBoundsInScreen( | 456 window_state()->SetRestoreBoundsInScreen( |
| 455 details_.restore_bounds.IsEmpty() ? | 457 details().restore_bounds.IsEmpty() ? |
| 456 initial_bounds : | 458 initial_bounds : |
| 457 details_.restore_bounds); | 459 details().restore_bounds); |
| 458 } | 460 } |
| 459 DCHECK(snap_sizer_); | 461 DCHECK(snap_sizer_); |
| 460 if (window_state()->CanResize() && | 462 if (window_state()->CanResize() && |
| 461 !dock_layout_->is_dragged_window_docked()) { | 463 !dock_layout_->is_dragged_window_docked()) { |
| 462 snap_sizer_->SnapWindowToTargetBounds(); | 464 snap_sizer_->SnapWindowToTargetBounds(); |
| 463 snapped = true; | 465 snapped = true; |
| 464 } | 466 } |
| 465 } | 467 } |
| 466 if (window_state()->IsSnapped() && !snapped) | 468 if (window_state()->IsSnapped() && !snapped) |
| 467 window_state()->Restore(); | 469 window_state()->Restore(); |
| 468 } | 470 } |
| 469 | 471 |
| 470 void WorkspaceWindowResizer::RevertDrag() { | 472 void WorkspaceWindowResizer::RevertDrag() { |
| 471 window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); | 473 window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); |
| 472 snap_phantom_window_controller_.reset(); | 474 snap_phantom_window_controller_.reset(); |
| 473 | 475 |
| 474 if (!did_move_or_resize_) | 476 if (!did_move_or_resize_) |
| 475 return; | 477 return; |
| 476 | 478 |
| 477 window()->SetBounds(details_.initial_bounds_in_parent); | 479 GetTarget()->SetBounds(details().initial_bounds_in_parent); |
| 478 if (!details_.restore_bounds.IsEmpty()) { | 480 if (!details().restore_bounds.IsEmpty()) { |
| 479 window_state()->SetRestoreBoundsInScreen(details_.restore_bounds); | 481 window_state()->SetRestoreBoundsInScreen(details().restore_bounds); |
| 480 } | 482 } |
| 481 | 483 |
| 482 if (details_.window_component == HTRIGHT) { | 484 if (details().window_component == HTRIGHT) { |
| 483 int last_x = details_.initial_bounds_in_parent.right(); | 485 int last_x = details().initial_bounds_in_parent.right(); |
| 484 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 486 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 485 gfx::Rect bounds(attached_windows_[i]->bounds()); | 487 gfx::Rect bounds(attached_windows_[i]->bounds()); |
| 486 bounds.set_x(last_x); | 488 bounds.set_x(last_x); |
| 487 bounds.set_width(initial_size_[i]); | 489 bounds.set_width(initial_size_[i]); |
| 488 attached_windows_[i]->SetBounds(bounds); | 490 attached_windows_[i]->SetBounds(bounds); |
| 489 last_x = attached_windows_[i]->bounds().right(); | 491 last_x = attached_windows_[i]->bounds().right(); |
| 490 } | 492 } |
| 491 } else { | 493 } else { |
| 492 int last_y = details_.initial_bounds_in_parent.bottom(); | 494 int last_y = details().initial_bounds_in_parent.bottom(); |
| 493 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 495 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 494 gfx::Rect bounds(attached_windows_[i]->bounds()); | 496 gfx::Rect bounds(attached_windows_[i]->bounds()); |
| 495 bounds.set_y(last_y); | 497 bounds.set_y(last_y); |
| 496 bounds.set_height(initial_size_[i]); | 498 bounds.set_height(initial_size_[i]); |
| 497 attached_windows_[i]->SetBounds(bounds); | 499 attached_windows_[i]->SetBounds(bounds); |
| 498 last_y = attached_windows_[i]->bounds().bottom(); | 500 last_y = attached_windows_[i]->bounds().bottom(); |
| 499 } | 501 } |
| 500 } | 502 } |
| 501 } | 503 } |
| 502 | 504 |
| 503 aura::Window* WorkspaceWindowResizer::GetTarget() { | |
| 504 return details_.window; | |
| 505 } | |
| 506 | |
| 507 const gfx::Point& WorkspaceWindowResizer::GetInitialLocation() const { | |
| 508 return details_.initial_location_in_parent; | |
| 509 } | |
| 510 | |
| 511 WorkspaceWindowResizer::WorkspaceWindowResizer( | 505 WorkspaceWindowResizer::WorkspaceWindowResizer( |
| 512 const Details& details, | 506 wm::WindowState* window_state, |
| 513 const std::vector<aura::Window*>& attached_windows) | 507 const std::vector<aura::Window*>& attached_windows) |
| 514 : details_(details), | 508 : WindowResizer(window_state), |
| 515 attached_windows_(attached_windows), | 509 attached_windows_(attached_windows), |
| 516 did_lock_cursor_(false), | 510 did_lock_cursor_(false), |
| 517 did_move_or_resize_(false), | 511 did_move_or_resize_(false), |
| 518 initial_bounds_changed_by_user_( | 512 initial_bounds_changed_by_user_(window_state_->bounds_changed_by_user()), |
| 519 details.window_state->bounds_changed_by_user()), | |
| 520 total_min_(0), | 513 total_min_(0), |
| 521 total_initial_size_(0), | 514 total_initial_size_(0), |
| 522 snap_type_(SNAP_NONE), | 515 snap_type_(SNAP_NONE), |
| 523 num_mouse_moves_since_bounds_change_(0), | 516 num_mouse_moves_since_bounds_change_(0), |
| 524 magnetism_window_(NULL), | 517 magnetism_window_(NULL), |
| 525 weak_ptr_factory_(this) { | 518 weak_ptr_factory_(this) { |
| 526 DCHECK(details_.is_resizable); | 519 DCHECK(details().is_resizable); |
| 527 | 520 |
| 528 // A mousemove should still show the cursor even if the window is | 521 // A mousemove should still show the cursor even if the window is |
| 529 // being moved or resized with touch, so do not lock the cursor. | 522 // being moved or resized with touch, so do not lock the cursor. |
| 530 if (details.source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 523 if (details().source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
| 531 Shell* shell = Shell::GetInstance(); | 524 Shell* shell = Shell::GetInstance(); |
| 532 shell->cursor_manager()->LockCursor(); | 525 shell->cursor_manager()->LockCursor(); |
| 533 did_lock_cursor_ = true; | 526 did_lock_cursor_ = true; |
| 534 } | 527 } |
| 535 | 528 |
| 536 aura::Window* dock_container = Shell::GetContainer( | 529 aura::Window* dock_container = Shell::GetContainer( |
| 537 window()->GetRootWindow(), kShellWindowId_DockedContainer); | 530 GetTarget()->GetRootWindow(), kShellWindowId_DockedContainer); |
| 538 dock_layout_ = static_cast<DockedWindowLayoutManager*>( | 531 dock_layout_ = static_cast<DockedWindowLayoutManager*>( |
| 539 dock_container->layout_manager()); | 532 dock_container->layout_manager()); |
| 540 | 533 |
| 541 // Only support attaching to the right/bottom. | 534 // Only support attaching to the right/bottom. |
| 542 DCHECK(attached_windows_.empty() || | 535 DCHECK(attached_windows_.empty() || |
| 543 (details.window_component == HTRIGHT || | 536 (details().window_component == HTRIGHT || |
| 544 details.window_component == HTBOTTOM)); | 537 details().window_component == HTBOTTOM)); |
| 545 | 538 |
| 546 // TODO: figure out how to deal with window going off the edge. | 539 // TODO: figure out how to deal with window going off the edge. |
| 547 | 540 |
| 548 // Calculate sizes so that we can maintain the ratios if we need to resize. | 541 // Calculate sizes so that we can maintain the ratios if we need to resize. |
| 549 int total_available = 0; | 542 int total_available = 0; |
| 550 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 543 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 551 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); | 544 gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); |
| 552 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); | 545 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); |
| 553 initial_size_.push_back(initial_size); | 546 initial_size_.push_back(initial_size); |
| 554 // If current size is smaller than the min, use the current size as the min. | 547 // If current size is smaller than the min, use the current size as the min. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 566 const gfx::Rect& bounds) const { | 559 const gfx::Rect& bounds) const { |
| 567 if (snap_phantom_window_controller_.get() && | 560 if (snap_phantom_window_controller_.get() && |
| 568 snap_phantom_window_controller_->IsShowing()) { | 561 snap_phantom_window_controller_->IsShowing()) { |
| 569 return snap_phantom_window_controller_->bounds_in_screen(); | 562 return snap_phantom_window_controller_->bounds_in_screen(); |
| 570 } | 563 } |
| 571 return bounds; | 564 return bounds; |
| 572 } | 565 } |
| 573 | 566 |
| 574 void WorkspaceWindowResizer::LayoutAttachedWindows( | 567 void WorkspaceWindowResizer::LayoutAttachedWindows( |
| 575 gfx::Rect* bounds) { | 568 gfx::Rect* bounds) { |
| 576 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); | 569 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(GetTarget())); |
| 577 int initial_size = PrimaryAxisSize(details_.initial_bounds_in_parent.size()); | 570 int initial_size = PrimaryAxisSize(details().initial_bounds_in_parent.size()); |
| 578 int current_size = PrimaryAxisSize(bounds->size()); | 571 int current_size = PrimaryAxisSize(bounds->size()); |
| 579 int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); | 572 int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); |
| 580 int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); | 573 int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); |
| 581 | 574 |
| 582 int delta = current_size - initial_size; | 575 int delta = current_size - initial_size; |
| 583 int available_size = end - start; | 576 int available_size = end - start; |
| 584 std::vector<int> sizes; | 577 std::vector<int> sizes; |
| 585 int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); | 578 int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); |
| 586 | 579 |
| 587 // leftovers > 0 means that the attached windows can't grow to compensate for | 580 // leftovers > 0 means that the attached windows can't grow to compensate for |
| 588 // the shrinkage of the main window. This line causes the attached windows to | 581 // the shrinkage of the main window. This line causes the attached windows to |
| 589 // be moved so they are still flush against the main window, rather than the | 582 // be moved so they are still flush against the main window, rather than the |
| 590 // main window being prevented from shrinking. | 583 // main window being prevented from shrinking. |
| 591 leftovers = std::min(0, leftovers); | 584 leftovers = std::min(0, leftovers); |
| 592 // Reallocate any leftover pixels back into the main window. This is | 585 // Reallocate any leftover pixels back into the main window. This is |
| 593 // necessary when, for example, the main window shrinks, but none of the | 586 // necessary when, for example, the main window shrinks, but none of the |
| 594 // attached windows can grow without exceeding their max size constraints. | 587 // attached windows can grow without exceeding their max size constraints. |
| 595 // Adding the pixels back to the main window effectively prevents the main | 588 // Adding the pixels back to the main window effectively prevents the main |
| 596 // window from resizing too far. | 589 // window from resizing too far. |
| 597 if (details_.window_component == HTRIGHT) | 590 if (details().window_component == HTRIGHT) |
| 598 bounds->set_width(bounds->width() + leftovers); | 591 bounds->set_width(bounds->width() + leftovers); |
| 599 else | 592 else |
| 600 bounds->set_height(bounds->height() + leftovers); | 593 bounds->set_height(bounds->height() + leftovers); |
| 601 | 594 |
| 602 DCHECK_EQ(attached_windows_.size(), sizes.size()); | 595 DCHECK_EQ(attached_windows_.size(), sizes.size()); |
| 603 int last = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); | 596 int last = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); |
| 604 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 597 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
| 605 gfx::Rect attached_bounds(attached_windows_[i]->bounds()); | 598 gfx::Rect attached_bounds(attached_windows_[i]->bounds()); |
| 606 if (details_.window_component == HTRIGHT) { | 599 if (details().window_component == HTRIGHT) { |
| 607 attached_bounds.set_x(last); | 600 attached_bounds.set_x(last); |
| 608 attached_bounds.set_width(sizes[i]); | 601 attached_bounds.set_width(sizes[i]); |
| 609 } else { | 602 } else { |
| 610 attached_bounds.set_y(last); | 603 attached_bounds.set_y(last); |
| 611 attached_bounds.set_height(sizes[i]); | 604 attached_bounds.set_height(sizes[i]); |
| 612 } | 605 } |
| 613 attached_windows_[i]->SetBounds(attached_bounds); | 606 attached_windows_[i]->SetBounds(attached_bounds); |
| 614 last += sizes[i]; | 607 last += sizes[i]; |
| 615 } | 608 } |
| 616 } | 609 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 int min = PrimaryAxisSize(delegate->GetMinimumSize()); | 699 int min = PrimaryAxisSize(delegate->GetMinimumSize()); |
| 707 int max = PrimaryAxisSize(delegate->GetMaximumSize()); | 700 int max = PrimaryAxisSize(delegate->GetMaximumSize()); |
| 708 | 701 |
| 709 sizes->push_back(WindowSize(initial_size, min, max)); | 702 sizes->push_back(WindowSize(initial_size, min, max)); |
| 710 } | 703 } |
| 711 } | 704 } |
| 712 | 705 |
| 713 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { | 706 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { |
| 714 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { | 707 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { |
| 715 gfx::Point point = OriginForMagneticAttach( | 708 gfx::Point point = OriginForMagneticAttach( |
| 716 ScreenAsh::ConvertRectToScreen(window()->parent(), *bounds), | 709 ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), *bounds), |
| 717 magnetism_window_->GetBoundsInScreen(), | 710 magnetism_window_->GetBoundsInScreen(), |
| 718 magnetism_edge_); | 711 magnetism_edge_); |
| 719 aura::client::GetScreenPositionClient(window()->GetRootWindow())-> | 712 aura::client::GetScreenPositionClient(GetTarget()->GetRootWindow())-> |
| 720 ConvertPointFromScreen(window()->parent(), &point); | 713 ConvertPointFromScreen(GetTarget()->parent(), &point); |
| 721 bounds->set_origin(point); | 714 bounds->set_origin(point); |
| 722 } | 715 } |
| 723 } | 716 } |
| 724 | 717 |
| 725 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( | 718 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( |
| 726 gfx::Rect* bounds) { | 719 gfx::Rect* bounds) { |
| 727 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); | 720 const uint32 edges = WindowComponentToMagneticEdge( |
| 721 details().window_component); |
| 728 if (UpdateMagnetismWindow(*bounds, edges)) { | 722 if (UpdateMagnetismWindow(*bounds, edges)) { |
| 729 *bounds = ScreenAsh::ConvertRectFromScreen( | 723 *bounds = ScreenAsh::ConvertRectFromScreen( |
| 730 window()->parent(), | 724 GetTarget()->parent(), |
| 731 BoundsForMagneticResizeAttach( | 725 BoundsForMagneticResizeAttach( |
| 732 ScreenAsh::ConvertRectToScreen(window()->parent(), *bounds), | 726 ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), *bounds), |
| 733 magnetism_window_->GetBoundsInScreen(), | 727 magnetism_window_->GetBoundsInScreen(), |
| 734 magnetism_edge_)); | 728 magnetism_edge_)); |
| 735 } | 729 } |
| 736 } | 730 } |
| 737 | 731 |
| 738 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, | 732 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, |
| 739 uint32 edges) { | 733 uint32 edges) { |
| 740 // |bounds| are in coordinates of original window's parent. | 734 // |bounds| are in coordinates of original window's parent. |
| 741 gfx::Rect bounds_in_screen = | 735 gfx::Rect bounds_in_screen = |
| 742 ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); | 736 ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), bounds); |
| 743 MagnetismMatcher matcher(bounds_in_screen, edges); | 737 MagnetismMatcher matcher(bounds_in_screen, edges); |
| 744 | 738 |
| 745 // If we snapped to a window then check it first. That way we don't bounce | 739 // If we snapped to a window then check it first. That way we don't bounce |
| 746 // around when close to multiple edges. | 740 // around when close to multiple edges. |
| 747 if (magnetism_window_) { | 741 if (magnetism_window_) { |
| 748 if (window_tracker_.Contains(magnetism_window_) && | 742 if (window_tracker_.Contains(magnetism_window_) && |
| 749 matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), | 743 matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), |
| 750 &magnetism_edge_)) { | 744 &magnetism_edge_)) { |
| 751 return true; | 745 return true; |
| 752 } | 746 } |
| 753 window_tracker_.Remove(magnetism_window_); | 747 window_tracker_.Remove(magnetism_window_); |
| 754 magnetism_window_ = NULL; | 748 magnetism_window_ = NULL; |
| 755 } | 749 } |
| 756 | 750 |
| 757 // Avoid magnetically snapping windows that are not resizable. | 751 // Avoid magnetically snapping windows that are not resizable. |
| 758 // TODO(oshima): change this to window.type() == TYPE_NORMAL. | 752 // TODO(oshima): change this to window.type() == TYPE_NORMAL. |
| 759 if (!window_state()->CanResize()) | 753 if (!window_state()->CanResize()) |
| 760 return false; | 754 return false; |
| 761 | 755 |
| 762 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 756 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| 763 for (aura::Window::Windows::iterator iter = root_windows.begin(); | 757 for (aura::Window::Windows::iterator iter = root_windows.begin(); |
| 764 iter != root_windows.end(); ++iter) { | 758 iter != root_windows.end(); ++iter) { |
| 765 const aura::Window* root_window = *iter; | 759 const aura::Window* root_window = *iter; |
| 766 // Test all children from the desktop in each root window. | 760 // Test all children from the desktop in each root window. |
| 767 const aura::Window::Windows& children = Shell::GetContainer( | 761 const aura::Window::Windows& children = Shell::GetContainer( |
| 768 root_window, kShellWindowId_DefaultContainer)->children(); | 762 root_window, kShellWindowId_DefaultContainer)->children(); |
| 769 for (aura::Window::Windows::const_reverse_iterator i = children.rbegin(); | 763 for (aura::Window::Windows::const_reverse_iterator i = children.rbegin(); |
| 770 i != children.rend() && !matcher.AreEdgesObscured(); ++i) { | 764 i != children.rend() && !matcher.AreEdgesObscured(); ++i) { |
| 771 wm::WindowState* other_state = wm::GetWindowState(*i); | 765 wm::WindowState* other_state = wm::GetWindowState(*i); |
| 772 if (other_state->window() == window() || | 766 if (other_state->window() == GetTarget() || |
| 773 !other_state->window()->IsVisible() || | 767 !other_state->window()->IsVisible() || |
| 774 !other_state->IsNormalShowState() || | 768 !other_state->IsNormalShowState() || |
| 775 !other_state->CanResize()) { | 769 !other_state->CanResize()) { |
| 776 continue; | 770 continue; |
| 777 } | 771 } |
| 778 if (matcher.ShouldAttach( | 772 if (matcher.ShouldAttach( |
| 779 other_state->window()->GetBoundsInScreen(), &magnetism_edge_)) { | 773 other_state->window()->GetBoundsInScreen(), &magnetism_edge_)) { |
| 780 magnetism_window_ = other_state->window(); | 774 magnetism_window_ = other_state->window(); |
| 781 window_tracker_.Add(magnetism_window_); | 775 window_tracker_.Add(magnetism_window_); |
| 782 return true; | 776 return true; |
| 783 } | 777 } |
| 784 } | 778 } |
| 785 } | 779 } |
| 786 return false; | 780 return false; |
| 787 } | 781 } |
| 788 | 782 |
| 789 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( | 783 void WorkspaceWindowResizer::AdjustBoundsForMainWindow( |
| 790 int sticky_size, | 784 int sticky_size, |
| 791 gfx::Rect* bounds) { | 785 gfx::Rect* bounds) { |
| 792 gfx::Point last_mouse_location_in_screen = last_mouse_location_; | 786 gfx::Point last_mouse_location_in_screen = last_mouse_location_; |
| 793 wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); | 787 wm::ConvertPointToScreen(GetTarget()->parent(), |
| 788 &last_mouse_location_in_screen); |
| 794 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( | 789 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( |
| 795 last_mouse_location_in_screen); | 790 last_mouse_location_in_screen); |
| 796 gfx::Rect work_area = | 791 gfx::Rect work_area = |
| 797 ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area()); | 792 ScreenAsh::ConvertRectFromScreen(GetTarget()->parent(), |
| 798 if (details_.window_component == HTCAPTION) { | 793 display.work_area()); |
| 794 if (details().window_component == HTCAPTION) { |
| 799 // Adjust the bounds to the work area where the mouse cursor is located. | 795 // Adjust the bounds to the work area where the mouse cursor is located. |
| 800 // Always keep kMinOnscreenHeight or the window height (whichever is less) | 796 // Always keep kMinOnscreenHeight or the window height (whichever is less) |
| 801 // on the bottom. | 797 // on the bottom. |
| 802 int max_y = work_area.bottom() - std::min(kMinOnscreenHeight, | 798 int max_y = work_area.bottom() - std::min(kMinOnscreenHeight, |
| 803 bounds->height()); | 799 bounds->height()); |
| 804 if (bounds->y() > max_y) { | 800 if (bounds->y() > max_y) { |
| 805 bounds->set_y(max_y); | 801 bounds->set_y(max_y); |
| 806 } else if (bounds->y() <= work_area.y()) { | 802 } else if (bounds->y() <= work_area.y()) { |
| 807 // Don't allow dragging above the top of the display until the mouse | 803 // Don't allow dragging above the top of the display until the mouse |
| 808 // cursor reaches the work area above if any. | 804 // cursor reaches the work area above if any. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 819 } | 815 } |
| 820 } else if (sticky_size > 0) { | 816 } else if (sticky_size > 0) { |
| 821 MagneticallySnapResizeToOtherWindows(bounds); | 817 MagneticallySnapResizeToOtherWindows(bounds); |
| 822 if (!magnetism_window_ && sticky_size > 0) | 818 if (!magnetism_window_ && sticky_size > 0) |
| 823 StickToWorkAreaOnResize(work_area, sticky_size, bounds); | 819 StickToWorkAreaOnResize(work_area, sticky_size, bounds); |
| 824 } | 820 } |
| 825 | 821 |
| 826 if (attached_windows_.empty()) | 822 if (attached_windows_.empty()) |
| 827 return; | 823 return; |
| 828 | 824 |
| 829 if (details_.window_component == HTRIGHT) { | 825 if (details().window_component == HTRIGHT) { |
| 830 bounds->set_width(std::min(bounds->width(), | 826 bounds->set_width(std::min(bounds->width(), |
| 831 work_area.right() - total_min_ - bounds->x())); | 827 work_area.right() - total_min_ - bounds->x())); |
| 832 } else { | 828 } else { |
| 833 DCHECK_EQ(HTBOTTOM, details_.window_component); | 829 DCHECK_EQ(HTBOTTOM, details().window_component); |
| 834 bounds->set_height(std::min(bounds->height(), | 830 bounds->set_height(std::min(bounds->height(), |
| 835 work_area.bottom() - total_min_ - bounds->y())); | 831 work_area.bottom() - total_min_ - bounds->y())); |
| 836 } | 832 } |
| 837 } | 833 } |
| 838 | 834 |
| 839 bool WorkspaceWindowResizer::StickToWorkAreaOnMove( | 835 bool WorkspaceWindowResizer::StickToWorkAreaOnMove( |
| 840 const gfx::Rect& work_area, | 836 const gfx::Rect& work_area, |
| 841 int sticky_size, | 837 int sticky_size, |
| 842 gfx::Rect* bounds) const { | 838 gfx::Rect* bounds) const { |
| 843 const int left_edge = work_area.x(); | 839 const int left_edge = work_area.x(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 863 bounds->set_y(bottom_edge - bounds->height()); | 859 bounds->set_y(bottom_edge - bounds->height()); |
| 864 updated = true; | 860 updated = true; |
| 865 } | 861 } |
| 866 return updated; | 862 return updated; |
| 867 } | 863 } |
| 868 | 864 |
| 869 void WorkspaceWindowResizer::StickToWorkAreaOnResize( | 865 void WorkspaceWindowResizer::StickToWorkAreaOnResize( |
| 870 const gfx::Rect& work_area, | 866 const gfx::Rect& work_area, |
| 871 int sticky_size, | 867 int sticky_size, |
| 872 gfx::Rect* bounds) const { | 868 gfx::Rect* bounds) const { |
| 873 const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); | 869 const uint32 edges = WindowComponentToMagneticEdge( |
| 870 details().window_component); |
| 874 const int left_edge = work_area.x(); | 871 const int left_edge = work_area.x(); |
| 875 const int right_edge = work_area.right(); | 872 const int right_edge = work_area.right(); |
| 876 const int top_edge = work_area.y(); | 873 const int top_edge = work_area.y(); |
| 877 const int bottom_edge = work_area.bottom(); | 874 const int bottom_edge = work_area.bottom(); |
| 878 if (edges & MAGNETISM_EDGE_TOP && | 875 if (edges & MAGNETISM_EDGE_TOP && |
| 879 ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { | 876 ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { |
| 880 bounds->set_height(bounds->bottom() - top_edge); | 877 bounds->set_height(bounds->bottom() - top_edge); |
| 881 bounds->set_y(top_edge); | 878 bounds->set_y(top_edge); |
| 882 } | 879 } |
| 883 if (edges & MAGNETISM_EDGE_LEFT && | 880 if (edges & MAGNETISM_EDGE_LEFT && |
| 884 ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { | 881 ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { |
| 885 bounds->set_width(bounds->right() - left_edge); | 882 bounds->set_width(bounds->right() - left_edge); |
| 886 bounds->set_x(left_edge); | 883 bounds->set_x(left_edge); |
| 887 } | 884 } |
| 888 if (edges & MAGNETISM_EDGE_BOTTOM && | 885 if (edges & MAGNETISM_EDGE_BOTTOM && |
| 889 ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size)) { | 886 ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size)) { |
| 890 bounds->set_height(bottom_edge - bounds->y()); | 887 bounds->set_height(bottom_edge - bounds->y()); |
| 891 } | 888 } |
| 892 if (edges & MAGNETISM_EDGE_RIGHT && | 889 if (edges & MAGNETISM_EDGE_RIGHT && |
| 893 ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { | 890 ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { |
| 894 bounds->set_width(right_edge - bounds->x()); | 891 bounds->set_width(right_edge - bounds->x()); |
| 895 } | 892 } |
| 896 } | 893 } |
| 897 | 894 |
| 898 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { | 895 int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { |
| 899 return PrimaryAxisCoordinate(size.width(), size.height()); | 896 return PrimaryAxisCoordinate(size.width(), size.height()); |
| 900 } | 897 } |
| 901 | 898 |
| 902 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { | 899 int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { |
| 903 switch (details_.window_component) { | 900 switch (details().window_component) { |
| 904 case HTRIGHT: | 901 case HTRIGHT: |
| 905 return x; | 902 return x; |
| 906 case HTBOTTOM: | 903 case HTBOTTOM: |
| 907 return y; | 904 return y; |
| 908 default: | 905 default: |
| 909 NOTREACHED(); | 906 NOTREACHED(); |
| 910 } | 907 } |
| 911 return 0; | 908 return 0; |
| 912 } | 909 } |
| 913 | 910 |
| 914 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, | 911 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, |
| 915 const gfx::Rect& bounds) { | 912 const gfx::Rect& bounds) { |
| 916 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) | 913 if (!did_move_or_resize_ || details().window_component != HTCAPTION) |
| 917 return; | 914 return; |
| 918 | 915 |
| 919 SnapType last_type = snap_type_; | 916 SnapType last_type = snap_type_; |
| 920 snap_type_ = GetSnapType(location); | 917 snap_type_ = GetSnapType(location); |
| 921 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { | 918 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { |
| 922 snap_phantom_window_controller_.reset(); | 919 snap_phantom_window_controller_.reset(); |
| 923 snap_sizer_.reset(); | 920 snap_sizer_.reset(); |
| 924 if (snap_type_ == SNAP_NONE) { | 921 if (snap_type_ == SNAP_NONE) { |
| 925 SetDraggedWindowDocked(false); | 922 SetDraggedWindowDocked(false); |
| 926 return; | 923 return; |
| 927 } | 924 } |
| 928 } | 925 } |
| 929 const bool can_dock = dock_layout_->CanDockWindow(window(), snap_type_); | 926 const bool can_dock = dock_layout_->CanDockWindow(GetTarget(), snap_type_); |
| 930 const bool can_snap = window_state()->CanSnap(); | 927 const bool can_snap = window_state()->CanSnap(); |
| 931 if (!can_snap && !can_dock) { | 928 if (!can_snap && !can_dock) { |
| 932 snap_type_ = SNAP_NONE; | 929 snap_type_ = SNAP_NONE; |
| 933 snap_phantom_window_controller_.reset(); | 930 snap_phantom_window_controller_.reset(); |
| 934 snap_sizer_.reset(); | 931 snap_sizer_.reset(); |
| 935 SetDraggedWindowDocked(false); | 932 SetDraggedWindowDocked(false); |
| 936 return; | 933 return; |
| 937 } | 934 } |
| 938 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? | 935 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? |
| 939 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; | 936 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| 940 if (!snap_sizer_) { | 937 if (!snap_sizer_) { |
| 941 snap_sizer_.reset(new SnapSizer(window_state(), | 938 snap_sizer_.reset(new SnapSizer(window_state(), |
| 942 location, | 939 location, |
| 943 edge, | 940 edge, |
| 944 internal::SnapSizer::OTHER_INPUT)); | 941 internal::SnapSizer::OTHER_INPUT)); |
| 945 } else { | 942 } else { |
| 946 snap_sizer_->Update(location); | 943 snap_sizer_->Update(location); |
| 947 } | 944 } |
| 948 | 945 |
| 949 // Update phantom window with snapped or docked guide bounds. | 946 // Update phantom window with snapped or docked guide bounds. |
| 950 // Windows that cannot be snapped or are less wide than kMaxDockWidth can get | 947 // Windows that cannot be snapped or are less wide than kMaxDockWidth can get |
| 951 // docked without going through a snapping sequence. | 948 // docked without going through a snapping sequence. |
| 952 gfx::Rect phantom_bounds; | 949 gfx::Rect phantom_bounds; |
| 953 if (can_snap && | 950 if (can_snap && (!can_dock || GetTarget()->bounds().width() > |
| 954 (!can_dock || | 951 DockedWindowLayoutManager::kMaxDockWidth)) { |
| 955 window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth)) | |
| 956 phantom_bounds = snap_sizer_->target_bounds(); | 952 phantom_bounds = snap_sizer_->target_bounds(); |
| 953 } |
| 957 const bool should_dock = can_dock && | 954 const bool should_dock = can_dock && |
| 958 (phantom_bounds.IsEmpty() || | 955 (phantom_bounds.IsEmpty() || |
| 959 snap_sizer_->end_of_sequence() || | 956 snap_sizer_->end_of_sequence() || |
| 960 dock_layout_->is_dragged_window_docked()); | 957 dock_layout_->is_dragged_window_docked()); |
| 961 SetDraggedWindowDocked(should_dock); | 958 SetDraggedWindowDocked(should_dock); |
| 962 snap_type_ = GetSnapType(location); | 959 snap_type_ = GetSnapType(location); |
| 963 if (dock_layout_->is_dragged_window_docked()) { | 960 if (dock_layout_->is_dragged_window_docked()) { |
| 964 phantom_bounds = ScreenAsh::ConvertRectFromScreen( | 961 phantom_bounds = ScreenAsh::ConvertRectFromScreen( |
| 965 window()->parent(), dock_layout_->dragged_bounds()); | 962 GetTarget()->parent(), dock_layout_->dragged_bounds()); |
| 966 } | 963 } |
| 967 | 964 |
| 968 if (phantom_bounds.IsEmpty()) { | 965 if (phantom_bounds.IsEmpty()) { |
| 969 snap_phantom_window_controller_.reset(); | 966 snap_phantom_window_controller_.reset(); |
| 970 return; | 967 return; |
| 971 } | 968 } |
| 972 | 969 |
| 973 if (!snap_phantom_window_controller_) { | 970 if (!snap_phantom_window_controller_) { |
| 974 snap_phantom_window_controller_.reset( | 971 snap_phantom_window_controller_.reset( |
| 975 new PhantomWindowController(window())); | 972 new PhantomWindowController(GetTarget())); |
| 976 } | 973 } |
| 977 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( | 974 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( |
| 978 window()->parent(), phantom_bounds)); | 975 GetTarget()->parent(), phantom_bounds)); |
| 979 } | 976 } |
| 980 | 977 |
| 981 void WorkspaceWindowResizer::RestackWindows() { | 978 void WorkspaceWindowResizer::RestackWindows() { |
| 982 if (attached_windows_.empty()) | 979 if (attached_windows_.empty()) |
| 983 return; | 980 return; |
| 984 // Build a map from index in children to window, returning if there is a | 981 // Build a map from index in children to window, returning if there is a |
| 985 // window with a different parent. | 982 // window with a different parent. |
| 986 typedef std::map<size_t, aura::Window*> IndexToWindowMap; | 983 typedef std::map<size_t, aura::Window*> IndexToWindowMap; |
| 987 IndexToWindowMap map; | 984 IndexToWindowMap map; |
| 988 aura::Window* parent = window()->parent(); | 985 aura::Window* parent = GetTarget()->parent(); |
| 989 const aura::Window::Windows& windows(parent->children()); | 986 const aura::Window::Windows& windows(parent->children()); |
| 990 map[std::find(windows.begin(), windows.end(), window()) - | 987 map[std::find(windows.begin(), windows.end(), GetTarget()) - |
| 991 windows.begin()] = window(); | 988 windows.begin()] = GetTarget(); |
| 992 for (std::vector<aura::Window*>::const_iterator i = | 989 for (std::vector<aura::Window*>::const_iterator i = |
| 993 attached_windows_.begin(); i != attached_windows_.end(); ++i) { | 990 attached_windows_.begin(); i != attached_windows_.end(); ++i) { |
| 994 if ((*i)->parent() != parent) | 991 if ((*i)->parent() != parent) |
| 995 return; | 992 return; |
| 996 size_t index = | 993 size_t index = |
| 997 std::find(windows.begin(), windows.end(), *i) - windows.begin(); | 994 std::find(windows.begin(), windows.end(), *i) - windows.begin(); |
| 998 map[index] = *i; | 995 map[index] = *i; |
| 999 } | 996 } |
| 1000 | 997 |
| 1001 // Reorder the windows starting at the topmost. | 998 // Reorder the windows starting at the topmost. |
| 1002 parent->StackChildAtTop(map.rbegin()->second); | 999 parent->StackChildAtTop(map.rbegin()->second); |
| 1003 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); | 1000 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); |
| 1004 i != map.rend(); ) { | 1001 i != map.rend(); ) { |
| 1005 aura::Window* window = i->second; | 1002 aura::Window* window = i->second; |
| 1006 ++i; | 1003 ++i; |
| 1007 if (i != map.rend()) | 1004 if (i != map.rend()) |
| 1008 parent->StackChildBelow(i->second, window); | 1005 parent->StackChildBelow(i->second, window); |
| 1009 } | 1006 } |
| 1010 } | 1007 } |
| 1011 | 1008 |
| 1012 SnapType WorkspaceWindowResizer::GetSnapType( | 1009 SnapType WorkspaceWindowResizer::GetSnapType( |
| 1013 const gfx::Point& location) const { | 1010 const gfx::Point& location) const { |
| 1014 // TODO: this likely only wants total display area, not the area of a single | 1011 // TODO: this likely only wants total display area, not the area of a single |
| 1015 // display. | 1012 // display. |
| 1016 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); | 1013 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(GetTarget())); |
| 1017 if (details_.source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 1014 if (details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
| 1018 // Increase tolerance for touch-snapping near the screen edges. This is only | 1015 // Increase tolerance for touch-snapping near the screen edges. This is only |
| 1019 // necessary when the work area left or right edge is same as screen edge. | 1016 // necessary when the work area left or right edge is same as screen edge. |
| 1020 gfx::Rect display_bounds(ScreenAsh::GetDisplayBoundsInParent(window())); | 1017 gfx::Rect display_bounds(ScreenAsh::GetDisplayBoundsInParent(GetTarget())); |
| 1021 int inset_left = 0; | 1018 int inset_left = 0; |
| 1022 if (area.x() == display_bounds.x()) | 1019 if (area.x() == display_bounds.x()) |
| 1023 inset_left = kScreenEdgeInsetForTouchResize; | 1020 inset_left = kScreenEdgeInsetForTouchResize; |
| 1024 int inset_right = 0; | 1021 int inset_right = 0; |
| 1025 if (area.right() == display_bounds.right()) | 1022 if (area.right() == display_bounds.right()) |
| 1026 inset_right = kScreenEdgeInsetForTouchResize; | 1023 inset_right = kScreenEdgeInsetForTouchResize; |
| 1027 area.Inset(inset_left, 0, inset_right, 0); | 1024 area.Inset(inset_left, 0, inset_right, 0); |
| 1028 } | 1025 } |
| 1029 if (location.x() <= area.x()) | 1026 if (location.x() <= area.x()) |
| 1030 return SNAP_LEFT; | 1027 return SNAP_LEFT; |
| 1031 if (location.x() >= area.right() - 1) | 1028 if (location.x() >= area.right() - 1) |
| 1032 return SNAP_RIGHT; | 1029 return SNAP_RIGHT; |
| 1033 return SNAP_NONE; | 1030 return SNAP_NONE; |
| 1034 } | 1031 } |
| 1035 | 1032 |
| 1036 void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) { | 1033 void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) { |
| 1037 if (should_dock && | 1034 if (should_dock && |
| 1038 dock_layout_->GetAlignmentOfWindow(window()) != DOCKED_ALIGNMENT_NONE) { | 1035 dock_layout_->GetAlignmentOfWindow(GetTarget()) != |
| 1036 DOCKED_ALIGNMENT_NONE) { |
| 1039 if (!dock_layout_->is_dragged_window_docked()) { | 1037 if (!dock_layout_->is_dragged_window_docked()) { |
| 1040 window_state()->set_bounds_changed_by_user(false); | 1038 window_state()->set_bounds_changed_by_user(false); |
| 1041 dock_layout_->DockDraggedWindow(window()); | 1039 dock_layout_->DockDraggedWindow(GetTarget()); |
| 1042 } | 1040 } |
| 1043 } else { | 1041 } else { |
| 1044 if (dock_layout_->is_dragged_window_docked()) { | 1042 if (dock_layout_->is_dragged_window_docked()) { |
| 1045 dock_layout_->UndockDraggedWindow(); | 1043 dock_layout_->UndockDraggedWindow(); |
| 1046 window_state()->set_bounds_changed_by_user(true); | 1044 window_state()->set_bounds_changed_by_user(true); |
| 1047 } | 1045 } |
| 1048 } | 1046 } |
| 1049 } | 1047 } |
| 1050 | 1048 |
| 1051 } // namespace internal | 1049 } // namespace internal |
| 1052 } // namespace ash | 1050 } // namespace ash |
| OLD | NEW |