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

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 should get triggered by pressing against the screen edge (warn) 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"
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"
23 #include "ash/wm/window_properties.h" 24 #include "ash/wm/window_properties.h"
24 #include "ash/wm/window_util.h" 25 #include "ash/wm/window_util.h"
25 #include "ash/wm/workspace/phantom_window_controller.h" 26 #include "ash/wm/workspace/phantom_window_controller.h"
26 #include "ash/wm/workspace/snap_sizer.h" 27 #include "ash/wm/workspace/snap_sizer.h"
27 #include "base/command_line.h" 28 #include "base/command_line.h"
29 #include "base/memory/weak_ptr.h"
28 #include "ui/aura/client/aura_constants.h" 30 #include "ui/aura/client/aura_constants.h"
29 #include "ui/aura/client/screen_position_client.h" 31 #include "ui/aura/client/screen_position_client.h"
30 #include "ui/aura/client/window_types.h" 32 #include "ui/aura/client/window_types.h"
31 #include "ui/aura/root_window.h" 33 #include "ui/aura/root_window.h"
32 #include "ui/aura/window.h" 34 #include "ui/aura/window.h"
33 #include "ui/aura/window_delegate.h" 35 #include "ui/aura/window_delegate.h"
34 #include "ui/base/hit_test.h" 36 #include "ui/base/hit_test.h"
35 #include "ui/compositor/layer.h" 37 #include "ui/compositor/layer.h"
36 #include "ui/gfx/screen.h" 38 #include "ui/gfx/screen.h"
37 #include "ui/gfx/transform.h" 39 #include "ui/gfx/transform.h"
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); 373 gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent);
372 374
373 if (wm::IsWindowNormal(window())) 375 if (wm::IsWindowNormal(window()))
374 AdjustBoundsForMainWindow(sticky_size, &bounds); 376 AdjustBoundsForMainWindow(sticky_size, &bounds);
375 377
376 if (bounds != window()->bounds()) { 378 if (bounds != window()->bounds()) {
377 if (!did_move_or_resize_) { 379 if (!did_move_or_resize_) {
378 if (!details_.restore_bounds.IsEmpty()) 380 if (!details_.restore_bounds.IsEmpty())
379 ClearRestoreBounds(window()); 381 ClearRestoreBounds(window());
380 RestackWindows(); 382 RestackWindows();
383 DCHECK(!snap_sizer_);
384 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) {
385 // Create SnapSizer if a window is snapped to maintain docked state.
386 snap_sizer_.reset(new SnapSizer(
387 window(),
388 details_.initial_location_in_parent,
389 (snap_type_ == SNAP_LEFT) ?
390 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE,
391 internal::SnapSizer::WORKSPACE_DRAG_INPUT));
392 }
381 } 393 }
382 did_move_or_resize_ = true; 394 did_move_or_resize_ = true;
383 } 395 }
384 396
385 gfx::Point location_in_screen = location_in_parent; 397 gfx::Point location_in_screen = location_in_parent;
386 wm::ConvertPointToScreen(window()->parent(), &location_in_screen); 398 wm::ConvertPointToScreen(window()->parent(), &location_in_screen);
387 const bool in_original_root = 399
388 wm::GetRootWindowAt(location_in_screen) == window()->GetRootWindow(); 400 aura::RootWindow* root = NULL;
401 gfx::Display display =
402 ScreenAsh::FindDisplayContainingPoint(location_in_screen);
403 // Track the last screen that the pointer was on to keep the snap phantom
404 // window there.
405 if (display.is_valid()) {
406 root = Shell::GetInstance()->display_controller()->
407 GetRootWindowForDisplayId(display.id());
408 }
409 if (!attached_windows_.empty())
410 LayoutAttachedWindows(&bounds);
411 if (bounds != window()->bounds()) {
412 // SetBounds needs to be called to update the layout which affects where the
413 // phantom window is drawn. Keep track if the window was destroyed during
414 // the drag and quit early if so.
415 base::WeakPtr<WorkspaceWindowResizer> resizer(
416 weak_ptr_factory_.GetWeakPtr());
417 window()->SetBounds(bounds);
418 if (!resizer)
419 return;
420 }
421 const bool in_original_root = !root || root == window()->GetRootWindow();
389 // Hide a phantom window for snapping if the cursor is in another root window. 422 // Hide a phantom window for snapping if the cursor is in another root window.
390 if (in_original_root && wm::CanResizeWindow(window())) { 423 if (in_original_root) {
391 UpdateSnapPhantomWindow(location_in_parent, bounds); 424 UpdateSnapPhantomWindow(location_in_parent, bounds);
392 } else { 425 } else {
393 snap_type_ = SNAP_NONE; 426 snap_type_ = SNAP_NONE;
394 snap_phantom_window_controller_.reset(); 427 snap_phantom_window_controller_.reset();
428 snap_sizer_.reset();
395 } 429 }
396
397 if (!attached_windows_.empty())
398 LayoutAttachedWindows(&bounds);
399 if (bounds != window()->bounds())
400 window()->SetBounds(bounds);
401 } 430 }
402 431
403 void WorkspaceWindowResizer::CompleteDrag(int event_flags) { 432 void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
404 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true); 433 wm::SetUserHasChangedWindowPositionOrSize(details_.window, true);
405 snap_phantom_window_controller_.reset(); 434 snap_phantom_window_controller_.reset();
406 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 435 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
407 return; 436 return;
408 437
409 // When the window is not in the normal show state, we do not snap the window. 438 // 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 439 // 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 440 // 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 441 // out of a maximized window, it's already in the normal show state when this
413 // is called, so it does not matter. 442 // is called, so it does not matter.
414 if (wm::IsWindowNormal(window()) && 443 if (wm::IsWindowNormal(window()) &&
415 (window()->type() != aura::client::WINDOW_TYPE_PANEL || 444 (window()->type() != aura::client::WINDOW_TYPE_PANEL ||
416 !window()->GetProperty(kPanelAttachedKey)) && 445 !window()->GetProperty(kPanelAttachedKey)) &&
417 (snap_type_ == SNAP_LEFT_EDGE || snap_type_ == SNAP_RIGHT_EDGE)) { 446 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) {
418 if (!GetRestoreBoundsInScreen(window())) { 447 if (!GetRestoreBoundsInScreen(window())) {
419 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( 448 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen(
420 window()->parent(), details_.initial_bounds_in_parent); 449 window()->parent(), details_.initial_bounds_in_parent);
421 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ? 450 SetRestoreBoundsInScreen(window(), details_.restore_bounds.IsEmpty() ?
422 initial_bounds : 451 initial_bounds :
423 details_.restore_bounds); 452 details_.restore_bounds);
424 } 453 }
425 window()->SetBounds(snap_sizer_->target_bounds()); 454 DCHECK(snap_sizer_);
455 if (wm::CanResizeWindow(window()) &&
456 !snap_sizer_->ShouldDockWindow() &&
457 !snap_sizer_->target_bounds().IsEmpty()) {
458 window()->SetBounds(snap_sizer_->target_bounds());
459 }
426 return; 460 return;
427 } 461 }
428 } 462 }
429 463
430 void WorkspaceWindowResizer::RevertDrag() { 464 void WorkspaceWindowResizer::RevertDrag() {
431 snap_phantom_window_controller_.reset(); 465 snap_phantom_window_controller_.reset();
432 466
433 if (!did_move_or_resize_) 467 if (!did_move_or_resize_)
434 return; 468 return;
435 469
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 } 501 }
468 502
469 WorkspaceWindowResizer::WorkspaceWindowResizer( 503 WorkspaceWindowResizer::WorkspaceWindowResizer(
470 const Details& details, 504 const Details& details,
471 const std::vector<aura::Window*>& attached_windows) 505 const std::vector<aura::Window*>& attached_windows)
472 : details_(details), 506 : details_(details),
473 attached_windows_(attached_windows), 507 attached_windows_(attached_windows),
474 did_move_or_resize_(false), 508 did_move_or_resize_(false),
475 total_min_(0), 509 total_min_(0),
476 total_initial_size_(0), 510 total_initial_size_(0),
477 snap_type_(SNAP_NONE), 511 snap_type_(GetSnapType(details_.initial_location_in_parent)),
478 num_mouse_moves_since_bounds_change_(0), 512 num_mouse_moves_since_bounds_change_(0),
479 magnetism_window_(NULL) { 513 magnetism_window_(NULL),
514 weak_ptr_factory_(this) {
480 DCHECK(details_.is_resizable); 515 DCHECK(details_.is_resizable);
481 516
482 Shell* shell = Shell::GetInstance(); 517 Shell* shell = Shell::GetInstance();
483 shell->cursor_manager()->LockCursor(); 518 shell->cursor_manager()->LockCursor();
484 519
485 // Only support attaching to the right/bottom. 520 // Only support attaching to the right/bottom.
486 DCHECK(attached_windows_.empty() || 521 DCHECK(attached_windows_.empty() ||
487 (details.window_component == HTRIGHT || 522 (details.window_component == HTRIGHT ||
488 details.window_component == HTBOTTOM)); 523 details.window_component == HTBOTTOM));
489 524
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 NOTREACHED(); 883 NOTREACHED();
849 } 884 }
850 return 0; 885 return 0;
851 } 886 }
852 887
853 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, 888 void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
854 const gfx::Rect& bounds) { 889 const gfx::Rect& bounds) {
855 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 890 if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
856 return; 891 return;
857 892
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_; 893 SnapType last_type = snap_type_;
867 snap_type_ = GetSnapType(location); 894 snap_type_ = GetSnapType(location);
868 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { 895 if (snap_type_ == SNAP_NONE || snap_type_ != last_type) {
869 snap_phantom_window_controller_.reset(); 896 snap_phantom_window_controller_.reset();
870 snap_sizer_.reset(); 897 snap_sizer_.reset();
871 if (snap_type_ == SNAP_NONE) 898 if (snap_type_ == SNAP_NONE)
872 return; 899 return;
873 } 900 }
901 SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ?
902 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE;
903
874 if (!snap_sizer_) { 904 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(), 905 snap_sizer_.reset(new SnapSizer(window(),
878 location, 906 location,
879 edge, 907 edge,
880 internal::SnapSizer::OTHER_INPUT)); 908 internal::SnapSizer::WORKSPACE_DRAG_INPUT));
881 } else { 909 } else {
882 snap_sizer_->Update(location); 910 snap_sizer_->Update(location);
883 } 911 }
912
913 // Update phantom window when it is used for side-maximizing.
914 // In case of docking it will be called directly by the chained resizer.
915 if (!wm::CanSnapWindow(window()) && !SnapSizer::CanDockWindow(window(), edge))
916 return;
917
918 if (snap_sizer_->target_bounds().IsEmpty()) {
919 snap_phantom_window_controller_.reset();
920 return;
921 }
884 if (!snap_phantom_window_controller_) { 922 if (!snap_phantom_window_controller_) {
885 snap_phantom_window_controller_.reset( 923 snap_phantom_window_controller_.reset(
886 new PhantomWindowController(window())); 924 new PhantomWindowController(window()));
887 } 925 }
888 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( 926 snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen(
889 window()->parent(), snap_sizer_->target_bounds())); 927 window()->parent(), snap_sizer_->target_bounds()));
890 } 928 }
891 929
892 void WorkspaceWindowResizer::RestackWindows() { 930 void WorkspaceWindowResizer::RestackWindows() {
893 if (attached_windows_.empty()) 931 if (attached_windows_.empty())
(...skipping 19 matching lines...) Expand all
913 parent->StackChildAtTop(map.rbegin()->second); 951 parent->StackChildAtTop(map.rbegin()->second);
914 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); 952 for (IndexToWindowMap::const_reverse_iterator i = map.rbegin();
915 i != map.rend(); ) { 953 i != map.rend(); ) {
916 aura::Window* window = i->second; 954 aura::Window* window = i->second;
917 ++i; 955 ++i;
918 if (i != map.rend()) 956 if (i != map.rend())
919 parent->StackChildBelow(i->second, window); 957 parent->StackChildBelow(i->second, window);
920 } 958 }
921 } 959 }
922 960
923 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( 961 SnapType WorkspaceWindowResizer::GetSnapType(
924 const gfx::Point& location) const { 962 const gfx::Point& location) const {
925 // TODO: this likely only wants total display area, not the area of a single 963 // TODO: this likely only wants total display area, not the area of a single
926 // display. 964 // display.
927 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window())); 965 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window()));
928 if (location.x() <= area.x()) 966 if (location.x() <= area.x())
929 return SNAP_LEFT_EDGE; 967 return SNAP_LEFT;
930 if (location.x() >= area.right() - 1) 968 if (location.x() >= area.right() - 1)
931 return SNAP_RIGHT_EDGE; 969 return SNAP_RIGHT;
932 return SNAP_NONE; 970 return SNAP_NONE;
933 } 971 }
934 972
935 } // namespace internal 973 } // namespace internal
936 } // namespace ash 974 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698