diff options
-rw-r--r-- | ash/ash.gyp | 2 | ||||
-rw-r--r-- | ash/system/tray/hover_highlight_view.cc | 36 | ||||
-rw-r--r-- | ash/system/tray/hover_highlight_view.h | 4 | ||||
-rw-r--r-- | ash/system/tray/system_tray_bubble.cc | 68 | ||||
-rw-r--r-- | ash/system/tray/system_tray_unittest.cc | 73 | ||||
-rw-r--r-- | ash/system/tray/tray_details_view_unittest.cc | 85 | ||||
-rw-r--r-- | ash/system/tray/tray_popup_item_container.cc | 88 | ||||
-rw-r--r-- | ash/system/tray/tray_popup_item_container.h | 51 |
8 files changed, 324 insertions, 83 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index 4c232b6..6aa2dd2 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -427,6 +427,8 @@ 'system/tray/tray_notification_view.h', 'system/tray/tray_popup_header_button.cc', 'system/tray/tray_popup_header_button.h', + 'system/tray/tray_popup_item_container.cc', + 'system/tray/tray_popup_item_container.h', 'system/tray/tray_popup_label_button.cc', 'system/tray/tray_popup_label_button.h', 'system/tray/tray_popup_label_button_border.cc', diff --git a/ash/system/tray/hover_highlight_view.cc b/ash/system/tray/hover_highlight_view.cc index be2efc2..d81f5a6 100644 --- a/ash/system/tray/hover_highlight_view.cc +++ b/ash/system/tray/hover_highlight_view.cc @@ -9,6 +9,7 @@ #include "ash/system/tray/view_click_listener.h" #include "ui/accessibility/ax_view_state.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_switches_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/resources/grit/ui_resources.h" @@ -130,6 +131,19 @@ void HoverHighlightView::SetExpandable(bool expandable) { } } +void HoverHighlightView::SetHoverHighlight(bool hover) { + if (hover_ == hover) + return; + hover_ = hover; + if (!text_label_) + return; + if (hover_ && text_highlight_color_) + text_label_->SetEnabledColor(text_highlight_color_); + if (!hover_ && text_default_color_) + text_label_->SetEnabledColor(text_default_color_); + SchedulePaint(); +} + bool HoverHighlightView::PerformAction(const ui::Event& event) { if (!listener_) return false; @@ -159,17 +173,23 @@ int HoverHighlightView::GetHeightForWidth(int width) const { } void HoverHighlightView::OnMouseEntered(const ui::MouseEvent& event) { - hover_ = true; - if (text_highlight_color_ && text_label_) - text_label_->SetEnabledColor(text_highlight_color_); - SchedulePaint(); + SetHoverHighlight(true); } void HoverHighlightView::OnMouseExited(const ui::MouseEvent& event) { - hover_ = false; - if (text_default_color_ && text_label_) - text_label_->SetEnabledColor(text_default_color_); - SchedulePaint(); + SetHoverHighlight(false); +} + +void HoverHighlightView::OnGestureEvent(ui::GestureEvent* event) { + if (switches::IsTouchFeedbackEnabled()) { + if (event->type() == ui::ET_GESTURE_TAP_DOWN) { + SetHoverHighlight(true); + } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL || + event->type() == ui::ET_GESTURE_TAP) { + SetHoverHighlight(false); + } + } + ActionableView::OnGestureEvent(event); } void HoverHighlightView::OnEnabledChanged() { diff --git a/ash/system/tray/hover_highlight_view.h b/ash/system/tray/hover_highlight_view.h index 6df822f..ffd83a2 100644 --- a/ash/system/tray/hover_highlight_view.h +++ b/ash/system/tray/hover_highlight_view.h @@ -64,6 +64,9 @@ class HoverHighlightView : public ActionableView { virtual void GetAccessibleState(ui::AXViewState* state) override; private: + // Sets the highlighted color on a text label if |hover| is set. + void SetHoverHighlight(bool hover); + // Overridden from ActionableView: virtual bool PerformAction(const ui::Event& event) override; @@ -72,6 +75,7 @@ class HoverHighlightView : public ActionableView { virtual int GetHeightForWidth(int width) const override; virtual void OnMouseEntered(const ui::MouseEvent& event) override; virtual void OnMouseExited(const ui::MouseEvent& event) override; + virtual void OnGestureEvent(ui::GestureEvent* event) override; virtual void OnEnabledChanged() override; virtual void OnPaintBackground(gfx::Canvas* canvas) override; virtual void OnFocus() override; diff --git a/ash/system/tray/system_tray_bubble.cc b/ash/system/tray/system_tray_bubble.cc index 97500df..96e19c2 100644 --- a/ash/system/tray/system_tray_bubble.cc +++ b/ash/system/tray/system_tray_bubble.cc @@ -10,6 +10,7 @@ #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_bubble_wrapper.h" #include "ash/system/tray/tray_constants.h" +#include "ash/system/tray/tray_popup_item_container.h" #include "base/message_loop/message_loop.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" @@ -37,73 +38,6 @@ const int kDetailedBubbleMaxHeight = kTrayPopupItemHeight * 5; // detailed view or vice versa. const int kSwipeDelayMS = 150; -// A view with some special behaviour for tray items in the popup: -// - optionally changes background color on hover. -class TrayPopupItemContainer : public views::View { - public: - TrayPopupItemContainer(views::View* view, - bool change_background, - bool draw_border) - : hover_(false), - change_background_(change_background) { - set_notify_enter_exit_on_child(true); - if (draw_border) { - SetBorder( - views::Border::CreateSolidSidedBorder(0, 0, 1, 0, kBorderLightColor)); - } - views::BoxLayout* layout = new views::BoxLayout( - views::BoxLayout::kVertical, 0, 0, 0); - layout->SetDefaultFlex(1); - SetLayoutManager(layout); - SetPaintToLayer(view->layer() != NULL); - if (view->layer()) - SetFillsBoundsOpaquely(view->layer()->fills_bounds_opaquely()); - AddChildView(view); - SetVisible(view->visible()); - } - - virtual ~TrayPopupItemContainer() {} - - private: - // Overridden from views::View. - virtual void ChildVisibilityChanged(View* child) override { - if (visible() == child->visible()) - return; - SetVisible(child->visible()); - PreferredSizeChanged(); - } - - virtual void ChildPreferredSizeChanged(View* child) override { - PreferredSizeChanged(); - } - - virtual void OnMouseEntered(const ui::MouseEvent& event) override { - hover_ = true; - SchedulePaint(); - } - - virtual void OnMouseExited(const ui::MouseEvent& event) override { - hover_ = false; - SchedulePaint(); - } - - virtual void OnPaintBackground(gfx::Canvas* canvas) override { - if (child_count() == 0) - return; - - views::View* view = child_at(0); - if (!view->background()) { - canvas->FillRect(gfx::Rect(size()), (hover_ && change_background_) ? - kHoverBackgroundColor : kBackgroundColor); - } - } - - bool hover_; - bool change_background_; - - DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer); -}; - // Implicit animation observer that deletes itself and the layer at the end of // the animation. class AnimationObserverDeleteLayer : public ui::ImplicitAnimationObserver { diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc index f06b648..4cfe64b 100644 --- a/ash/system/tray/system_tray_unittest.cc +++ b/ash/system/tray/system_tray_unittest.cc @@ -12,16 +12,21 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h" +#include "ash/system/tray/system_tray_bubble.h" #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_constants.h" +#include "ash/system/tray/tray_popup_item_container.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_util.h" +#include "base/command_line.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "ui/aura/window.h" +#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_types.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/views/controls/label.h" #include "ui/views/layout/fill_layout.h" @@ -157,7 +162,20 @@ class ModalWidgetDelegate : public views::WidgetDelegateView { } // namespace -typedef AshTestBase SystemTrayTest; +class SystemTrayTest : public AshTestBase { + public: + SystemTrayTest() {} + virtual ~SystemTrayTest() {} + + virtual void SetUp() OVERRIDE { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableTouchFeedback); + test::AshTestBase::SetUp(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SystemTrayTest); +}; TEST_F(SystemTrayTest, SystemTrayDefaultView) { SystemTray* tray = GetSystemTray(); @@ -505,5 +523,58 @@ TEST_F(SystemTrayTest, SetVisibleDuringHideAnimation) { EXPECT_EQ(1.0f, tray->layer()->GetTargetOpacity()); } +#if defined(OS_CHROMEOS) +// Tests that touch on an item in the system bubble triggers it to become +// active. +TEST_F(SystemTrayTest, TrayPopupItemContainerTouchFeedback) { + SystemTray* tray = GetSystemTray(); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + + TrayPopupItemContainer* view = + static_cast<TrayPopupItemContainer*>(tray->GetSystemBubble()-> + bubble_view()->child_at(0)); + EXPECT_FALSE(view->active()); + + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + generator.set_current_location(view->GetBoundsInScreen().CenterPoint()); + generator.PressTouch(); + RunAllPendingInMessageLoop(); + EXPECT_TRUE(view->active()); + + generator.ReleaseTouch(); + RunAllPendingInMessageLoop(); + EXPECT_FALSE(view->active()); +} + +// Tests that touch events on an item in the system bubble cause it to stop +// being active. +TEST_F(SystemTrayTest, TrayPopupItemContainerTouchFeedbackCancellation) { + SystemTray* tray = GetSystemTray(); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + + TrayPopupItemContainer* view = + static_cast<TrayPopupItemContainer*>(tray->GetSystemBubble()-> + bubble_view()->child_at(0)); + EXPECT_FALSE(view->active()); + + gfx::Rect view_bounds = view->GetBoundsInScreen(); + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + generator.set_current_location(view_bounds.CenterPoint()); + generator.PressTouch(); + RunAllPendingInMessageLoop(); + EXPECT_TRUE(view->active()); + + gfx::Point move_point(view_bounds.x(), view_bounds.CenterPoint().y()); + generator.MoveTouch(move_point); + RunAllPendingInMessageLoop(); + EXPECT_FALSE(view->active()); + + generator.set_current_location(move_point); + generator.ReleaseTouch(); + RunAllPendingInMessageLoop(); + EXPECT_FALSE(view->active()); +} +#endif // OS_CHROMEOS + } // namespace test } // namespace ash diff --git a/ash/system/tray/tray_details_view_unittest.cc b/ash/system/tray/tray_details_view_unittest.cc index 32c859a..3430c76 100644 --- a/ash/system/tray/tray_details_view_unittest.cc +++ b/ash/system/tray/tray_details_view_unittest.cc @@ -8,14 +8,19 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h" +#include "ash/system/tray/hover_highlight_view.h" +#include "ash/system/tray/special_popup_row.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_details_view.h" #include "ash/system/tray/view_click_listener.h" #include "ash/test/ash_test_base.h" +#include "base/command_line.h" #include "base/run_loop.h" #include "grit/ash_strings.h" #include "ui/aura/window.h" +#include "ui/base/ui_base_switches.h" +#include "ui/events/test/event_generator.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -31,14 +36,15 @@ SystemTray* GetSystemTray() { class TestDetailsView : public TrayDetailsView, public ViewClickListener { public: - explicit TestDetailsView(SystemTrayItem* owner) : TrayDetailsView(owner) {} - - virtual ~TestDetailsView() {} - - void CreateFooterAndFocus() { + explicit TestDetailsView(SystemTrayItem* owner) : TrayDetailsView(owner) { // Uses bluetooth label for testing purpose. It can be changed to any // string_id. CreateSpecialRow(IDS_ASH_STATUS_TRAY_BLUETOOTH, this); + } + + virtual ~TestDetailsView() {} + + void FocusFooter() { footer()->content()->RequestFocus(); } @@ -92,7 +98,33 @@ class TestItem : public SystemTrayItem { } // namespace -typedef AshTestBase TrayDetailsViewTest; +class TrayDetailsViewTest : public AshTestBase { + public: + TrayDetailsViewTest() {} + virtual ~TrayDetailsViewTest() {} + + HoverHighlightView* CreateAndShowHoverHighlightView() { + SystemTray* tray = GetSystemTray(); + TestItem* test_item = new TestItem; + tray->AddTrayItem(test_item); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING); + RunAllPendingInMessageLoop(); + + return static_cast<HoverHighlightView*>(test_item->detailed_view()-> + footer()->content()); + } + + virtual void SetUp() OVERRIDE { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableTouchFeedback); + test::AshTestBase::SetUp(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TrayDetailsViewTest); +}; TEST_F(TrayDetailsViewTest, TransitionToDefaultViewTest) { SystemTray* tray = GetSystemTray(); @@ -119,7 +151,7 @@ TEST_F(TrayDetailsViewTest, TransitionToDefaultViewTest) { // Transition back to default view, the default view of item 2 should have // focus. - test_item_2->detailed_view()->CreateFooterAndFocus(); + test_item_2->detailed_view()->FocusFooter(); test_item_2->detailed_view()->TransitionToDefaultView(); RunAllPendingInMessageLoop(); @@ -143,5 +175,44 @@ TEST_F(TrayDetailsViewTest, TransitionToDefaultViewTest) { EXPECT_FALSE(test_item_2->default_view()->HasFocus()); } +// Tests that HoverHighlightView enters hover state in response to touch. +TEST_F(TrayDetailsViewTest, HoverHighlightViewTouchFeedback) { + HoverHighlightView* view = CreateAndShowHoverHighlightView(); + EXPECT_FALSE(view->hover()); + + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + generator.set_current_location(view->GetBoundsInScreen().CenterPoint()); + generator.PressTouch(); + RunAllPendingInMessageLoop(); + EXPECT_TRUE(view->hover()); + + generator.ReleaseTouch(); + RunAllPendingInMessageLoop(); + EXPECT_FALSE(view->hover()); +} + +// Tests that touch events leaving HoverHighlightView cancel the hover state. +TEST_F(TrayDetailsViewTest, HoverHighlightViewTouchFeedbackCancellation) { + HoverHighlightView* view = CreateAndShowHoverHighlightView(); + EXPECT_FALSE(view->hover()); + + gfx::Rect view_bounds = view->GetBoundsInScreen(); + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + generator.set_current_location(view_bounds.CenterPoint()); + generator.PressTouch(); + RunAllPendingInMessageLoop(); + EXPECT_TRUE(view->hover()); + + gfx::Point move_point(view_bounds.x(), view_bounds.CenterPoint().y()); + generator.MoveTouch(move_point); + RunAllPendingInMessageLoop(); + EXPECT_FALSE(view->hover()); + + generator.set_current_location(move_point); + generator.ReleaseTouch(); + RunAllPendingInMessageLoop(); + EXPECT_FALSE(view->hover()); +} + } // namespace test } // namespace ash diff --git a/ash/system/tray/tray_popup_item_container.cc b/ash/system/tray/tray_popup_item_container.cc new file mode 100644 index 0000000..9a21399 --- /dev/null +++ b/ash/system/tray/tray_popup_item_container.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/tray/tray_popup_item_container.h" + +#include "ash/system/tray/tray_constants.h" +#include "base/command_line.h" +#include "ui/base/ui_base_switches_util.h" +#include "ui/gfx/canvas.h" +#include "ui/views/border.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +TrayPopupItemContainer::TrayPopupItemContainer(views::View* view, + bool change_background, + bool draw_border) + : active_(false), + change_background_(change_background) { + set_notify_enter_exit_on_child(true); + if (draw_border) { + SetBorder( + views::Border::CreateSolidSidedBorder(0, 0, 1, 0, kBorderLightColor)); + } + views::BoxLayout* layout = new views::BoxLayout( + views::BoxLayout::kVertical, 0, 0, 0); + layout->SetDefaultFlex(1); + SetLayoutManager(layout); + SetPaintToLayer(view->layer() != NULL); + if (view->layer()) + SetFillsBoundsOpaquely(view->layer()->fills_bounds_opaquely()); + AddChildView(view); + SetVisible(view->visible()); +} + +TrayPopupItemContainer::~TrayPopupItemContainer() { +} + +void TrayPopupItemContainer::SetActive(bool active) { + if (!change_background_ || active_ == active) + return; + active_ = active; + SchedulePaint(); +} + +void TrayPopupItemContainer::ChildVisibilityChanged(View* child) { + if (visible() == child->visible()) + return; + SetVisible(child->visible()); + PreferredSizeChanged(); +} + +void TrayPopupItemContainer::ChildPreferredSizeChanged(View* child) { + PreferredSizeChanged(); +} + +void TrayPopupItemContainer::OnMouseEntered(const ui::MouseEvent& event) { + SetActive(true); +} + +void TrayPopupItemContainer::OnMouseExited(const ui::MouseEvent& event) { + SetActive(false); +} + +void TrayPopupItemContainer::OnGestureEvent(ui::GestureEvent* event) { + if (!switches::IsTouchFeedbackEnabled()) + return; + if (event->type() == ui::ET_GESTURE_TAP_DOWN) { + SetActive(true); + } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL || + event->type() == ui::ET_GESTURE_TAP) { + SetActive(false); + } +} + +void TrayPopupItemContainer::OnPaintBackground(gfx::Canvas* canvas) { + if (child_count() == 0) + return; + + views::View* view = child_at(0); + if (!view->background()) { + canvas->FillRect(gfx::Rect(size()), (active_) ? kHoverBackgroundColor + : kBackgroundColor); + } +} + +} // namespace ash diff --git a/ash/system/tray/tray_popup_item_container.h b/ash/system/tray/tray_popup_item_container.h new file mode 100644 index 0000000..8992b21 --- /dev/null +++ b/ash/system/tray/tray_popup_item_container.h @@ -0,0 +1,51 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_TRAY_TRAY_POPUP_ITEM_CONTAINER_H_ +#define ASH_SYSTEM_TRAY_TRAY_POPUP_ITEM_CONTAINER_H_ + +#include "ui/views/view.h" + +namespace ash { + +// A view which can optionally change the background color when a mouse is +// hovering or a user is interacting via touch. +class TrayPopupItemContainer : public views::View { + public: + TrayPopupItemContainer(views::View* view, + bool change_background, + bool draw_border); + + virtual ~TrayPopupItemContainer(); + + bool active() { + return active_; + } + + private: + // Sets whether the active background is to be used, and triggers a paint. + void SetActive(bool active); + + // views::View: + virtual void ChildVisibilityChanged(views::View* child) override; + virtual void ChildPreferredSizeChanged(views::View* child) override; + virtual void OnMouseEntered(const ui::MouseEvent& event) override; + virtual void OnMouseExited(const ui::MouseEvent& event) override; + virtual void OnGestureEvent(ui::GestureEvent* event) override; + virtual void OnPaintBackground(gfx::Canvas* canvas) override; + + // True if either a mouse is hovering over this view, or if a user has touched + // down. + bool active_; + + // True if mouse hover and touch feedback can alter the background color of + // the container. + bool change_background_; + + DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_TRAY_TRAY_POPUP_ITEM_CONTAINER_H_ |