Chromium Code Reviews| Index: ash/wm/workspace/frame_maximize_button.cc |
| diff --git a/ash/wm/workspace/frame_maximize_button.cc b/ash/wm/workspace/frame_maximize_button.cc |
| index 213f4d21228762557d251138335c7d1dfec32277..152f525c6b1f3b49f9bb8d138de17062b6cd7601 100644 |
| --- a/ash/wm/workspace/frame_maximize_button.cc |
| +++ b/ash/wm/workspace/frame_maximize_button.cc |
| @@ -8,6 +8,7 @@ |
| #include "ash/screen_ash.h" |
| #include "ash/shell.h" |
| #include "ash/wm/property_util.h" |
| +#include "ash/wm/maximize_bubble_controller.h" |
| #include "ash/wm/workspace/phantom_window_controller.h" |
| #include "ash/wm/workspace/snap_sizer.h" |
| #include "grit/ash_strings.h" |
| @@ -74,7 +75,7 @@ bool FrameMaximizeButton::EscapeEventFilter::PreHandleKeyEvent( |
| aura::KeyEvent* event) { |
| if (event->type() == ui::ET_KEY_PRESSED && |
| event->key_code() == ui::VKEY_ESCAPE) { |
| - button_->Cancel(); |
| + button_->Cancel(false); |
| } |
| return false; |
| } |
| @@ -105,15 +106,31 @@ FrameMaximizeButton::FrameMaximizeButton(views::ButtonListener* listener, |
| frame_(frame), |
| is_snap_enabled_(false), |
| exceeded_drag_threshold_(false), |
| - snap_type_(SNAP_NONE) { |
| + window_(NULL), |
| + snap_type_(workspace::SNAP_NONE) { |
| // TODO(sky): nuke this. It's temporary while we don't have good images. |
| SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM); |
| - SetTooltipText(l10n_util::GetStringUTF16(IDS_FRAME_MAXIMIZE_BUTTON_TOOLTIP)); |
| } |
| FrameMaximizeButton::~FrameMaximizeButton() { |
| } |
| +void FrameMaximizeButton::OnWindowBoundsChanged( |
| + aura::Window* window, |
| + const gfx::Rect& old_bounds, |
| + const gfx::Rect& new_bounds) { |
| + Cancel(false); |
| +} |
| + |
| +void FrameMaximizeButton::OnWindowDestroying(aura::Window* window) { |
| + maximizer_.reset(); |
| + if (window_) { |
| + CHECK_EQ(window_, window); |
| + window_->RemoveObserver(this); |
| + window_ = NULL; |
| + } |
| +} |
| + |
| bool FrameMaximizeButton::OnMousePressed(const views::MouseEvent& event) { |
| is_snap_enabled_ = event.IsLeftMouseButton(); |
| if (is_snap_enabled_) |
| @@ -124,10 +141,30 @@ bool FrameMaximizeButton::OnMousePressed(const views::MouseEvent& event) { |
| void FrameMaximizeButton::OnMouseEntered(const views::MouseEvent& event) { |
| ImageButton::OnMouseEntered(event); |
| + if (!maximizer_.get()) { |
| + DCHECK(parent()->GetWidget()); |
| + if (!window_ && parent()) { |
|
sky
2012/08/03 19:42:00
remove parent() here
Mr4D (OOO till 08-26)
2012/08/03 20:39:28
Okay. I don't quite get this. Why is the widget of
sky
2012/08/03 23:10:17
That's how the hierarchy is set up. Most views sha
|
| + window_ = parent()->GetWidget()->GetNativeWindow(); |
|
sky
2012/08/03 19:42:00
remove parent() here
Mr4D (OOO till 08-26)
2012/08/03 20:39:28
Done.
|
| + window_->AddObserver(this); |
| + } |
| + maximizer_.reset(new MaximizeBubbleController( |
| + this, |
| + frame_->GetWidget()->IsMaximized())); |
|
sky
2012/08/03 19:42:00
remove frame_ here
Mr4D (OOO till 08-26)
2012/08/03 20:39:28
Fascinating. How is it possible that the widget of
|
| + } |
| } |
| void FrameMaximizeButton::OnMouseExited(const views::MouseEvent& event) { |
| ImageButton::OnMouseExited(event); |
| + // Remove the bubble menu when the button is not pressed and the mouse is not |
| + // within the bubble. |
| + if (!is_snap_enabled_ && maximizer_.get() && maximizer_->GetBubbleWindow()) { |
| + gfx::Point screen_location = gfx::Screen::GetCursorScreenPoint(); |
| + if (!maximizer_->GetBubbleWindow()->bounds().Contains(screen_location)) { |
|
sky
2012/08/03 19:42:00
bounds() is not necessarily in the same coordinate
Mr4D (OOO till 08-26)
2012/08/03 20:39:28
The Bubble window is a top level window and the co
sky
2012/08/03 23:10:17
toplevel window and screen coordinates are two dif
|
| + maximizer_.reset(); |
| + // Make sure that all remaining snap hover states get removed. |
| + SnapButtonHovered(workspace::SNAP_NONE); |
| + } |
| + } |
| } |
| bool FrameMaximizeButton::OnMouseDragged(const views::MouseEvent& event) { |
| @@ -139,10 +176,11 @@ bool FrameMaximizeButton::OnMouseDragged(const views::MouseEvent& event) { |
| void FrameMaximizeButton::OnMouseReleased(const views::MouseEvent& event) { |
| if (!ProcessEndEvent(event)) |
| ImageButton::OnMouseReleased(event); |
| + maximizer_.reset(); |
| } |
| void FrameMaximizeButton::OnMouseCaptureLost() { |
| - Cancel(); |
| + Cancel(false); |
| ImageButton::OnMouseCaptureLost(); |
| } |
| @@ -180,59 +218,68 @@ ui::GestureStatus FrameMaximizeButton::OnGestureEvent( |
| return ImageButton::OnGestureEvent(event); |
| } |
| -gfx::ImageSkia FrameMaximizeButton::GetImageToPaint() { |
| - if (is_snap_enabled_) { |
| - int id = 0; |
| - if (frame_->GetWidget()->IsMaximized()) { |
| - switch (snap_type_) { |
| - case SNAP_LEFT: |
| - id = IDR_AURA_WINDOW_MAXIMIZED_SNAP_LEFT_P; |
| - break; |
| - case SNAP_RIGHT: |
| - id = IDR_AURA_WINDOW_MAXIMIZED_SNAP_RIGHT_P; |
| - break; |
| - case SNAP_MAXIMIZE: |
| - case SNAP_RESTORE: |
| - case SNAP_NONE: |
| - id = IDR_AURA_WINDOW_MAXIMIZED_SNAP_P; |
| - break; |
| - case SNAP_MINIMIZE: |
| - id = IDR_AURA_WINDOW_MAXIMIZED_SNAP_MINIMIZE_P; |
| - break; |
| - default: |
| - NOTREACHED(); |
| - } |
| - } else { |
| - switch (snap_type_) { |
| - case SNAP_LEFT: |
| - id = IDR_AURA_WINDOW_SNAP_LEFT_P; |
| - break; |
| - case SNAP_RIGHT: |
| - id = IDR_AURA_WINDOW_SNAP_RIGHT_P; |
| - break; |
| - case SNAP_MAXIMIZE: |
| - case SNAP_RESTORE: |
| - case SNAP_NONE: |
| - id = IDR_AURA_WINDOW_SNAP_P; |
| - break; |
| - case SNAP_MINIMIZE: |
| - id = IDR_AURA_WINDOW_SNAP_MINIMIZE_P; |
| - break; |
| - default: |
| - NOTREACHED(); |
| - } |
| - } |
| - return *ResourceBundle::GetSharedInstance().GetImageNamed(id).ToImageSkia(); |
| +void FrameMaximizeButton::SnapButtonHovered(workspace::SnapType type) { |
| + // Make sure to only show hover operations when no button is pressed and |
| + // a similar snap operation in progress does not get re-applied. |
| + if (is_snap_enabled_ || (type == snap_type_ && snap_sizer_.get())) |
| + return; |
| + // Prime the mouse location with the center of the (local) button. |
| + press_location_ = gfx::Point(width() / 2, height() / 2); |
| + // Then get an adjusted mouse position to initiate the effect. |
| + gfx::Point location = press_location_; |
| + switch (type) { |
| + case workspace::SNAP_LEFT: |
| + location.set_x(location.x() - width()); |
| + break; |
| + case workspace::SNAP_RIGHT: |
| + location.set_x(location.x() + width()); |
| + break; |
| + case workspace::SNAP_MINIMIZE: |
| + location.set_y(location.y() + height()); |
| + break; |
| + case workspace::SNAP_MAXIMIZE: |
| + case workspace::SNAP_RESTORE: |
| + break; |
| + case workspace::SNAP_NONE: |
| + Cancel(true); |
| + return; |
| + default: |
| + // We should not come here. |
| + NOTREACHED(); |
| } |
| - // Hot and pressed states handled by regular ImageButton. |
| - return ImageButton::GetImageToPaint(); |
| + UpdateSnap(location); |
| +} |
| + |
| +void FrameMaximizeButton::ExecuteSnapAndCloseMenu( |
| + workspace::SnapType snap_type) { |
| + DCHECK_NE(snap_type_, workspace::SNAP_NONE); |
| + snap_type_ = snap_type; |
| + Snap(); |
| + // Remove any pending snap previews. |
| + SnapButtonHovered(workspace::SNAP_NONE); |
| + // At this point the operation has been performed and the menu should be |
| + // closed - if not, it'll get now closed. |
| + maximizer_.reset(); |
| +} |
| + |
| +void FrameMaximizeButton::DestroyMaximizeMenu() { |
| + maximizer_.reset(); |
| } |
| void FrameMaximizeButton::ProcessStartEvent(const views::LocatedEvent& event) { |
| DCHECK(is_snap_enabled_); |
| + // Prepare the help menu. |
| + if (!maximizer_.get()) { |
| + maximizer_.reset(new MaximizeBubbleController( |
| + this, |
| + frame_->GetWidget()->IsMaximized())); |
| + } else { |
| + // If the menu did not show up yet, we delay it even a bit more. |
| + maximizer_->DelayCreation(); |
| + } |
| snap_sizer_.reset(NULL); |
| InstallEventFilter(); |
| - snap_type_ = SNAP_NONE; |
| + snap_type_ = workspace::SNAP_NONE; |
| press_location_ = event.location(); |
| exceeded_drag_threshold_ = false; |
| update_timer_.Start( |
| @@ -260,7 +307,12 @@ bool FrameMaximizeButton::ProcessEndEvent(const views::LocatedEvent& event) { |
| bool should_snap = is_snap_enabled_; |
| is_snap_enabled_ = false; |
| - if (!should_snap || snap_type_ == SNAP_NONE) |
| + // Remove our help menu if the mouse cursor is not still over it. |
| + gfx::Point screen_location = gfx::Screen::GetCursorScreenPoint(); |
|
sky
2012/08/03 19:42:00
ProcessEndEvent may be invoked from a gesture even
Mr4D (OOO till 08-26)
2012/08/03 20:39:28
As said in your earlier review: The idea is to kee
sky
2012/08/03 20:43:08
We hide the mouse cursor when you touch, so it doe
Mr4D (OOO till 08-26)
2012/08/03 20:47:31
I suppose it is either way confusing. Okay, will d
|
| + if (!GetBoundsInScreen().Contains(screen_location)) |
| + maximizer_.reset(); |
| + |
| + if (!should_snap || snap_type_ == workspace::SNAP_NONE) |
| return false; |
| SetState(BS_NORMAL); |
| @@ -272,11 +324,15 @@ bool FrameMaximizeButton::ProcessEndEvent(const views::LocatedEvent& event) { |
| return true; |
| } |
| -void FrameMaximizeButton::Cancel() { |
| - UninstallEventFilter(); |
| - is_snap_enabled_ = false; |
| +void FrameMaximizeButton::Cancel(bool keep_menu_open) { |
| + if (!keep_menu_open) { |
| + maximizer_.reset(); |
| + UninstallEventFilter(); |
| + is_snap_enabled_ = false; |
| + } |
| phantom_window_.reset(); |
| snap_sizer_.reset(); |
| + snap_type_ = workspace::SNAP_NONE; |
| update_timer_.Stop(); |
| SchedulePaint(); |
| } |
| @@ -301,7 +357,7 @@ void FrameMaximizeButton::UpdateSnapFromEventLocation() { |
| } |
| void FrameMaximizeButton::UpdateSnap(const gfx::Point& location) { |
| - SnapType type = SnapTypeForLocation(location); |
| + workspace::SnapType type = SnapTypeForLocation(location); |
| if (type == snap_type_) { |
| if (snap_sizer_.get()) { |
| snap_sizer_->Update(LocationForSnapSizer(location)); |
| @@ -316,13 +372,14 @@ void FrameMaximizeButton::UpdateSnap(const gfx::Point& location) { |
| snap_sizer_.reset(); |
| SchedulePaint(); |
| - if (snap_type_ == SNAP_NONE) { |
| + if (snap_type_ == workspace::SNAP_NONE) { |
| phantom_window_.reset(); |
| return; |
| } |
| - if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { |
| - SnapSizer::Edge snap_edge = snap_type_ == SNAP_LEFT ? |
| + if (snap_type_ == workspace::SNAP_LEFT || |
| + snap_type_ == workspace::SNAP_RIGHT) { |
| + SnapSizer::Edge snap_edge = snap_type_ == workspace::SNAP_LEFT ? |
| SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| int grid_size = Shell::GetInstance()->GetGridSize(); |
| snap_sizer_.reset(new SnapSizer(frame_->GetWidget()->GetNativeWindow(), |
| @@ -333,37 +390,44 @@ void FrameMaximizeButton::UpdateSnap(const gfx::Point& location) { |
| phantom_window_.reset(new internal::PhantomWindowController( |
| frame_->GetWidget()->GetNativeWindow())); |
| } |
| + if (maximizer_.get()) { |
| + phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); |
| + maximizer_->SetSnapType(snap_type_); |
| + } |
| phantom_window_->Show(ScreenBoundsForType(snap_type_)); |
| } |
| -FrameMaximizeButton::SnapType FrameMaximizeButton::SnapTypeForLocation( |
| +workspace::SnapType FrameMaximizeButton::SnapTypeForLocation( |
| const gfx::Point& location) const { |
| int delta_x = location.x() - press_location_.x(); |
| int delta_y = location.y() - press_location_.y(); |
| if (!views::View::ExceededDragThreshold(delta_x, delta_y)) |
| - return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; |
| + return !frame_->GetWidget()->IsMaximized() ? workspace::SNAP_MAXIMIZE : |
| + workspace::SNAP_RESTORE; |
| else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) |
| - return SNAP_LEFT; |
| + return workspace::SNAP_LEFT; |
| else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) |
| - return SNAP_RIGHT; |
| + return workspace::SNAP_RIGHT; |
| else if (delta_y > 0) |
| - return SNAP_MINIMIZE; |
| - return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; |
| + return workspace::SNAP_MINIMIZE; |
| + return !frame_->GetWidget()->IsMaximized() ? workspace::SNAP_MAXIMIZE : |
| + workspace::SNAP_RESTORE; |
| } |
| -gfx::Rect FrameMaximizeButton::ScreenBoundsForType(SnapType type) const { |
| +gfx::Rect FrameMaximizeButton::ScreenBoundsForType( |
| + workspace::SnapType type) const { |
| aura::Window* window = frame_->GetWidget()->GetNativeWindow(); |
| switch (type) { |
| - case SNAP_LEFT: |
| - case SNAP_RIGHT: |
| + case workspace::SNAP_LEFT: |
| + case workspace::SNAP_RIGHT: |
| return ScreenAsh::ConvertRectToScreen( |
| frame_->GetWidget()->GetNativeView()->parent(), |
| snap_sizer_->target_bounds()); |
| - case SNAP_MAXIMIZE: |
| + case workspace::SNAP_MAXIMIZE: |
| return ScreenAsh::ConvertRectToScreen( |
| window->parent(), |
| ScreenAsh::GetMaximizedWindowBoundsInParent(window)); |
| - case SNAP_MINIMIZE: { |
| + case workspace::SNAP_MINIMIZE: { |
| Launcher* launcher = Shell::GetInstance()->launcher(); |
| gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); |
| if (!item_rect.IsEmpty()) { |
| @@ -374,12 +438,12 @@ gfx::Rect FrameMaximizeButton::ScreenBoundsForType(SnapType type) const { |
| } |
| return launcher->widget()->GetWindowBoundsInScreen(); |
| } |
| - case SNAP_RESTORE: { |
| + case workspace::SNAP_RESTORE: { |
| const gfx::Rect* restore = GetRestoreBoundsInScreen(window); |
| return restore ? |
| *restore : frame_->GetWidget()->GetWindowBoundsInScreen(); |
| } |
| - case SNAP_NONE: |
| + case workspace::SNAP_NONE: |
| NOTREACHED(); |
| } |
| return gfx::Rect(); |
| @@ -394,8 +458,8 @@ gfx::Point FrameMaximizeButton::LocationForSnapSizer( |
| void FrameMaximizeButton::Snap() { |
| switch (snap_type_) { |
| - case SNAP_LEFT: |
| - case SNAP_RIGHT: |
| + case workspace::SNAP_LEFT: |
| + case workspace::SNAP_RIGHT: |
| if (frame_->GetWidget()->IsMaximized()) { |
| ash::SetRestoreBoundsInScreen(frame_->GetWidget()->GetNativeWindow(), |
| ScreenBoundsForType(snap_type_)); |
| @@ -404,16 +468,16 @@ void FrameMaximizeButton::Snap() { |
| frame_->GetWidget()->SetBounds(ScreenBoundsForType(snap_type_)); |
| } |
| break; |
| - case SNAP_MAXIMIZE: |
| + case workspace::SNAP_MAXIMIZE: |
| frame_->GetWidget()->Maximize(); |
| break; |
| - case SNAP_MINIMIZE: |
| + case workspace::SNAP_MINIMIZE: |
| frame_->GetWidget()->Minimize(); |
| break; |
| - case SNAP_RESTORE: |
| + case workspace::SNAP_RESTORE: |
| frame_->GetWidget()->Restore(); |
| break; |
| - case SNAP_NONE: |
| + case workspace::SNAP_NONE: |
| NOTREACHED(); |
| } |
| } |