diff options
author | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-14 23:33:43 +0000 |
---|---|---|
committer | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-14 23:33:43 +0000 |
commit | 145d67fc623f958ff07b1f40e9208ba8f0757b0a (patch) | |
tree | 41bde91b870b7bf2d81d2322c758632fc28b1478 /ash | |
parent | 708d0cce7d55778a3527c6c6ea60ebaac1d6ec10 (diff) | |
download | chromium_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.h | 5 | ||||
-rw-r--r-- | ash/wm/custom_frame_view_ash_unittest.cc | 116 | ||||
-rw-r--r-- | ash/wm/maximize_bubble_controller.cc | 97 | ||||
-rw-r--r-- | ash/wm/maximize_bubble_controller.h | 18 | ||||
-rw-r--r-- | ash/wm/workspace/frame_maximize_button.cc | 12 | ||||
-rw-r--r-- | ash/wm/workspace/frame_maximize_button.h | 14 |
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); }; |