Chromium Code Reviews| 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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 } | 427 } |
| 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(ScreenBoundsForType(snap_type_, *snap_sizer_.get())); | 432 phantom_window_->Show(ScreenBoundsForType(snap_type_, *snap_sizer_.get())); |
| 431 } | 433 } |
| 432 | 434 |
| 433 SnapType FrameMaximizeButton::SnapTypeForLocation( | 435 SnapType FrameMaximizeButton::SnapTypeForLocation( |
| 434 const gfx::Point& location) const { | 436 const gfx::Point& location) const { |
| 437 MaximizeBubbleFrameState maximize_type = GetMaximizeBubbleFrameState(); | |
| 435 int delta_x = location.x() - press_location_.x(); | 438 int delta_x = location.x() - press_location_.x(); |
| 436 int delta_y = location.y() - press_location_.y(); | 439 int delta_y = location.y() - press_location_.y(); |
| 437 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) | 440 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) |
| 438 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; | 441 return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; |
| 439 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) | 442 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) |
| 440 return SNAP_LEFT; | 443 return maximize_type == FRAME_STATE_SNAP_LEFT ? SNAP_RESTORE : SNAP_LEFT; |
| 441 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) | 444 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) |
| 442 return SNAP_RIGHT; | 445 return maximize_type == FRAME_STATE_SNAP_RIGHT ? SNAP_RESTORE : SNAP_RIGHT; |
| 443 else if (delta_y > 0) | 446 else if (delta_y > 0) |
| 444 return SNAP_MINIMIZE; | 447 return SNAP_MINIMIZE; |
| 445 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; | 448 return maximize_type != FRAME_STATE_FULL ? SNAP_MAXIMIZE : SNAP_RESTORE; |
| 446 } | 449 } |
| 447 | 450 |
| 448 gfx::Rect FrameMaximizeButton::ScreenBoundsForType( | 451 gfx::Rect FrameMaximizeButton::ScreenBoundsForType( |
| 449 SnapType type, | 452 SnapType type, |
| 450 const SnapSizer& snap_sizer) const { | 453 const SnapSizer& snap_sizer) const { |
| 451 aura::Window* window = frame_->GetWidget()->GetNativeWindow(); | 454 aura::Window* window = frame_->GetWidget()->GetNativeWindow(); |
| 452 switch (type) { | 455 switch (type) { |
| 453 case SNAP_LEFT: | 456 case SNAP_LEFT: |
| 454 case SNAP_RIGHT: | 457 case SNAP_RIGHT: |
| 455 return ScreenAsh::ConvertRectToScreen( | 458 return ScreenAsh::ConvertRectToScreen( |
| 456 frame_->GetWidget()->GetNativeView()->parent(), | 459 frame_->GetWidget()->GetNativeView()->parent(), |
| 457 snap_sizer.target_bounds()); | 460 snap_sizer.target_bounds()); |
| 458 case SNAP_MAXIMIZE: | 461 case SNAP_MAXIMIZE: |
| 459 return ScreenAsh::ConvertRectToScreen( | 462 return ScreenAsh::ConvertRectToScreen( |
| 460 window->parent(), | 463 window->parent(), |
| 461 ScreenAsh::GetMaximizedWindowBoundsInParent(window)); | 464 ScreenAsh::GetMaximizedWindowBoundsInParent(window)); |
| 462 case SNAP_MINIMIZE: { | 465 case SNAP_MINIMIZE: { |
| 463 Launcher* launcher = Shell::GetInstance()->launcher(); | 466 Launcher* launcher = Shell::GetInstance()->launcher(); |
| 464 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); | 467 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow( |
| 468 window)); | |
| 465 if (!item_rect.IsEmpty()) { | 469 if (!item_rect.IsEmpty()) { |
| 466 // PhantomWindowController insets slightly, outset it so the phantom | 470 // PhantomWindowController insets slightly, outset it so the phantom |
| 467 // doesn't appear inset. | 471 // doesn't appear inset. |
| 468 item_rect.Inset(-8, -8); | 472 item_rect.Inset(-8, -8); |
| 469 return item_rect; | 473 return item_rect; |
| 470 } | 474 } |
| 471 return launcher->widget()->GetWindowBoundsInScreen(); | 475 return launcher->widget()->GetWindowBoundsInScreen(); |
| 472 } | 476 } |
| 473 case SNAP_RESTORE: { | 477 case SNAP_RESTORE: { |
| 474 const gfx::Rect* restore = GetRestoreBoundsInScreen(window); | 478 const gfx::Rect* restore = GetRestoreBoundsInScreen(window); |
| 475 return restore ? | 479 return restore ? |
| 476 *restore : frame_->GetWidget()->GetWindowBoundsInScreen(); | 480 *restore : frame_->GetWidget()->GetWindowBoundsInScreen(); |
| 477 } | 481 } |
| 478 case SNAP_NONE: | 482 case SNAP_NONE: |
| 479 NOTREACHED(); | 483 NOTREACHED(); |
| 480 } | 484 } |
| 481 return gfx::Rect(); | 485 return gfx::Rect(); |
| 482 } | 486 } |
| 483 | 487 |
| 484 gfx::Point FrameMaximizeButton::LocationForSnapSizer( | 488 gfx::Point FrameMaximizeButton::LocationForSnapSizer( |
| 485 const gfx::Point& location) const { | 489 const gfx::Point& location) const { |
| 486 gfx::Point result(location); | 490 gfx::Point result(location); |
| 487 views::View::ConvertPointToScreen(this, &result); | 491 views::View::ConvertPointToScreen(this, &result); |
| 488 return result; | 492 return result; |
| 489 } | 493 } |
| 490 | 494 |
| 491 void FrameMaximizeButton::Snap(const SnapSizer& snap_sizer) { | 495 void FrameMaximizeButton::Snap(const SnapSizer& snap_sizer) { |
| 496 views::Widget* widget = frame_->GetWidget(); | |
| 492 switch (snap_type_) { | 497 switch (snap_type_) { |
| 493 case SNAP_LEFT: | 498 case SNAP_LEFT: |
| 494 case SNAP_RIGHT: | 499 case SNAP_RIGHT: { |
| 495 if (frame_->GetWidget()->IsMaximized()) { | 500 // Get the window coordinates on the screen for restore purposes. |
| 496 ash::SetRestoreBoundsInScreen(frame_->GetWidget()->GetNativeWindow(), | 501 gfx::Rect restore = widget->GetNativeWindow()->bounds(); |
| 502 if (widget->IsMaximized()) { | |
| 503 // If it was maximized we need to recover the old restore set. | |
| 504 restore = *ash::GetRestoreBoundsInScreen(widget->GetNativeWindow()); | |
|
sky
2012/08/29 17:29:20
This will crash if GetRestoreBoundsInScreen return
Mr4D (OOO till 08-26)
2012/08/29 18:57:34
I thought that in maximized mode the restore recta
sky
2012/08/29 21:08:50
A DCHECK is the right thing. It says you expect th
| |
| 505 // Set the restore size we want to restore to. | |
| 506 ash::SetRestoreBoundsInScreen(widget->GetNativeWindow(), | |
|
sky
2012/08/29 17:29:20
Why do you need to set the restore bounds here as
Mr4D (OOO till 08-26)
2012/08/29 18:57:34
This is from the original code: We need to exit ma
| |
| 497 ScreenBoundsForType(snap_type_, | 507 ScreenBoundsForType(snap_type_, |
| 498 snap_sizer)); | 508 snap_sizer)); |
| 499 frame_->GetWidget()->Restore(); | 509 widget->Restore(); |
|
sky
2012/08/29 17:29:20
Gah. Looking at this whole branch it seems wrong.
Mr4D (OOO till 08-26)
2012/08/29 18:57:34
This code predates my doing and was only taken ove
sky
2012/08/29 21:08:50
Good point.
| |
| 500 } else { | 510 } else { |
| 501 frame_->GetWidget()->SetBounds(ScreenBoundsForType(snap_type_, | 511 widget->SetBounds(ScreenBoundsForType(snap_type_, snap_sizer)); |
| 502 snap_sizer)); | 512 } |
| 513 // Remember the widow's bounds for restoration. | |
| 514 ash::SetRestoreBoundsInScreen(widget->GetNativeWindow(), restore); | |
| 503 } | 515 } |
| 504 break; | 516 break; |
| 505 case SNAP_MAXIMIZE: | 517 case SNAP_MAXIMIZE: |
| 506 frame_->GetWidget()->Maximize(); | 518 widget->Maximize(); |
| 507 break; | 519 break; |
| 508 case SNAP_MINIMIZE: | 520 case SNAP_MINIMIZE: |
| 509 frame_->GetWidget()->Minimize(); | 521 widget->Minimize(); |
| 510 break; | 522 break; |
| 511 case SNAP_RESTORE: | 523 case SNAP_RESTORE: |
| 512 frame_->GetWidget()->Restore(); | 524 widget->Restore(); |
| 513 break; | 525 break; |
| 514 case SNAP_NONE: | 526 case SNAP_NONE: |
| 515 NOTREACHED(); | 527 NOTREACHED(); |
| 516 } | 528 } |
| 517 } | 529 } |
| 518 | 530 |
| 531 MaximizeBubbleFrameState FrameMaximizeButton::GetMaximizeBubbleFrameState( | |
| 532 ) const { | |
|
sky
2012/08/29 17:29:20
Wrap FMB::GetMa.. to the next line, eg:
MaximizeBu
Mr4D (OOO till 08-26)
2012/08/29 18:57:34
Done.
| |
| 533 // When there are no restore bounds, we are in normal mode. | |
| 534 if (!ash::GetRestoreBoundsInScreen( | |
| 535 frame_->GetWidget()->GetNativeWindow())) | |
| 536 return FRAME_STATE_NONE; | |
| 537 // The normal maximized test can be used. | |
| 538 if (frame_->GetWidget()->IsMaximized()) | |
| 539 return FRAME_STATE_FULL; | |
| 540 // For Left/right maximize we need to check the dimensions. | |
| 541 gfx::Rect bounds = frame_->GetWidget()->GetWindowBoundsInScreen(); | |
| 542 gfx::Rect screen = gfx::Screen::GetDisplayMatching(bounds).work_area(); | |
| 543 if (bounds.width() < (screen.width() * kMinSnapSizePercent) / 100) | |
| 544 return FRAME_STATE_NONE; | |
| 545 // We have to be in a maximize mode at this point. | |
| 546 DCHECK(bounds.y() == screen.y()); | |
| 547 DCHECK(bounds.height() >= screen.height()); | |
| 548 if (bounds.x() == screen.x()) | |
| 549 return FRAME_STATE_SNAP_LEFT; | |
| 550 if (bounds.right() == screen.right()) | |
| 551 return FRAME_STATE_SNAP_RIGHT; | |
| 552 NOTREACHED(); | |
|
sky
2012/08/29 17:29:20
Won't you hit this if you resize the window horizo
Mr4D (OOO till 08-26)
2012/08/29 18:57:34
This state is still ominous to me and contradicts
| |
| 553 return FRAME_STATE_NONE; | |
| 554 } | |
| 555 | |
| 519 } // namespace ash | 556 } // namespace ash |
| OLD | NEW |