Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: ash/wm/workspace/workspace_window_resizer.cc

Issue 23431009: Windows docking should get triggered by pressing against the screen edge (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Windows docking by pressing against the screen edge (rebase) Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
20 #include "ash/wm/dock/docked_window_layout_manager.h"
19 #include "ash/wm/dock/docked_window_resizer.h" 21 #include "ash/wm/dock/docked_window_resizer.h"
20 #include "ash/wm/drag_window_resizer.h" 22 #include "ash/wm/drag_window_resizer.h"
21 #include "ash/wm/panels/panel_window_resizer.h" 23 #include "ash/wm/panels/panel_window_resizer.h"
22 #include "ash/wm/property_util.h" 24 #include "ash/wm/property_util.h"
23 #include "ash/wm/window_settings.h" 25 #include "ash/wm/window_settings.h"
24 #include "ash/wm/window_util.h" 26 #include "ash/wm/window_util.h"
25 #include "ash/wm/workspace/phantom_window_controller.h" 27 #include "ash/wm/workspace/phantom_window_controller.h"
26 #include "ash/wm/workspace/snap_sizer.h" 28 #include "ash/wm/workspace/snap_sizer.h"
27 #include "base/command_line.h" 29 #include "base/command_line.h"
30 #include "base/memory/weak_ptr.h"
28 #include "ui/aura/client/aura_constants.h" 31 #include "ui/aura/client/aura_constants.h"
29 #include "ui/aura/client/screen_position_client.h" 32 #include "ui/aura/client/screen_position_client.h"
30 #include "ui/aura/client/window_types.h" 33 #include "ui/aura/client/window_types.h"
31 #include "ui/aura/root_window.h" 34 #include "ui/aura/root_window.h"
32 #include "ui/aura/window.h" 35 #include "ui/aura/window.h"
33 #include "ui/aura/window_delegate.h" 36 #include "ui/aura/window_delegate.h"
34 #include "ui/base/hit_test.h" 37 #include "ui/base/hit_test.h"
35 #include "ui/compositor/layer.h" 38 #include "ui/compositor/layer.h"
36 #include "ui/gfx/screen.h" 39 #include "ui/gfx/screen.h"
37 #include "ui/gfx/transform.h" 40 #include "ui/gfx/transform.h"
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 if (!did_move_or_resize_) { 382 if (!did_move_or_resize_) {
380 if (!details_.restore_bounds.IsEmpty()) 383 if (!details_.restore_bounds.IsEmpty())
381 ClearRestoreBounds(window()); 384 ClearRestoreBounds(window());
382 RestackWindows(); 385 RestackWindows();
383 } 386 }
384 did_move_or_resize_ = true; 387 did_move_or_resize_ = true;
385 } 388 }
386 389
387 gfx::Point location_in_screen = location_in_parent; 390 gfx::Point location_in_screen = location_in_parent;
388 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); 391 wm::ConvertPointToScreen(window()->parent(), &location_in_screen);
389 const bool in_original_root = 392
390 wm::GetRootWindowAt(location_in_screen) == window()->GetRootWindow(); 393 aura::RootWindow* root = NULL;
394 gfx::Display display =
395 ScreenAsh::FindDisplayContainingPoint(location_in_screen);
396 // Track the last screen that the pointer was on to keep the snap phantom
397 // window there.
398 if (display.is_valid()) {
399 root = Shell::GetInstance()->display_controller()->
400 GetRootWindowForDisplayId(display.id());
401 }
402 if (!attached_windows_.empty())
403 LayoutAttachedWindows(&bounds);
404 if (bounds != window()->bounds()) {
405 // SetBounds needs to be called to update the layout which affects where the
406 // phantom window is drawn. Keep track if the window was destroyed during
407 // the drag and quit early if so.
408 base::WeakPtr<WorkspaceWindowResizer> resizer(
409 weak_ptr_factory_.GetWeakPtr());
410 window()->SetBounds(bounds);
411 if (!resizer)
412 return;
413 }
414 const bool in_original_root = !root || root == window()->GetRootWindow();
391 // Hide a phantom window for snapping if the cursor is in another root window. 415 // Hide a phantom window for snapping if the cursor is in another root window.
392 if (in_original_root && wm::CanResizeWindow(window())) { 416 if (in_original_root) {
393 UpdateSnapPhantomWindow(location_in_parent, bounds); 417 UpdateSnapPhantomWindow(location_in_parent, bounds);
394 } else { 418 } else {
395 snap_type_ = SNAP_NONE; 419 snap_type_ = SNAP_NONE;
396 snap_phantom_window_controller_.reset(); 420 snap_phantom_window_controller_.reset();
421 snap_sizer_.reset();
422 UpdateDockedState(false);
397 } 423 }
398
399 if (!attached_windows_.empty())
400 LayoutAttachedWindows(&bounds);
401 if (bounds != window()->bounds())
402 window()->SetBounds(bounds);
403 } 424 }
404 425
405 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { 426 void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
406 wm::GetWindowSettings(details_.window)->set_bounds_changed_by_user(true); 427 wm::GetWindowSettings(details_.window)->set_bounds_changed_by_user(true);
407 snap_phantom_window_controller_.reset(); 428 snap_phantom_window_controller_.reset();
408 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 429 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
409 return; 430 return;
410 431
411 // When the window is not in the normal show state, we do not snap the window. 432 // When the window is not in the normal show state, we do not snap the window.
412 // This happens when the user minimizes or maximizes the window by keyboard 433 // This happens when the user minimizes or maximizes the window by keyboard
413 // shortcut while dragging it. If the window is the result of dragging a tab 434 // shortcut while dragging it. If the window is the result of dragging a tab
414 // out of a maximized window, it's already in the normal show state when this 435 // out of a maximized window, it's already in the normal show state when this
415 // is called, so it does not matter. 436 // is called, so it does not matter.
416 if (wm::IsWindowNormal(window()) && 437 if (wm::IsWindowNormal(window()) &&
417 (window()->type() != aura::client::WINDOW_TYPE_PANEL || 438 (window()->type() != aura::client::WINDOW_TYPE_PANEL ||
418 !wm::GetWindowSettings(window())->panel_attached()) && 439 !wm::GetWindowSettings(window())->panel_attached()) &&
419 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { 440 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) {
420 if (!GetRestoreBoundsInScreen(window())) { 441 if (!GetRestoreBoundsInScreen(window())) {
421 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( 442 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen(
422 window()->parent(), details_.initial_bounds_in_parent); 443 window()->parent(), details_.initial_bounds_in_parent);
423 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? 444 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ?
424 initial_bounds : 445 initial_bounds :
425 details_.restore_bounds); 446 details_.restore_bounds);
426 } 447 }
427 window()->SetBounds(snap_sizer_->target_bounds()); 448 DCHECK(snap_sizer_);
449 if (wm::CanResizeWindow(window()) &&
450 !dock_layout_->is_dragged_window_docked() &&
451 !snap_sizer_->target_bounds().IsEmpty()) {
452 window()->SetBounds(snap_sizer_->target_bounds());
453 }
428 return; 454 return;
429 } 455 }
430 } 456 }
431 457
432 void WorkspaceWindowResizer::RevertDrag() { 458 void WorkspaceWindowResizer::RevertDrag() {
433 snap_phantom_window_controller_.reset(); 459 snap_phantom_window_controller_.reset();
434 460
435 if (!did_move_or_resize_) 461 if (!did_move_or_resize_)
436 return; 462 return;
437 463
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 WorkspaceWindowResizer::WorkspaceWindowResizer( 497 WorkspaceWindowResizer::WorkspaceWindowResizer(
472 const Details& details, 498 const Details& details,
473 const std::vector<aura::Window*>& attached_windows) 499 const std::vector<aura::Window*>& attached_windows)
474 : details_(details), 500 : details_(details),
475 attached_windows_(attached_windows), 501 attached_windows_(attached_windows),
476 did_move_or_resize_(false), 502 did_move_or_resize_(false),
477 total_min_(0), 503 total_min_(0),
478 total_initial_size_(0), 504 total_initial_size_(0),
479 snap_type_(SNAP_NONE), 505 snap_type_(SNAP_NONE),
480 num_mouse_moves_since_bounds_change_(0), 506 num_mouse_moves_since_bounds_change_(0),
481 magnetism_window_(NULL) { 507 magnetism_window_(NULL),
508 weak_ptr_factory_(this) {
482 DCHECK(details_.is_resizable); 509 DCHECK(details_.is_resizable);
483 510
484 Shell* shell = Shell::GetInstance(); 511 Shell* shell = Shell::GetInstance();
485 shell->cursor_manager()->LockCursor(); 512 shell->cursor_manager()->LockCursor();
486 513
514 aura::Window* dock_container = Shell::GetContainer(
515 window()->GetRootWindow(), kShellWindowId_DockedContainer);
516 dock_layout_ = static_cast<DockedWindowLayoutManager*>(
517 dock_container->layout_manager());
518
487 // Only support attaching to the right/bottom. 519 // Only support attaching to the right/bottom.
488 DCHECK(attached_windows_.empty() || 520 DCHECK(attached_windows_.empty() ||
489 (details.window_component == HTRIGHT || 521 (details.window_component == HTRIGHT ||
490 details.window_component == HTBOTTOM)); 522 details.window_component == HTBOTTOM));
491 523
492 // TODO: figure out how to deal with window going off the edge. 524 // TODO: figure out how to deal with window going off the edge.
493 525
494 // Calculate sizes so that we can maintain the ratios if we need to resize. 526 // Calculate sizes so that we can maintain the ratios if we need to resize.
495 int total_available = 0; 527 int total_available = 0;
496 for (size_t i = 0; i < attached_windows_.size(); ++i) { 528 for (size_t i = 0; i < attached_windows_.size(); ++i) {
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 NOTREACHED(); 883 NOTREACHED();
852 } 884 }
853 return 0; 885 return 0;
854 } 886 }
855 887
856 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, 888 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
857 const gfx::Rect& bounds) { 889 const gfx::Rect& bounds) {
858 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 890 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
859 return; 891 return;
860 892
861 if (!wm::CanSnapWindow(window()))
862 return;
863
864 if (window()->type() == aura::client::WINDOW_TYPE_PANEL &&
865 wm::GetWindowSettings(window())->panel_attached()) {
866 return;
867 }
868
869 SnapType last_type = snap_type_; 893 SnapType last_type = snap_type_;
870 snap_type_ = GetSnapType(location); 894 snap_type_ = GetSnapType(location);
871 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { 895 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) {
872 snap_phantom_window_controller_.reset(); 896 snap_phantom_window_controller_.reset();
873 snap_sizer_.reset(); 897 snap_sizer_.reset();
898 UpdateDockedState(false);
874 if (snap_type_ == SNAP_NONE) 899 if (snap_type_ == SNAP_NONE)
875 return; 900 return;
876 } 901 }
902 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ?
903 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE;
904
877 if (!snap_sizer_) { 905 if (!snap_sizer_) {
878 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ?
879 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE;
880 snap_sizer_.reset(new SnapSizer(window(), 906 snap_sizer_.reset(new SnapSizer(window(),
881 location, 907 location,
882 edge, 908 edge,
883 internal::SnapSizer::OTHER_INPUT)); 909 internal::SnapSizer::OTHER_INPUT));
884 } else { 910 } else {
885 snap_sizer_->Update(location); 911 snap_sizer_->Update(location);
886 } 912 }
913
914 const bool can_dock = dock_layout_->CanDockWindow(window(), snap_type_);
915 if (!wm::CanSnapWindow(window()) && !can_dock)
916 return;
917
918 // Update phantom window with snapped or docked guide bounds.
919 // Windows that cannot be snapped or are less wide than kMaxDockWidth can get
920 // docked without going through a snapping sequence.
921 gfx::Rect phantom_bounds;
922 if (!can_dock ||
923 window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth)
924 phantom_bounds = snap_sizer_->target_bounds();
925 const bool is_docked = can_dock &&
926 (phantom_bounds.IsEmpty() || snap_sizer_->end_of_sequence());
927 UpdateDockedState(is_docked);
928 if (is_docked) {
929 phantom_bounds = ScreenAsh::ConvertRectFromScreen(
930 window()->parent(), dock_layout_->dragged_bounds());
931 }
932
933 if (phantom_bounds.IsEmpty()) {
934 snap_phantom_window_controller_.reset();
935 return;
936 }
937
887 if (!snap_phantom_window_controller_) { 938 if (!snap_phantom_window_controller_) {
888 snap_phantom_window_controller_.reset( 939 snap_phantom_window_controller_.reset(
889 new PhantomWindowController(window())); 940 new PhantomWindowController(window()));
890 } 941 }
891 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( 942 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen(
892 window()->parent(), snap_sizer_->target_bounds())); 943 window()->parent(), phantom_bounds));
893 } 944 }
894 945
895 void WorkspaceWindowResizer::RestackWindows() { 946 void WorkspaceWindowResizer::RestackWindows() {
896 if (attached_windows_.empty()) 947 if (attached_windows_.empty())
897 return; 948 return;
898 // Build a map from index in children to window, returning if there is a 949 // Build a map from index in children to window, returning if there is a
899 // window with a different parent. 950 // window with a different parent.
900 typedef std::map<size_t, aura::Window*> IndexToWindowMap; 951 typedef std::map<size_t, aura::Window*> IndexToWindowMap;
901 IndexToWindowMap map; 952 IndexToWindowMap map;
902 aura::Window* parent = window()->parent(); 953 aura::Window* parent = window()->parent();
(...skipping 13 matching lines...) Expand all
916 parent->StackChildAtTop(map.rbegin()->second); 967 parent->StackChildAtTop(map.rbegin()->second);
917 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); 968 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin();
918 i != map.rend(); ) { 969 i != map.rend(); ) {
919 aura::Window* window = i->second; 970 aura::Window* window = i->second;
920 ++i; 971 ++i;
921 if (i != map.rend()) 972 if (i != map.rend())
922 parent->StackChildBelow(i->second, window); 973 parent->StackChildBelow(i->second, window);
923 } 974 }
924 } 975 }
925 976
926 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( 977 SnapType WorkspaceWindowResizer::GetSnapType(
927 const gfx::Point& location) const { 978 const gfx::Point& location) const {
928 // TODO: this likely only wants total display area, not the area of a single 979 // TODO: this likely only wants total display area, not the area of a single
929 // display. 980 // display.
930 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); 981 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window()));
931 if (location.x() <= area.x()) 982 if (location.x() <= area.x())
932 return SNAP_LEFT_EDGE; 983 return SNAP_LEFT;
933 if (location.x() >= area.right() - 1) 984 if (location.x() >= area.right() - 1)
934 return SNAP_RIGHT_EDGE; 985 return SNAP_RIGHT;
935 return SNAP_NONE; 986 return SNAP_NONE;
936 } 987 }
937 988
989 void WorkspaceWindowResizer::UpdateDockedState(bool is_docked) {
990 if (is_docked &&
991 dock_layout_->GetAlignmentOfWindow(window()) != DOCKED_ALIGNMENT_NONE) {
992 if (!dock_layout_->is_dragged_window_docked())
993 dock_layout_->DockDraggedWindow(window());
994 } else {
995 if (dock_layout_->is_dragged_window_docked())
996 dock_layout_->UndockDraggedWindow();
997 }
998 }
999
938 } // namespace internal 1000 } // namespace internal
939 } // namespace ash 1001 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/workspace/workspace_window_resizer.h ('k') | ash/wm/workspace/workspace_window_resizer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698