summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorskuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-14 23:33:43 +0000
committerskuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-14 23:33:43 +0000
commit145d67fc623f958ff07b1f40e9208ba8f0757b0a (patch)
tree41bde91b870b7bf2d81d2322c758632fc28b1478 /ash
parent708d0cce7d55778a3527c6c6ea60ebaac1d6ec10 (diff)
downloadchromium_src-145d67fc623f958ff07b1f40e9208ba8f0757b0a.zip
chromium_src-145d67fc623f958ff07b1f40e9208ba8f0757b0a.tar.gz
chromium_src-145d67fc623f958ff07b1f40e9208ba8f0757b0a.tar.bz2
Adding unit tests for maximize menu
BUG=141635 TEST=Unittest Review URL: https://chromiumcodereview.appspot.com/10825327 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@151604 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/wm/custom_frame_view_ash.h5
-rw-r--r--ash/wm/custom_frame_view_ash_unittest.cc116
-rw-r--r--ash/wm/maximize_bubble_controller.cc97
-rw-r--r--ash/wm/maximize_bubble_controller.h18
-rw-r--r--ash/wm/workspace/frame_maximize_button.cc12
-rw-r--r--ash/wm/workspace/frame_maximize_button.h14
6 files changed, 242 insertions, 20 deletions
diff --git a/ash/wm/custom_frame_view_ash.h b/ash/wm/custom_frame_view_ash.h
index c875874..b65a9a1 100644
--- a/ash/wm/custom_frame_view_ash.h
+++ b/ash/wm/custom_frame_view_ash.h
@@ -12,6 +12,7 @@
namespace ash {
class FramePainter;
+class FrameMaximizeButton;
}
namespace gfx {
class Font;
@@ -40,7 +41,7 @@ class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView,
explicit TestApi(CustomFrameViewAsh* frame) : frame_(frame) {
}
- views::ImageButton* maximize_button() const {
+ ash::FrameMaximizeButton* maximize_button() const {
return frame_->maximize_button_;
}
@@ -81,7 +82,7 @@ class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView,
// Not owned.
views::Widget* frame_;
- views::ImageButton* maximize_button_;
+ ash::FrameMaximizeButton* maximize_button_;
views::ImageButton* close_button_;
views::ImageButton* window_icon_;
diff --git a/ash/wm/custom_frame_view_ash_unittest.cc b/ash/wm/custom_frame_view_ash_unittest.cc
index ebdc946..ae1d946 100644
--- a/ash/wm/custom_frame_view_ash_unittest.cc
+++ b/ash/wm/custom_frame_view_ash_unittest.cc
@@ -6,7 +6,9 @@
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
+#include "ash/wm/maximize_bubble_controller.h"
#include "ash/wm/window_util.h"
+#include "ash/wm/workspace/frame_maximize_button.h"
#include "ash/wm/workspace/snap_sizer.h"
#include "base/command_line.h"
#include "ui/aura/aura_switches.h"
@@ -255,5 +257,119 @@ TEST_F(CustomFrameViewAshTest, ResizeButtonDrag) {
widget->Close();
}
+// Test that closing the (browser) window with an opened balloon does not
+// crash the system. In other words: Make sure that shutting down the frame
+// destroys the opened balloon in an orderly fashion.
+TEST_F(CustomFrameViewAshTest, MaximizeButtonExternalShutDown) {
+ views::Widget* widget = CreateWidget();
+ aura::Window* window = widget->GetNativeWindow();
+ CustomFrameViewAsh* frame = custom_frame_view_ash(widget);
+ CustomFrameViewAsh::TestApi test(frame);
+ ash::FrameMaximizeButton* maximize_button = test.maximize_button();
+ maximize_button->set_bubble_appearance_delay_ms(0);
+ gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
+ gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
+
+ aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
+ EXPECT_FALSE(maximize_button->maximizer());
+ EXPECT_TRUE(ash::wm::IsWindowNormal(window));
+
+ // Move the mouse cursor over the button to bring up the maximizer bubble.
+ generator.MoveMouseTo(button_pos);
+ EXPECT_TRUE(maximize_button->maximizer());
+
+ // Even though the widget is closing the bubble menu should not crash upon
+ // its delayed destruction.
+ widget->CloseNow();
+}
+
+// Test that hovering over a button in the balloon dialog will show the phantom
+// window. Moving then away from the button will hide it again. Then check that
+// pressing and dragging the button itself off the button will also release the
+// phantom window.
+TEST_F(CustomFrameViewAshTest, MaximizeLeftButtonDragOut) {
+ views::Widget* widget = CreateWidget();
+ aura::Window* window = widget->GetNativeWindow();
+ CustomFrameViewAsh* frame = custom_frame_view_ash(widget);
+ CustomFrameViewAsh::TestApi test(frame);
+ ash::FrameMaximizeButton* maximize_button = test.maximize_button();
+ maximize_button->set_bubble_appearance_delay_ms(0);
+ gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
+ gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
+
+ aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
+ EXPECT_FALSE(maximize_button->maximizer());
+ EXPECT_TRUE(ash::wm::IsWindowNormal(window));
+ EXPECT_FALSE(maximize_button->phantom_window_open());
+
+ // Move the mouse cursor over the button to bring up the maximizer bubble.
+ generator.MoveMouseTo(button_pos);
+ EXPECT_TRUE(maximize_button->maximizer());
+
+ // Move the mouse over the left maximize button.
+ gfx::Point left_max_pos = maximize_button->maximizer()->
+ GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint();
+
+ generator.MoveMouseTo(left_max_pos);
+ // Expect the phantom window to be open.
+ EXPECT_TRUE(maximize_button->phantom_window_open());
+
+ // Move away to see the window being destroyed.
+ generator.MoveMouseTo(off_pos);
+ EXPECT_FALSE(maximize_button->phantom_window_open());
+
+ // Move back over the button.
+ generator.MoveMouseTo(button_pos);
+ generator.MoveMouseTo(left_max_pos);
+ EXPECT_TRUE(maximize_button->phantom_window_open());
+
+ // Press button and drag out of dialog.
+ generator.PressLeftButton();
+ generator.MoveMouseTo(off_pos);
+ generator.ReleaseLeftButton();
+
+ // Check that the phantom window is also gone.
+ EXPECT_FALSE(maximize_button->phantom_window_open());
+}
+
+// Test that clicking a button in the maximizer bubble (in this case the
+// maximize left button) will do the requested action.
+TEST_F(CustomFrameViewAshTest, MaximizeLeftByButton) {
+ const int kGridSize = ash::Shell::GetInstance()->GetGridSize();
+ views::Widget* widget = CreateWidget();
+ aura::Window* window = widget->GetNativeWindow();
+ CustomFrameViewAsh* frame = custom_frame_view_ash(widget);
+ CustomFrameViewAsh::TestApi test(frame);
+ ash::FrameMaximizeButton* maximize_button = test.maximize_button();
+ maximize_button->set_bubble_appearance_delay_ms(0);
+ gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint();
+ gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100);
+
+ aura::test::EventGenerator generator(window->GetRootWindow(), off_pos);
+ EXPECT_FALSE(maximize_button->maximizer());
+ EXPECT_TRUE(ash::wm::IsWindowNormal(window));
+ EXPECT_FALSE(maximize_button->phantom_window_open());
+
+ // Move the mouse cursor over the button to bring up the maximizer bubble.
+ generator.MoveMouseTo(button_pos);
+ EXPECT_TRUE(maximize_button->maximizer());
+
+ // Move the mouse over the left maximize button.
+ gfx::Point left_max_pos = maximize_button->maximizer()->
+ GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint();
+ generator.MoveMouseTo(left_max_pos);
+ EXPECT_TRUE(maximize_button->phantom_window_open());
+ generator.ClickLeftButton();
+
+ EXPECT_FALSE(maximize_button->maximizer());
+ EXPECT_FALSE(maximize_button->phantom_window_open());
+
+ EXPECT_FALSE(ash::wm::IsWindowMaximized(window));
+ EXPECT_FALSE(ash::wm::IsWindowMinimized(window));
+ internal::SnapSizer sizer(window, button_pos,
+ internal::SnapSizer::LEFT_EDGE, kGridSize);
+ EXPECT_EQ(sizer.target_bounds().ToString(), window->bounds().ToString());
+}
+
} // namespace internal
} // namespace ash
diff --git a/ash/wm/maximize_bubble_controller.cc b/ash/wm/maximize_bubble_controller.cc
index 98fa63d..4fa2e91 100644
--- a/ash/wm/maximize_bubble_controller.cc
+++ b/ash/wm/maximize_bubble_controller.cc
@@ -50,9 +50,6 @@ const int kLabelSpacing = 4;
const int kArrowHeight = 10;
const int kArrowWidth = 20;
-// The delay of the bubble appearance.
-const int kBubbleAppearanceDelayMS = 200;
-
// The animation offset in y for the bubble when appearing.
const int kBubbleAnimationOffsetY = 5;
@@ -217,7 +214,7 @@ class BubbleMouseWatcherHost: public views::MouseWatcherHost {
class MaximizeBubbleController::Bubble : public views::BubbleDelegateView,
public views::MouseWatcherListener {
public:
- explicit Bubble(MaximizeBubbleController* owner);
+ explicit Bubble(MaximizeBubbleController* owner, int appearance_delay_ms_);
virtual ~Bubble() {}
// The window of the menu under which the SnapSizer will get created.
@@ -256,6 +253,10 @@ class MaximizeBubbleController::Bubble : public views::BubbleDelegateView,
// of an asynchronous shutdown.
MaximizeBubbleController* controller() const { return owner_; }
+ // Added for unit test: Retrieve the button for an action.
+ // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE.
+ views::CustomButton* GetButtonForUnitTest(SnapType state);
+
private:
// True if the shut down has been initiated.
bool shutting_down_;
@@ -278,6 +279,9 @@ class MaximizeBubbleController::Bubble : public views::BubbleDelegateView,
// The mouse watcher which takes care of out of window hover events.
scoped_ptr<views::MouseWatcher> mouse_watcher_;
+ // The fade delay - if 0 it will show / hide immediately.
+ const int appearance_delay_ms_;
+
DISALLOW_COPY_AND_ASSIGN(Bubble);
};
@@ -295,6 +299,12 @@ class BubbleContentsButtonRow : public views::View,
// Called from BubbleDialogButton.
void ButtonHovered(BubbleDialogButton* sender);
+ // Added for unit test: Retrieve the button for an action.
+ // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE.
+ views::CustomButton* GetButtonForUnitTest(SnapType state);
+
+ MaximizeBubbleController::Bubble* bubble() { return bubble_; }
+
private:
// The owning object which gets notifications.
MaximizeBubbleController::Bubble* bubble_;
@@ -319,6 +329,12 @@ class BubbleContentsView : public views::View {
// through hover operations.
void SetSnapType(SnapType snap_type);
+ // Added for unit test: Retrieve the button for an action.
+ // |state| can be either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE.
+ views::CustomButton* GetButtonForUnitTest(SnapType state) {
+ return buttons_view_->GetButtonForUnitTest(state);
+ }
+
private:
// The owning class.
MaximizeBubbleController::Bubble* bubble_;
@@ -347,6 +363,7 @@ class BubbleDialogButton : public views::ImageButton {
virtual void OnMouseCaptureLost() OVERRIDE;
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
+ virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
private:
// The creating class which needs to get notified in case of a hover event.
@@ -355,14 +372,17 @@ class BubbleDialogButton : public views::ImageButton {
DISALLOW_COPY_AND_ASSIGN(BubbleDialogButton);
};
-MaximizeBubbleController::Bubble::Bubble(MaximizeBubbleController* owner)
+MaximizeBubbleController::Bubble::Bubble(
+ MaximizeBubbleController* owner,
+ int appearance_delay_ms)
: views::BubbleDelegateView(owner->frame_maximize_button(),
views::BubbleBorder::TOP_RIGHT),
shutting_down_(false),
owner_(owner),
bubble_widget_(NULL),
contents_view_(NULL),
- bubble_border_(NULL) {
+ bubble_border_(NULL),
+ appearance_delay_ms_(appearance_delay_ms) {
set_margins(gfx::Insets());
// The window needs to be owned by the root so that the SnapSizer does not
@@ -401,7 +421,10 @@ MaximizeBubbleController::Bubble::Bubble(MaximizeBubbleController* owner)
// Recalculate size with new border.
SizeToContents();
- StartFade(true);
+ if (!appearance_delay_ms_)
+ Show();
+ else
+ StartFade(true);
mouse_watcher_.reset(new views::MouseWatcher(
new BubbleMouseWatcherHost(this),
@@ -518,7 +541,10 @@ void MaximizeBubbleController::Bubble::ControllerRequestsCloseAndDelete() {
// Close the widget asynchronously after the hide animation is finished.
initial_position_ = bubble_widget_->GetNativeWindow()->bounds();
- StartFade(false);
+ if (!appearance_delay_ms_)
+ bubble_widget_->CloseNow();
+ else
+ StartFade(false);
}
void MaximizeBubbleController::Bubble::SetSnapType(SnapType snap_type) {
@@ -526,6 +552,11 @@ void MaximizeBubbleController::Bubble::SetSnapType(SnapType snap_type) {
contents_view_->SetSnapType(snap_type);
}
+views::CustomButton* MaximizeBubbleController::Bubble::GetButtonForUnitTest(
+ SnapType state) {
+ return contents_view_->GetButtonForUnitTest(state);
+}
+
BubbleContentsButtonRow::BubbleContentsButtonRow(
MaximizeBubbleController::Bubble* bubble)
: bubble_(bubble),
@@ -585,6 +616,21 @@ void BubbleContentsButtonRow::ButtonHovered(BubbleDialogButton* sender) {
bubble_->controller()->OnButtonHover(SNAP_NONE);
}
+views::CustomButton* BubbleContentsButtonRow::GetButtonForUnitTest(
+ SnapType state) {
+ switch (state) {
+ case SNAP_LEFT:
+ return left_button_;
+ case SNAP_MINIMIZE:
+ return minimize_button_;
+ case SNAP_RIGHT:
+ return right_button_;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
BubbleContentsView::BubbleContentsView(
MaximizeBubbleController::Bubble* bubble)
: bubble_(bubble),
@@ -646,19 +692,25 @@ void BubbleContentsView::SetSnapType(SnapType snap_type) {
MaximizeBubbleController::MaximizeBubbleController(
FrameMaximizeButton* frame_maximize_button,
- bool is_maximized)
+ bool is_maximized,
+ int appearance_delay_ms)
: frame_maximize_button_(frame_maximize_button),
bubble_(NULL),
- is_maximized_(is_maximized) {
+ is_maximized_(is_maximized),
+ appearance_delay_ms_(appearance_delay_ms) {
// Create the task which will create the bubble delayed.
base::OneShotTimer<MaximizeBubbleController>* new_timer =
new base::OneShotTimer<MaximizeBubbleController>();
+ // Note: Even if there was no delay time given, we need to have a timer.
new_timer->Start(
FROM_HERE,
- base::TimeDelta::FromMilliseconds(kBubbleAppearanceDelayMS),
+ base::TimeDelta::FromMilliseconds(
+ appearance_delay_ms_ ? appearance_delay_ms_ : 10),
this,
&MaximizeBubbleController::CreateBubble);
timer_.reset(new_timer);
+ if (!appearance_delay_ms_)
+ CreateBubble();
}
MaximizeBubbleController::~MaximizeBubbleController() {
@@ -692,6 +744,11 @@ void MaximizeBubbleController::OnButtonHover(SnapType snap_type) {
frame_maximize_button_->SnapButtonHovered(snap_type);
}
+views::CustomButton* MaximizeBubbleController::GetButtonForUnitTest(
+ SnapType state) {
+ return bubble_ ? bubble_->GetButtonForUnitTest(state) : NULL;
+}
+
void MaximizeBubbleController::RequestDestructionThroughOwner() {
// Tell the parent to destroy us (if this didn't happen yet).
if (timer_.get()) {
@@ -704,7 +761,7 @@ void MaximizeBubbleController::RequestDestructionThroughOwner() {
void MaximizeBubbleController::CreateBubble() {
if (!bubble_)
- bubble_ = new Bubble(this);
+ bubble_ = new Bubble(this, appearance_delay_ms_);
timer_->Stop();
}
@@ -739,4 +796,20 @@ void BubbleDialogButton::OnMouseExited(const ui::MouseEvent& event) {
views::ImageButton::OnMouseExited(event);
}
+bool BubbleDialogButton::OnMouseDragged(const ui::MouseEvent& event) {
+ if (!button_row_->bubble()->controller())
+ return false;
+
+ // Remove the phantom window when we leave the button.
+ gfx::Point screen_location(event.location());
+ View::ConvertPointToScreen(this, &screen_location);
+ if (!GetBoundsInScreen().Contains(screen_location))
+ button_row_->ButtonHovered(NULL);
+ else
+ button_row_->ButtonHovered(this);
+
+ // Pass the event on to the normal handler.
+ return views::ImageButton::OnMouseDragged(event);
+}
+
} // namespace ash
diff --git a/ash/wm/maximize_bubble_controller.h b/ash/wm/maximize_bubble_controller.h
index 5712a3c..ab9083d 100644
--- a/ash/wm/maximize_bubble_controller.h
+++ b/ash/wm/maximize_bubble_controller.h
@@ -9,12 +9,16 @@
#include "ash/wm/workspace/snap_types.h"
#include "base/memory/scoped_ptr.h"
+namespace aura {
+class Window;
+}
+
namespace base {
class Timer;
}
-namespace aura {
-class Window;
+namespace views {
+class CustomButton;
}
namespace ash {
@@ -27,7 +31,8 @@ class ASH_EXPORT MaximizeBubbleController {
class Bubble;
MaximizeBubbleController(FrameMaximizeButton* frame_maximize_button,
- bool is_maximized);
+ bool is_maximized,
+ int appearance_delay_ms);
// Called from the outside to destroy the interface to the UI visuals.
// The visuals will then delete when possible (maybe asynchronously).
virtual ~MaximizeBubbleController();
@@ -58,6 +63,10 @@ class ASH_EXPORT MaximizeBubbleController {
// The status of the associated window: Maximized or normal.
bool is_maximized() const { return is_maximized_; }
+ // A unit test function to return buttons of the sub menu. |state| can be
+ // either SNAP_LEFT, SNAP_RIGHT or SNAP_MINIMIZE.
+ views::CustomButton* GetButtonForUnitTest(SnapType state);
+
protected:
// Called from the the Bubble class to destroy itself: It tells the owning
// object that it will destroy itself asynchronously. The owner will then
@@ -80,6 +89,9 @@ class ASH_EXPORT MaximizeBubbleController {
// The timer for the delayed creation of the menu.
scoped_ptr<base::Timer> timer_;
+ // The appearance delay in ms (delay and fade in & fade out delay).
+ const int appearance_delay_ms_;
+
DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleController);
};
diff --git a/ash/wm/workspace/frame_maximize_button.cc b/ash/wm/workspace/frame_maximize_button.cc
index 259dba4..f819c99 100644
--- a/ash/wm/workspace/frame_maximize_button.cc
+++ b/ash/wm/workspace/frame_maximize_button.cc
@@ -32,6 +32,9 @@ namespace {
// Delay before forcing an update of the snap location.
const int kUpdateDelayMS = 400;
+// The delay of the bubble appearance.
+const int kBubbleAppearanceDelayMS = 200;
+
}
// EscapeEventFilter is installed on the RootWindow to track when the escape key
@@ -107,7 +110,8 @@ FrameMaximizeButton::FrameMaximizeButton(views::ButtonListener* listener,
is_snap_enabled_(false),
exceeded_drag_threshold_(false),
window_(NULL),
- snap_type_(SNAP_NONE) {
+ snap_type_(SNAP_NONE),
+ bubble_appearance_delay_ms_(kBubbleAppearanceDelayMS) {
// TODO(sky): nuke this. It's temporary while we don't have good images.
SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
}
@@ -202,7 +206,8 @@ void FrameMaximizeButton::OnMouseEntered(const ui::MouseEvent& event) {
}
maximizer_.reset(new MaximizeBubbleController(
this,
- frame_->GetWidget()->IsMaximized()));
+ frame_->GetWidget()->IsMaximized(),
+ bubble_appearance_delay_ms_));
}
}
@@ -285,7 +290,8 @@ void FrameMaximizeButton::ProcessStartEvent(const ui::LocatedEvent& event) {
if (!maximizer_.get()) {
maximizer_.reset(new MaximizeBubbleController(
this,
- frame_->GetWidget()->IsMaximized()));
+ frame_->GetWidget()->IsMaximized(),
+ bubble_appearance_delay_ms_));
} else {
// If the menu did not show up yet, we delay it even a bit more.
maximizer_->DelayCreation();
diff --git a/ash/wm/workspace/frame_maximize_button.h b/ash/wm/workspace/frame_maximize_button.h
index 5c6bca2..9041a9b 100644
--- a/ash/wm/workspace/frame_maximize_button.h
+++ b/ash/wm/workspace/frame_maximize_button.h
@@ -63,6 +63,17 @@ class ASH_EXPORT FrameMaximizeButton : public views::ImageButton,
virtual ui::GestureStatus OnGestureEvent(
const ui::GestureEvent& event) OVERRIDE;
+ // Unit test overwrite: Change the UI delay used for the bubble show up.
+ void set_bubble_appearance_delay_ms(int bubble_appearance_delay_ms) {
+ bubble_appearance_delay_ms_ = bubble_appearance_delay_ms;
+ }
+
+ // Unit test accessor for the maximize bubble.
+ MaximizeBubbleController* maximizer() { return maximizer_.get(); }
+
+ // Unit test to see if phantom window is open.
+ bool phantom_window_open() { return phantom_window_.get() != NULL; }
+
private:
class EscapeEventFilter;
@@ -136,6 +147,9 @@ class ASH_EXPORT FrameMaximizeButton : public views::ImageButton,
scoped_ptr<MaximizeBubbleController> maximizer_;
+ // The delay of the bubble appearance.
+ int bubble_appearance_delay_ms_;
+
DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButton);
};