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

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

Issue 10883069: Added restore functionality for maximize full/left/right (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed unit test failure Created 8 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 | Annotate | Revision Log
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/frame_maximize_button.h" 5 #include "ash/wm/workspace/frame_maximize_button.h"
6 6
7 #include "ash/launcher/launcher.h" 7 #include "ash/launcher/launcher.h"
8 #include "ash/screen_ash.h" 8 #include "ash/screen_ash.h"
9 #include "ash/shell.h" 9 #include "ash/shell.h"
10 #include "ash/wm/property_util.h" 10 #include "ash/wm/property_util.h"
(...skipping 17 matching lines...) Expand all
28 namespace ash { 28 namespace ash {
29 29
30 namespace { 30 namespace {
31 31
32 // Delay before forcing an update of the snap location. 32 // Delay before forcing an update of the snap location.
33 const int kUpdateDelayMS = 400; 33 const int kUpdateDelayMS = 400;
34 34
35 // The delay of the bubble appearance. 35 // The delay of the bubble appearance.
36 const int kBubbleAppearanceDelayMS = 500; 36 const int kBubbleAppearanceDelayMS = 500;
37 37
38 // The minimum sanp size in percent of the screen width.
39 const int kMinSnapSizePercent = 50;
38 } 40 }
39 41
40 // EscapeEventFilter is installed on the RootWindow to track when the escape key 42 // EscapeEventFilter is installed on the RootWindow to track when the escape key
41 // is pressed. We use an EventFilter for this as the FrameMaximizeButton 43 // is pressed. We use an EventFilter for this as the FrameMaximizeButton
42 // normally does not get focus. 44 // normally does not get focus.
43 class FrameMaximizeButton::EscapeEventFilter : public aura::EventFilter { 45 class FrameMaximizeButton::EscapeEventFilter : public aura::EventFilter {
44 public: 46 public:
45 explicit EscapeEventFilter(FrameMaximizeButton* button); 47 explicit EscapeEventFilter(FrameMaximizeButton* button);
46 virtual ~EscapeEventFilter(); 48 virtual ~EscapeEventFilter();
47 49
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 void FrameMaximizeButton::OnMouseEntered(const ui::MouseEvent& event) { 207 void FrameMaximizeButton::OnMouseEntered(const ui::MouseEvent& event) {
206 ImageButton::OnMouseEntered(event); 208 ImageButton::OnMouseEntered(event);
207 if (!maximizer_.get()) { 209 if (!maximizer_.get()) {
208 DCHECK(GetWidget()); 210 DCHECK(GetWidget());
209 if (!window_) { 211 if (!window_) {
210 window_ = frame_->GetWidget()->GetNativeWindow(); 212 window_ = frame_->GetWidget()->GetNativeWindow();
211 window_->AddObserver(this); 213 window_->AddObserver(this);
212 } 214 }
213 maximizer_.reset(new MaximizeBubbleController( 215 maximizer_.reset(new MaximizeBubbleController(
214 this, 216 this,
215 frame_->GetWidget()->IsMaximized(), 217 GetMaximizeBubbleFrameState(),
216 bubble_appearance_delay_ms_)); 218 bubble_appearance_delay_ms_));
217 } 219 }
218 } 220 }
219 221
220 void FrameMaximizeButton::OnMouseExited(const ui::MouseEvent& event) { 222 void FrameMaximizeButton::OnMouseExited(const ui::MouseEvent& event) {
221 ImageButton::OnMouseExited(event); 223 ImageButton::OnMouseExited(event);
222 // Remove the bubble menu when the button is not pressed and the mouse is not 224 // Remove the bubble menu when the button is not pressed and the mouse is not
223 // within the bubble. 225 // within the bubble.
224 if (!is_snap_enabled_ && maximizer_.get()) { 226 if (!is_snap_enabled_ && maximizer_.get()) {
225 if (maximizer_->GetBubbleWindow()) { 227 if (maximizer_->GetBubbleWindow()) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 299
298 return ImageButton::OnGestureEvent(event); 300 return ImageButton::OnGestureEvent(event);
299 } 301 }
300 302
301 void FrameMaximizeButton::ProcessStartEvent(const ui::LocatedEvent& event) { 303 void FrameMaximizeButton::ProcessStartEvent(const ui::LocatedEvent& event) {
302 DCHECK(is_snap_enabled_); 304 DCHECK(is_snap_enabled_);
303 // Prepare the help menu. 305 // Prepare the help menu.
304 if (!maximizer_.get()) { 306 if (!maximizer_.get()) {
305 maximizer_.reset(new MaximizeBubbleController( 307 maximizer_.reset(new MaximizeBubbleController(
306 this, 308 this,
307 frame_->GetWidget()->IsMaximized(), 309 GetMaximizeBubbleFrameState(),
308 bubble_appearance_delay_ms_)); 310 bubble_appearance_delay_ms_));
309 } else { 311 } else {
310 // If the menu did not show up yet, we delay it even a bit more. 312 // If the menu did not show up yet, we delay it even a bit more.
311 maximizer_->DelayCreation(); 313 maximizer_->DelayCreation();
312 } 314 }
313 snap_sizer_.reset(NULL); 315 snap_sizer_.reset(NULL);
314 InstallEventFilter(); 316 InstallEventFilter();
315 snap_type_ = SNAP_NONE; 317 snap_type_ = SNAP_NONE;
316 press_location_ = event.location(); 318 press_location_ = event.location();
317 exceeded_drag_threshold_ = false; 319 exceeded_drag_threshold_ = false;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 if (maximizer_.get()) { 428 if (maximizer_.get()) {
427 phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); 429 phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow());
428 maximizer_->SetSnapType(snap_type_); 430 maximizer_->SetSnapType(snap_type_);
429 } 431 }
430 phantom_window_->Show( 432 phantom_window_->Show(
431 ScreenBoundsForType(snap_type_, *snap_sizer_.get()), NULL); 433 ScreenBoundsForType(snap_type_, *snap_sizer_.get()), NULL);
432 } 434 }
433 435
434 SnapType FrameMaximizeButton::SnapTypeForLocation( 436 SnapType FrameMaximizeButton::SnapTypeForLocation(
435 const gfx::Point& location) const { 437 const gfx::Point& location) const {
438 MaximizeBubbleFrameState maximize_type = GetMaximizeBubbleFrameState();
436 int delta_x = location.x() - press_location_.x(); 439 int delta_x = location.x() - press_location_.x();
437 int delta_y = location.y() - press_location_.y(); 440 int delta_y = location.y() - press_location_.y();
438 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) 441 if (!views::View::ExceededDragThreshold(delta_x, delta_y))
439 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; 442 return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE;
440 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) 443 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x)
441 return SNAP_LEFT; 444 return maximize_type == FRAME_STATE_SNAP_LEFT ? SNAP_RESTORE : SNAP_LEFT;
442 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) 445 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x)
443 return SNAP_RIGHT; 446 return maximize_type == FRAME_STATE_SNAP_RIGHT ? SNAP_RESTORE : SNAP_RIGHT;
444 else if (delta_y > 0) 447 else if (delta_y > 0)
445 return SNAP_MINIMIZE; 448 return SNAP_MINIMIZE;
446 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; 449 return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE;
447 } 450 }
448 451
449 gfx::Rect FrameMaximizeButton::ScreenBoundsForType( 452 gfx::Rect FrameMaximizeButton::ScreenBoundsForType(
450 SnapType type, 453 SnapType type,
451 const SnapSizer& snap_sizer) const { 454 const SnapSizer& snap_sizer) const {
452 aura::Window* window = frame_->GetWidget()->GetNativeWindow(); 455 aura::Window* window = frame_->GetWidget()->GetNativeWindow();
453 switch (type) { 456 switch (type) {
454 case SNAP_LEFT: 457 case SNAP_LEFT:
455 case SNAP_RIGHT: 458 case SNAP_RIGHT:
456 return ScreenAsh::ConvertRectToScreen( 459 return ScreenAsh::ConvertRectToScreen(
457 frame_->GetWidget()->GetNativeView()->parent(), 460 frame_->GetWidget()->GetNativeView()->parent(),
458 snap_sizer.target_bounds()); 461 snap_sizer.target_bounds());
459 case SNAP_MAXIMIZE: 462 case SNAP_MAXIMIZE:
460 return ScreenAsh::ConvertRectToScreen( 463 return ScreenAsh::ConvertRectToScreen(
461 window->parent(), 464 window->parent(),
462 ScreenAsh::GetMaximizedWindowBoundsInParent(window)); 465 ScreenAsh::GetMaximizedWindowBoundsInParent(window));
463 case SNAP_MINIMIZE: { 466 case SNAP_MINIMIZE: {
464 Launcher* launcher = Shell::GetInstance()->launcher(); 467 Launcher* launcher = Shell::GetInstance()->launcher();
465 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); 468 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(
469 window));
466 if (!item_rect.IsEmpty()) { 470 if (!item_rect.IsEmpty()) {
467 // PhantomWindowController insets slightly, outset it so the phantom 471 // PhantomWindowController insets slightly, outset it so the phantom
468 // doesn't appear inset. 472 // doesn't appear inset.
469 item_rect.Inset(-8, -8); 473 item_rect.Inset(-8, -8);
470 return item_rect; 474 return item_rect;
471 } 475 }
472 return launcher->widget()->GetWindowBoundsInScreen(); 476 return launcher->widget()->GetWindowBoundsInScreen();
473 } 477 }
474 case SNAP_RESTORE: { 478 case SNAP_RESTORE: {
475 const gfx::Rect* restore = GetRestoreBoundsInScreen(window); 479 const gfx::Rect* restore = GetRestoreBoundsInScreen(window);
476 return restore ? 480 return restore ?
477 *restore : frame_->GetWidget()->GetWindowBoundsInScreen(); 481 *restore : frame_->GetWidget()->GetWindowBoundsInScreen();
478 } 482 }
479 case SNAP_NONE: 483 case SNAP_NONE:
480 NOTREACHED(); 484 NOTREACHED();
481 } 485 }
482 return gfx::Rect(); 486 return gfx::Rect();
483 } 487 }
484 488
485 gfx::Point FrameMaximizeButton::LocationForSnapSizer( 489 gfx::Point FrameMaximizeButton::LocationForSnapSizer(
486 const gfx::Point& location) const { 490 const gfx::Point& location) const {
487 gfx::Point result(location); 491 gfx::Point result(location);
488 views::View::ConvertPointToScreen(this, &result); 492 views::View::ConvertPointToScreen(this, &result);
489 return result; 493 return result;
490 } 494 }
491 495
492 void FrameMaximizeButton::Snap(const SnapSizer& snap_sizer) { 496 void FrameMaximizeButton::Snap(const SnapSizer& snap_sizer) {
497 views::Widget* widget = frame_->GetWidget();
493 switch (snap_type_) { 498 switch (snap_type_) {
494 case SNAP_LEFT: 499 case SNAP_LEFT:
495 case SNAP_RIGHT: 500 case SNAP_RIGHT: {
496 if (frame_->GetWidget()->IsMaximized()) { 501 // Get the window coordinates on the screen for restore purposes.
497 ash::SetRestoreBoundsInScreen(frame_->GetWidget()->GetNativeWindow(), 502 gfx::Rect restore = widget->GetNativeWindow()->bounds();
503 if (widget->IsMaximized()) {
504 // In case of maximized we have a restore boundary.
505 DCHECK(ash::GetRestoreBoundsInScreen(widget->GetNativeWindow()));
506 // If it was maximized we need to recover the old restore set.
507 restore = *ash::GetRestoreBoundsInScreen(widget->GetNativeWindow());
508 // Set the restore size we want to restore to.
509 ash::SetRestoreBoundsInScreen(widget->GetNativeWindow(),
498 ScreenBoundsForType(snap_type_, 510 ScreenBoundsForType(snap_type_,
499 snap_sizer)); 511 snap_sizer));
500 frame_->GetWidget()->Restore(); 512 widget->Restore();
501 } else { 513 } else {
502 frame_->GetWidget()->SetBounds(ScreenBoundsForType(snap_type_, 514 // Others might also have set up a restore rectangle already. If so,
503 snap_sizer)); 515 // we should not overwrite the restore rectangle.
516 bool restore_set =
517 GetRestoreBoundsInScreen(widget->GetNativeWindow()) != NULL;
518 widget->SetBounds(ScreenBoundsForType(snap_type_, snap_sizer));
519 if (restore_set)
520 break;
521 }
522 // Remember the widow's bounds for restoration.
523 ash::SetRestoreBoundsInScreen(widget->GetNativeWindow(), restore);
504 } 524 }
505 break; 525 break;
506 case SNAP_MAXIMIZE: 526 case SNAP_MAXIMIZE:
507 frame_->GetWidget()->Maximize(); 527 widget->Maximize();
508 break; 528 break;
509 case SNAP_MINIMIZE: 529 case SNAP_MINIMIZE:
510 frame_->GetWidget()->Minimize(); 530 widget->Minimize();
511 break; 531 break;
512 case SNAP_RESTORE: 532 case SNAP_RESTORE:
513 frame_->GetWidget()->Restore(); 533 widget->Restore();
514 break; 534 break;
515 case SNAP_NONE: 535 case SNAP_NONE:
516 NOTREACHED(); 536 NOTREACHED();
517 } 537 }
518 } 538 }
519 539
540 MaximizeBubbleFrameState
541 FrameMaximizeButton::GetMaximizeBubbleFrameState() const {
542 // When there are no restore bounds, we are in normal mode.
543 if (!ash::GetRestoreBoundsInScreen(
544 frame_->GetWidget()->GetNativeWindow()))
545 return FRAME_STATE_NONE;
546 // The normal maximized test can be used.
547 if (frame_->GetWidget()->IsMaximized())
548 return FRAME_STATE_FULL;
549 // For Left/right maximize we need to check the dimensions.
550 gfx::Rect bounds = frame_->GetWidget()->GetWindowBoundsInScreen();
551 gfx::Rect screen = gfx::Screen::GetDisplayMatching(bounds).work_area();
552 if (bounds.width() < (screen.width() * kMinSnapSizePercent) / 100)
553 return FRAME_STATE_NONE;
554 // We have to be in a maximize mode at this point.
555 DCHECK(bounds.y() == screen.y());
556 DCHECK(bounds.height() >= screen.height());
557 if (bounds.x() == screen.x())
558 return FRAME_STATE_SNAP_LEFT;
559 if (bounds.right() == screen.right())
560 return FRAME_STATE_SNAP_RIGHT;
561 // If we come here, it is likely caused by the fact that the
562 // "VerticalResizeDoubleClick" stored a restore rectangle. In that case
563 // we allow all maximize operations (and keep the restore rectangle).
564 return FRAME_STATE_NONE;
565 }
566
520 } // namespace ash 567 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/workspace/frame_maximize_button.h ('k') | ash/wm/workspace/maximize_bubble_frame_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698