| 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()) {
|
| + window_ = parent()->GetWidget()->GetNativeWindow();
|
| + window_->AddObserver(this);
|
| + }
|
| + maximizer_.reset(new MaximizeBubbleController(
|
| + this,
|
| + frame_->GetWidget()->IsMaximized()));
|
| + }
|
| }
|
|
|
| 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)) {
|
| + 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();
|
| + 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();
|
| }
|
| }
|
|
|