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

Unified Diff: ash/wm/workspace/frame_maximize_button.cc

Issue 10823025: Adding new maximize menu according to spec (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Adding mouse watcher Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
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();
}
}

Powered by Google App Engine
This is Rietveld 408576698