diff options
author | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-22 00:24:46 +0000 |
---|---|---|
committer | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-22 00:24:46 +0000 |
commit | 2e195f5938e632d3cd7874848d5143d189f37f39 (patch) | |
tree | 208de3a892eaf01b303befe8560339a06b327e37 | |
parent | d9301f84d817be22d9e51248351145cc3140dea2 (diff) | |
download | chromium_src-2e195f5938e632d3cd7874848d5143d189f37f39.zip chromium_src-2e195f5938e632d3cd7874848d5143d189f37f39.tar.gz chromium_src-2e195f5938e632d3cd7874848d5143d189f37f39.tar.bz2 |
Disallow the shelf from hiding when the mouse is between the message bubble and the shelf area.
When a message bubble is open and the user moves the mouse towards the shelf, the shelf will disappear when he crosses the gap between the two elements. This change is extending the shelf between the two when a message is visible.
BUG=143178
TEST=unit test & visual
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=158066
Review URL: https://chromiumcodereview.appspot.com/10943038
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@158140 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/system/status_area_widget.cc | 6 | ||||
-rw-r--r-- | ash/system/status_area_widget.h | 3 | ||||
-rw-r--r-- | ash/wm/shelf_layout_manager.cc | 24 | ||||
-rw-r--r-- | ash/wm/shelf_layout_manager_unittest.cc | 124 |
4 files changed, 153 insertions, 4 deletions
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc index ec610ab..9370625 100644 --- a/ash/system/status_area_widget.cc +++ b/ash/system/status_area_widget.cc @@ -360,6 +360,12 @@ bool StatusAreaWidget::ShouldShowLauncher() const { web_notification_tray_->IsMouseInNotificationBubble()); } +bool StatusAreaWidget::IsMessageBubbleShown() const { + return ((system_tray_ && system_tray_->IsAnyBubbleVisible()) || + (web_notification_tray_ && + web_notification_tray_->IsMessageCenterBubbleVisible())); +} + void StatusAreaWidget::AddSystemTray(ShellDelegate* shell_delegate) { system_tray_ = new SystemTray(this); status_area_widget_delegate_->AddTray(system_tray_); diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h index 4a5e600..26ff2a3 100644 --- a/ash/system/status_area_widget.h +++ b/ash/system/status_area_widget.h @@ -74,6 +74,9 @@ class ASH_EXPORT StatusAreaWidget : public views::Widget { // the launcher to remain visible. bool ShouldShowLauncher() const; + // True if any message bubble is shown. + bool IsMessageBubbleShown() const; + private: void AddSystemTray(ShellDelegate* shell_delegate); void AddWebNotificationTray(); diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc index 1b765b3..0264c1d 100644 --- a/ash/wm/shelf_layout_manager.cc +++ b/ash/wm/shelf_layout_manager.cc @@ -36,6 +36,11 @@ namespace { // Delay before showing the launcher. This is after the mouse stops moving. const int kAutoHideDelayMS = 200; +// To avoid hiding the shelf when the mouse transitions from a message bubble +// into the shelf, the hit test area is enlarged by this amount of pixels to +// keep the shelf from hiding. +const int kNotificationBubbleGapHeight = 6; + ui::Layer* GetLayer(views::Widget* widget) { return widget->GetNativeView()->layer(); } @@ -852,10 +857,21 @@ ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState( if (event_filter_.get() && event_filter_->in_mouse_drag()) return AUTO_HIDE_HIDDEN; - bool mouse_over_launcher = - launcher_widget()->GetWindowBoundsInScreen().Contains( - gfx::Screen::GetCursorScreenPoint()); - return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN; + gfx::Rect shelf_region = launcher_widget()->GetWindowBoundsInScreen(); + if (Shell::GetInstance()->status_area_widget()->IsMessageBubbleShown() && + IsVisible()) { + // Increase the the hit test area to prevent the shelf from disappearing + // when the mouse is over the bubble gap. + shelf_region.Inset(alignment_ == SHELF_ALIGNMENT_RIGHT ? + -kNotificationBubbleGapHeight : 0, + alignment_ == SHELF_ALIGNMENT_BOTTOM ? + -kNotificationBubbleGapHeight : 0, + alignment_ == SHELF_ALIGNMENT_LEFT ? + -kNotificationBubbleGapHeight : 0, + 0); + } + return shelf_region.Contains(gfx::Screen::GetCursorScreenPoint()) ? + AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN; } void ShelfLayoutManager::UpdateHitTestBounds() { diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc index 8b1685c..e5a8d16 100644 --- a/ash/wm/shelf_layout_manager_unittest.cc +++ b/ash/wm/shelf_layout_manager_unittest.cc @@ -12,9 +12,12 @@ #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" +#include "ash/system/status_area_widget.h" #include "ash/system/tray/system_tray.h" +#include "ash/system/tray/system_tray_item.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_util.h" +#include "base/utf_string_conversions.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" #include "ui/aura/display_manager.h" @@ -26,6 +29,9 @@ #include "ui/compositor/layer_animator.h" #include "ui/gfx/display.h" #include "ui/gfx/screen.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/view.h" #include "ui/views/widget/widget.h" namespace ash { @@ -68,6 +74,76 @@ class ShelfLayoutObserverTest : public ShelfLayoutManager::Observer { DISALLOW_COPY_AND_ASSIGN(ShelfLayoutObserverTest); }; +// Trivial item implementation that tracks its views for testing. +class TestItem : public SystemTrayItem { + public: + TestItem() + : tray_view_(NULL), + default_view_(NULL), + detailed_view_(NULL), + notification_view_(NULL) {} + + virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE { + tray_view_ = new views::View; + // Add a label so it has non-zero width. + tray_view_->SetLayoutManager(new views::FillLayout); + tray_view_->AddChildView(new views::Label(UTF8ToUTF16("Tray"))); + return tray_view_; + } + + virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE { + default_view_ = new views::View; + default_view_->SetLayoutManager(new views::FillLayout); + default_view_->AddChildView(new views::Label(UTF8ToUTF16("Default"))); + return default_view_; + } + + virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE { + detailed_view_ = new views::View; + detailed_view_->SetLayoutManager(new views::FillLayout); + detailed_view_->AddChildView(new views::Label(UTF8ToUTF16("Detailed"))); + return detailed_view_; + } + + virtual views::View* CreateNotificationView( + user::LoginStatus status) OVERRIDE { + notification_view_ = new views::View; + return notification_view_; + } + + virtual void DestroyTrayView() OVERRIDE { + tray_view_ = NULL; + } + + virtual void DestroyDefaultView() OVERRIDE { + default_view_ = NULL; + } + + virtual void DestroyDetailedView() OVERRIDE { + detailed_view_ = NULL; + } + + virtual void DestroyNotificationView() OVERRIDE { + notification_view_ = NULL; + } + + virtual void UpdateAfterLoginStatusChange( + user::LoginStatus status) OVERRIDE {} + + views::View* tray_view() const { return tray_view_; } + views::View* default_view() const { return default_view_; } + views::View* detailed_view() const { return detailed_view_; } + views::View* notification_view() const { return notification_view_; } + + private: + views::View* tray_view_; + views::View* default_view_; + views::View* detailed_view_; + views::View* notification_view_; + + DISALLOW_COPY_AND_ASSIGN(TestItem); +}; + } // namespace class ShelfLayoutManagerTest : public ash::test::AshTestBase { @@ -808,5 +884,53 @@ TEST_F(ShelfLayoutManagerTest, Dimming) { EXPECT_FALSE(Shell::GetInstance()->launcher()->GetDimsShelf()); } +// Make sure that the shelf will not hide if the mouse is between a bubble and +// the shelf. +TEST_F(ShelfLayoutManagerTest, BubbleEnlargesShelfMouseHitArea) { + ShelfLayoutManager* shelf = GetShelfLayoutManager(); + StatusAreaWidget* status_area = Shell::GetInstance()->status_area_widget(); + SystemTray* tray = Shell::GetInstance()->system_tray(); + + shelf->LayoutShelf(); + aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + + // Make two iterations - first without a message bubble which should make + // the shelf disappear and then with a message bubble which should keep it + // visible. + for (int i = 0; i < 2; i++) { + // Make sure the shelf is visible and position the mouse over it. Then + // allow auto hide. + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); + EXPECT_FALSE(status_area->IsMessageBubbleShown()); + gfx::Point center = + shelf->status()->GetWindowBoundsInScreen().CenterPoint(); + generator.MoveMouseTo(center.x(), center.y()); + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + EXPECT_TRUE(shelf->IsVisible()); + if (!i) { + // In our first iteration we make sure there is no bubble. + tray->CloseBubbleForTest(); + EXPECT_FALSE(status_area->IsMessageBubbleShown()); + } else { + // In our second iteration we show a bubble. + TestItem *item = new TestItem; + tray->AddTrayItem(item); + tray->ShowNotificationView(item); + EXPECT_TRUE(status_area->IsMessageBubbleShown()); + } + // Move the pointer over the edge of the shelf. + generator.MoveMouseTo(center.x(), + shelf->status()->GetWindowBoundsInScreen().y() - 5); + shelf->UpdateVisibilityState(); + if (i) { + EXPECT_TRUE(shelf->IsVisible()); + EXPECT_TRUE(status_area->IsMessageBubbleShown()); + } else { + EXPECT_FALSE(shelf->IsVisible()); + EXPECT_FALSE(status_area->IsMessageBubbleShown()); + } + } +} + } // namespace internal } // namespace ash |