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

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

Powered by Google App Engine
This is Rietveld 408576698