summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authormsw <msw@chromium.org>2016-03-23 16:48:50 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-23 23:50:35 +0000
commite9d901efb5bc6bbf434ac67b70f90e9ef73419d8 (patch)
tree97c9e4909019d18b900220c7c4cfcbb42836656e /ash
parentfbaed4750ac46ce84d4b5d361b2601447db5390d (diff)
downloadchromium_src-e9d901efb5bc6bbf434ac67b70f90e9ef73419d8.zip
chromium_src-e9d901efb5bc6bbf434ac67b70f90e9ef73419d8.tar.gz
chromium_src-e9d901efb5bc6bbf434ac67b70f90e9ef73419d8.tar.bz2
Enable mash shelf tooltips.
Make ShelfItemDelegateMus::ShouldShowTooltip() return true. Put sysui menu/bubble widgets in mus's MENUS container. (bubbles are used for shelf tooltips and volume/etc. settings) Put sysui tooltip widgets in mus's TOOLTIPS container. Rewrite ShelfTooltipManager as an aura::Window pre-target handler. (can't install itself as a pre-target handler for the desktop root...) Remove ShelfButtonHost; simplify ShelfButton and AppListButton. (contain event observation logic within ShelfTooltipManager) Update unit tests and helper classes; note currently broken behavior: TODO: Make tooltips close on touch events outside the shelf. TODO: Push item state to items; avoid shelf item delegates, etc. BUG=595853 TEST=mash shelf shows tooltips; no cros regressions (except not closing on touch/gesture outside shelf). R=sky@chromium.org Review URL: https://codereview.chromium.org/1816753002 Cr-Commit-Position: refs/heads/master@{#382976}
Diffstat (limited to 'ash')
-rw-r--r--ash/ash.gyp1
-rw-r--r--ash/mus/shelf_delegate_mus.cc5
-rw-r--r--ash/mus/sysui_application.cc22
-rw-r--r--ash/shelf/app_list_button.cc59
-rw-r--r--ash/shelf/app_list_button.h22
-rw-r--r--ash/shelf/shelf_button.cc152
-rw-r--r--ash/shelf/shelf_button.h56
-rw-r--r--ash/shelf/shelf_button_host.h65
-rw-r--r--ash/shelf/shelf_tooltip_manager.cc332
-rw-r--r--ash/shelf/shelf_tooltip_manager.h84
-rw-r--r--ash/shelf/shelf_tooltip_manager_unittest.cc197
-rw-r--r--ash/shelf/shelf_view.cc302
-rw-r--r--ash/shelf/shelf_view.h48
-rw-r--r--ash/shelf/shelf_view_unittest.cc167
-rw-r--r--ash/test/shelf_test_api.cc7
-rw-r--r--ash/test/shelf_view_test_api.cc4
-rw-r--r--ash/test/shelf_view_test_api.h4
17 files changed, 500 insertions, 1027 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 3a8f474..4b49388 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -232,7 +232,6 @@
'shelf/shelf_bezel_event_filter.h',
'shelf/shelf_button.cc',
'shelf/shelf_button.h',
- 'shelf/shelf_button_host.h',
'shelf/shelf_constants.cc',
'shelf/shelf_constants.h',
'shelf/shelf_delegate.h',
diff --git a/ash/mus/shelf_delegate_mus.cc b/ash/mus/shelf_delegate_mus.cc
index ce3698a..510bb1b 100644
--- a/ash/mus/shelf_delegate_mus.cc
+++ b/ash/mus/shelf_delegate_mus.cc
@@ -66,10 +66,7 @@ class ShelfItemDelegateMus : public ShelfItemDelegate {
return false;
}
- bool ShouldShowTooltip() override {
- // NOTIMPLEMENTED(); very noisy
- return false;
- }
+ bool ShouldShowTooltip() override { return true; }
void Close() override { NOTIMPLEMENTED(); }
diff --git a/ash/mus/sysui_application.cc b/ash/mus/sysui_application.cc
index 16585a3..5fd5aac 100644
--- a/ash/mus/sysui_application.cc
+++ b/ash/mus/sysui_application.cc
@@ -45,11 +45,11 @@ namespace sysui {
namespace {
-// Tries to determine the corresponding container in mash from the ash container
-// for the widget.
-mash::wm::mojom::Container GetContainerId(aura::Window* container) {
- DCHECK(container);
- int id = container->id();
+// Tries to determine the corresponding mash container from widget init params.
+mash::wm::mojom::Container GetContainerId(
+ const views::Widget::InitParams& params) {
+ DCHECK(params.parent);
+ const int id = params.parent->id();
if (id == kShellWindowId_DesktopBackgroundContainer)
return mash::wm::mojom::Container::USER_BACKGROUND;
// mash::wm::ShelfLayout manages both the shelf and the status area.
@@ -57,6 +57,16 @@ mash::wm::mojom::Container GetContainerId(aura::Window* container) {
id == kShellWindowId_StatusContainer) {
return mash::wm::mojom::Container::USER_SHELF;
}
+
+ // Show mash shelf tooltips and settings bubbles in the menu container.
+ if (params.type == views::Widget::InitParams::Type::TYPE_MENU ||
+ params.type == views::Widget::InitParams::Type::TYPE_BUBBLE) {
+ return mash::wm::mojom::Container::MENUS;
+ }
+
+ if (params.type == views::Widget::InitParams::Type::TYPE_TOOLTIP)
+ return mash::wm::mojom::Container::TOOLTIPS;
+
return mash::wm::mojom::Container::COUNT;
}
@@ -118,7 +128,7 @@ class NativeWidgetFactory {
views::internal::NativeWidgetDelegate* delegate) {
std::map<std::string, std::vector<uint8_t>> properties;
if (params.parent) {
- mash::wm::mojom::Container container = GetContainerId(params.parent);
+ mash::wm::mojom::Container container = GetContainerId(params);
if (container != mash::wm::mojom::Container::COUNT) {
properties[mash::wm::mojom::kWindowContainer_Property] =
mojo::TypeConverter<const std::vector<uint8_t>, int32_t>::Convert(
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc
index acb0dd3..d1ee54b 100644
--- a/ash/shelf/app_list_button.cc
+++ b/ash/shelf/app_list_button.cc
@@ -5,10 +5,9 @@
#include "ash/shelf/app_list_button.h"
#include "ash/ash_constants.h"
-#include "ash/shelf/shelf_button.h"
-#include "ash/shelf/shelf_button_host.h"
#include "ash/shelf/shelf_item_types.h"
#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_view.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "base/command_line.h"
@@ -19,27 +18,15 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_switches_util.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animation_element.h"
-#include "ui/compositor/layer_animation_sequence.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/views/controls/button/image_button.h"
#include "ui/views/painter.h"
namespace ash {
-// static
-const int AppListButton::kImageBoundsSize = 7;
-
-AppListButton::AppListButton(views::ButtonListener* listener,
- ShelfButtonHost* host,
- ShelfWidget* shelf_widget)
- : views::ImageButton(listener),
+AppListButton::AppListButton(ShelfView* shelf_view)
+ : views::ImageButton(shelf_view),
draw_background_as_active_(false),
- host_(host),
- shelf_widget_(shelf_widget) {
+ shelf_view_(shelf_view) {
SetAccessibleName(
app_list::switches::IsExperimentalAppListEnabled()
? l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE)
@@ -50,61 +37,45 @@ AppListButton::AppListButton(views::ButtonListener* listener,
set_notify_action(CustomButton::NOTIFY_ON_PRESS);
}
-AppListButton::~AppListButton() {
-}
+AppListButton::~AppListButton() {}
bool AppListButton::OnMousePressed(const ui::MouseEvent& event) {
ImageButton::OnMousePressed(event);
- host_->PointerPressedOnButton(this, ShelfButtonHost::MOUSE, event);
+ shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event);
return true;
}
void AppListButton::OnMouseReleased(const ui::MouseEvent& event) {
ImageButton::OnMouseReleased(event);
- host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false);
}
void AppListButton::OnMouseCaptureLost() {
- host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, true);
+ shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, true);
ImageButton::OnMouseCaptureLost();
}
bool AppListButton::OnMouseDragged(const ui::MouseEvent& event) {
ImageButton::OnMouseDragged(event);
- host_->PointerDraggedOnButton(this, ShelfButtonHost::MOUSE, event);
+ shelf_view_->PointerDraggedOnButton(this, ShelfView::MOUSE, event);
return true;
}
-void AppListButton::OnMouseMoved(const ui::MouseEvent& event) {
- ImageButton::OnMouseMoved(event);
- host_->MouseMovedOverButton(this);
-}
-
-void AppListButton::OnMouseEntered(const ui::MouseEvent& event) {
- ImageButton::OnMouseEntered(event);
- host_->MouseEnteredButton(this);
-}
-
-void AppListButton::OnMouseExited(const ui::MouseEvent& event) {
- ImageButton::OnMouseExited(event);
- host_->MouseExitedButton(this);
-}
-
void AppListButton::OnGestureEvent(ui::GestureEvent* event) {
switch (event->type()) {
case ui::ET_GESTURE_SCROLL_BEGIN:
if (switches::IsTouchFeedbackEnabled())
SetDrawBackgroundAsActive(false);
- host_->PointerPressedOnButton(this, ShelfButtonHost::TOUCH, *event);
+ shelf_view_->PointerPressedOnButton(this, ShelfView::TOUCH, *event);
event->SetHandled();
return;
case ui::ET_GESTURE_SCROLL_UPDATE:
- host_->PointerDraggedOnButton(this, ShelfButtonHost::TOUCH, *event);
+ shelf_view_->PointerDraggedOnButton(this, ShelfView::TOUCH, *event);
event->SetHandled();
return;
case ui::ET_GESTURE_SCROLL_END:
case ui::ET_SCROLL_FLING_START:
- host_->PointerReleasedOnButton(this, ShelfButtonHost::TOUCH, false);
+ shelf_view_->PointerReleasedOnButton(this, ShelfView::TOUCH, false);
event->SetHandled();
return;
case ui::ET_GESTURE_TAP_DOWN:
@@ -133,7 +104,7 @@ void AppListButton::OnPaint(gfx::Canvas* canvas) {
draw_background_as_active_) {
background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
} else {
- if (shelf_widget_->GetDimsShelf())
+ if (shelf_view_->shelf()->shelf_widget()->GetDimsShelf())
background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
else
background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
@@ -152,7 +123,7 @@ void AppListButton::OnPaint(gfx::Canvas* canvas) {
gfx::Rect contents_bounds = GetContentsBounds();
gfx::Rect background_bounds, forground_bounds;
- ShelfAlignment alignment = shelf_widget_->GetAlignment();
+ ShelfAlignment alignment = shelf_view_->shelf()->alignment();
background_bounds.set_size(background_image->size());
if (alignment == SHELF_ALIGNMENT_LEFT) {
background_bounds.set_x(contents_bounds.width() -
@@ -189,7 +160,7 @@ void AppListButton::OnPaint(gfx::Canvas* canvas) {
void AppListButton::GetAccessibleState(ui::AXViewState* state) {
state->role = ui::AX_ROLE_BUTTON;
- state->name = host_->GetAccessibleName(this);
+ state->name = shelf_view_->GetTitleForView(this);
}
void AppListButton::SetDrawBackgroundAsActive(
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h
index e0e5cd8..52fafe6 100644
--- a/ash/shelf/app_list_button.h
+++ b/ash/shelf/app_list_button.h
@@ -9,23 +9,15 @@
#include "ui/views/controls/button/image_button.h"
namespace ash {
-class ShelfButtonHost;
-class ShelfWidget;
+class ShelfView;
// Button used for the AppList icon on the shelf.
class AppListButton : public views::ImageButton {
public:
- // Bounds size (inset) required for the app icon image (in pixels).
- static const int kImageBoundsSize;
-
- AppListButton(views::ButtonListener* listener,
- ShelfButtonHost* host,
- ShelfWidget* shelf_widget);
+ explicit AppListButton(ShelfView* shelf_view);
~AppListButton() override;
- bool draw_background_as_active() {
- return draw_background_as_active_;
- }
+ bool draw_background_as_active() { return draw_background_as_active_; }
protected:
// views::ImageButton overrides:
@@ -33,9 +25,6 @@ class AppListButton : public views::ImageButton {
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnMouseCaptureLost() override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
- void OnMouseMoved(const ui::MouseEvent& event) override;
- void OnMouseEntered(const ui::MouseEvent& event) override;
- void OnMouseExited(const ui::MouseEvent& event) override;
void OnPaint(gfx::Canvas* canvas) override;
void GetAccessibleState(ui::AXViewState* state) override;
@@ -50,10 +39,7 @@ class AppListButton : public views::ImageButton {
// the application list.
bool draw_background_as_active_;
- ShelfButtonHost* host_;
- // Reference to the shelf widget containing this button, owned by the
- // root window controller.
- ShelfWidget* shelf_widget_;
+ ShelfView* shelf_view_;
DISALLOW_COPY_AND_ASSIGN(AppListButton);
};
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc
index 5d44aa5..ff7b139 100644
--- a/ash/shelf/shelf_button.cc
+++ b/ash/shelf/shelf_button.cc
@@ -9,7 +9,7 @@
#include "ash/ash_constants.h"
#include "ash/ash_switches.h"
#include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_button_host.h"
+#include "ash/shelf/shelf_view.h"
#include "base/time/time.h"
#include "grit/ash_resources.h"
#include "skia/ext/image_operations.h"
@@ -115,8 +115,8 @@ namespace ash {
class ShelfButton::BarView : public views::ImageView,
public ShelfButtonAnimation::Observer {
public:
- BarView(ShelfButton* host)
- : host_(host),
+ BarView(Shelf* shelf)
+ : shelf_(shelf),
show_attention_(false),
animation_end_time_(base::TimeTicks()),
animating_(false) {
@@ -180,7 +180,7 @@ class ShelfButton::BarView : public views::ImageView,
double animation = animating_ ?
ShelfButtonAnimation::GetInstance()->GetAnimation() : 1.0;
double scale = .35 + .65 * animation;
- if (host_->shelf()->alignment() == SHELF_ALIGNMENT_BOTTOM) {
+ if (shelf_->alignment() == SHELF_ALIGNMENT_BOTTOM) {
int width = base_bounds_.width() * scale;
bounds.set_width(std::min(width, kIconSize));
int x_offset = (base_bounds_.width() - bounds.width()) / 2;
@@ -206,7 +206,7 @@ class ShelfButton::BarView : public views::ImageView,
}
}
- ShelfButton* host_;
+ Shelf* shelf_;
bool show_attention_;
base::TimeTicks animation_end_time_; // For attention throbbing underline.
bool animating_; // Is time-limited attention animation running?
@@ -216,41 +216,18 @@ class ShelfButton::BarView : public views::ImageView,
};
////////////////////////////////////////////////////////////////////////////////
-// ShelfButton::IconView
-
-ShelfButton::IconView::IconView() : icon_size_(kIconSize) {
- // Do not make this interactive, so that events are sent to ShelfView for
- // handling.
- set_interactive(false);
-}
-
-ShelfButton::IconView::~IconView() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
// ShelfButton
// static
const char ShelfButton::kViewClassName[] = "ash/ShelfButton";
-ShelfButton* ShelfButton::Create(views::ButtonListener* listener,
- ShelfButtonHost* host,
- Shelf* shelf) {
- ShelfButton* button = new ShelfButton(listener, host, shelf);
- button->Init();
- return button;
-}
-
-ShelfButton::ShelfButton(views::ButtonListener* listener,
- ShelfButtonHost* host,
- Shelf* shelf)
- : CustomButton(listener),
- host_(host),
- icon_view_(NULL),
- bar_(new BarView(this)),
+ShelfButton::ShelfButton(ShelfView* shelf_view)
+ : CustomButton(shelf_view),
+ shelf_view_(shelf_view),
+ icon_view_(new views::ImageView()),
+ bar_(new BarView(shelf_view->shelf())),
state_(STATE_NORMAL),
- shelf_(shelf),
- destroyed_flag_(NULL) {
+ destroyed_flag_(nullptr) {
SetAccessibilityFocusable(true);
const gfx::ShadowValue kShadows[] = {
@@ -260,7 +237,16 @@ ShelfButton::ShelfButton(views::ButtonListener* listener,
};
icon_shadows_.assign(kShadows, kShadows + arraysize(kShadows));
+ // TODO: refactor the layers so each button doesn't require 2.
+ icon_view_->SetPaintToLayer(true);
+ icon_view_->layer()->SetFillsBoundsOpaquely(false);
+ icon_view_->SetHorizontalAlignment(views::ImageView::CENTER);
+ icon_view_->SetVerticalAlignment(views::ImageView::LEADING);
+ // Do not make this interactive, so that events are sent to ShelfView.
+ icon_view_->set_interactive(false);
+
AddChildView(bar_);
+ AddChildView(icon_view_);
}
ShelfButton::~ShelfButton() {
@@ -280,19 +266,13 @@ void ShelfButton::SetImage(const gfx::ImageSkia& image) {
return;
}
- if (icon_view_->icon_size() == 0) {
- SetShadowedImage(image);
- return;
- }
-
// Resize the image maintaining our aspect ratio.
- int pref = icon_view_->icon_size();
float aspect_ratio =
static_cast<float>(image.width()) / static_cast<float>(image.height());
- int height = pref;
+ int height = kIconSize;
int width = static_cast<int>(aspect_ratio * height);
- if (width > pref) {
- width = pref;
+ if (width > kIconSize) {
+ width = kIconSize;
height = static_cast<int>(width / aspect_ratio);
}
@@ -342,7 +322,7 @@ void ShelfButton::ShowContextMenu(const gfx::Point& p,
CustomButton::ShowContextMenu(p, source_type);
if (!destroyed) {
- destroyed_flag_ = NULL;
+ destroyed_flag_ = nullptr;
// The menu will not propagate mouse events while its shown. To address,
// the hover state gets cleared once the menu was shown (and this was not
// destroyed).
@@ -356,71 +336,53 @@ const char* ShelfButton::GetClassName() const {
bool ShelfButton::OnMousePressed(const ui::MouseEvent& event) {
CustomButton::OnMousePressed(event);
- host_->PointerPressedOnButton(this, ShelfButtonHost::MOUSE, event);
+ shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event);
return true;
}
void ShelfButton::OnMouseReleased(const ui::MouseEvent& event) {
CustomButton::OnMouseReleased(event);
- host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false);
}
void ShelfButton::OnMouseCaptureLost() {
ClearState(STATE_HOVERED);
- host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, true);
+ shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, true);
CustomButton::OnMouseCaptureLost();
}
bool ShelfButton::OnMouseDragged(const ui::MouseEvent& event) {
CustomButton::OnMouseDragged(event);
- host_->PointerDraggedOnButton(this, ShelfButtonHost::MOUSE, event);
+ shelf_view_->PointerDraggedOnButton(this, ShelfView::MOUSE, event);
return true;
}
-void ShelfButton::OnMouseMoved(const ui::MouseEvent& event) {
- CustomButton::OnMouseMoved(event);
- host_->MouseMovedOverButton(this);
-}
-
-void ShelfButton::OnMouseEntered(const ui::MouseEvent& event) {
- AddState(STATE_HOVERED);
- CustomButton::OnMouseEntered(event);
- host_->MouseEnteredButton(this);
-}
-
-void ShelfButton::OnMouseExited(const ui::MouseEvent& event) {
- ClearState(STATE_HOVERED);
- CustomButton::OnMouseExited(event);
- host_->MouseExitedButton(this);
-}
-
void ShelfButton::GetAccessibleState(ui::AXViewState* state) {
state->role = ui::AX_ROLE_BUTTON;
- state->name = host_->GetAccessibleName(this);
+ state->name = shelf_view_->GetTitleForView(this);
}
void ShelfButton::Layout() {
const gfx::Rect button_bounds(GetContentsBounds());
- int icon_pad = shelf_->IsHorizontalAlignment() ? kIconPad : kIconPadVertical;
- int x_offset = shelf_->PrimaryAxisValue(0, icon_pad);
- int y_offset = shelf_->PrimaryAxisValue(icon_pad, 0);
+ Shelf* shelf = shelf_view_->shelf();
+ int icon_pad = shelf->PrimaryAxisValue(kIconPad, kIconPadVertical);
+ int x_offset = shelf->PrimaryAxisValue(0, icon_pad);
+ int y_offset = shelf->PrimaryAxisValue(icon_pad, 0);
- int icon_width = std::min(kIconSize,
- button_bounds.width() - x_offset);
- int icon_height = std::min(kIconSize,
- button_bounds.height() - y_offset);
+ int icon_width = std::min(kIconSize, button_bounds.width() - x_offset);
+ int icon_height = std::min(kIconSize, button_bounds.height() - y_offset);
// If on the left or top 'invert' the inset so the constant gap is on
// the interior (towards the center of display) edge of the shelf.
- if (SHELF_ALIGNMENT_LEFT == shelf_->alignment())
+ if (SHELF_ALIGNMENT_LEFT == shelf->alignment())
x_offset = button_bounds.width() - (kIconSize + icon_pad);
- if (SHELF_ALIGNMENT_TOP == shelf_->alignment())
+ if (SHELF_ALIGNMENT_TOP == shelf->alignment())
y_offset = button_bounds.height() - (kIconSize + icon_pad);
// Center icon with respect to the secondary axis, and ensure
// that the icon doesn't occlude the bar highlight.
- if (shelf_->IsHorizontalAlignment()) {
+ if (shelf->IsHorizontalAlignment()) {
x_offset = std::max(0, button_bounds.width() - icon_width) / 2;
if (y_offset + icon_height + kBarSize > button_bounds.height())
icon_height = button_bounds.height() - (y_offset + kBarSize);
@@ -484,16 +446,16 @@ void ShelfButton::OnGestureEvent(ui::GestureEvent* event) {
ClearState(STATE_HOVERED);
return CustomButton::OnGestureEvent(event);
case ui::ET_GESTURE_SCROLL_BEGIN:
- host_->PointerPressedOnButton(this, ShelfButtonHost::TOUCH, *event);
+ shelf_view_->PointerPressedOnButton(this, ShelfView::TOUCH, *event);
event->SetHandled();
return;
case ui::ET_GESTURE_SCROLL_UPDATE:
- host_->PointerDraggedOnButton(this, ShelfButtonHost::TOUCH, *event);
+ shelf_view_->PointerDraggedOnButton(this, ShelfView::TOUCH, *event);
event->SetHandled();
return;
case ui::ET_GESTURE_SCROLL_END:
case ui::ET_SCROLL_FLING_START:
- host_->PointerReleasedOnButton(this, ShelfButtonHost::TOUCH, false);
+ shelf_view_->PointerReleasedOnButton(this, ShelfView::TOUCH, false);
event->SetHandled();
return;
default:
@@ -501,28 +463,12 @@ void ShelfButton::OnGestureEvent(ui::GestureEvent* event) {
}
}
-void ShelfButton::Init() {
- icon_view_ = CreateIconView();
-
- // TODO: refactor the layers so each button doesn't require 2.
- icon_view_->SetPaintToLayer(true);
- icon_view_->layer()->SetFillsBoundsOpaquely(false);
- icon_view_->SetHorizontalAlignment(views::ImageView::CENTER);
- icon_view_->SetVerticalAlignment(views::ImageView::LEADING);
-
- AddChildView(icon_view_);
-}
-
-ShelfButton::IconView* ShelfButton::CreateIconView() {
- return new IconView;
-}
-
void ShelfButton::UpdateState() {
UpdateBar();
-
- icon_view_->SetHorizontalAlignment(shelf_->PrimaryAxisValue(
+ Shelf* shelf = shelf_view_->shelf();
+ icon_view_->SetHorizontalAlignment(shelf->PrimaryAxisValue(
views::ImageView::CENTER, views::ImageView::LEADING));
- icon_view_->SetVerticalAlignment(shelf_->PrimaryAxisValue(
+ icon_view_->SetVerticalAlignment(shelf->PrimaryAxisValue(
views::ImageView::LEADING, views::ImageView::CENTER));
SchedulePaint();
}
@@ -544,20 +490,22 @@ void ShelfButton::UpdateBar() {
if (bar_id != 0) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
const gfx::ImageSkia* image = rb.GetImageNamed(bar_id).ToImageSkia();
- if (shelf_->alignment() == SHELF_ALIGNMENT_BOTTOM) {
+
+ Shelf* shelf = shelf_view_->shelf();
+ if (shelf->alignment() == SHELF_ALIGNMENT_BOTTOM) {
bar_->SetImage(*image);
} else {
bar_->SetImage(gfx::ImageSkiaOperations::CreateRotatedImage(
- *image, shelf_->SelectValueForShelfAlignment(
+ *image, shelf->SelectValueForShelfAlignment(
SkBitmapOperations::ROTATION_90_CW,
SkBitmapOperations::ROTATION_90_CW,
SkBitmapOperations::ROTATION_270_CW,
SkBitmapOperations::ROTATION_180_CW)));
}
- bar_->SetHorizontalAlignment(shelf_->SelectValueForShelfAlignment(
+ bar_->SetHorizontalAlignment(shelf->SelectValueForShelfAlignment(
views::ImageView::CENTER, views::ImageView::LEADING,
views::ImageView::TRAILING, views::ImageView::CENTER));
- bar_->SetVerticalAlignment(shelf_->SelectValueForShelfAlignment(
+ bar_->SetVerticalAlignment(shelf->SelectValueForShelfAlignment(
views::ImageView::TRAILING, views::ImageView::CENTER,
views::ImageView::CENTER, views::ImageView::LEADING));
bar_->SchedulePaint();
diff --git a/ash/shelf/shelf_button.h b/ash/shelf/shelf_button.h
index 4e63e9e..4a84a61 100644
--- a/ash/shelf/shelf_button.h
+++ b/ash/shelf/shelf_button.h
@@ -12,8 +12,7 @@
#include "ui/views/controls/image_view.h"
namespace ash {
-class Shelf;
-class ShelfButtonHost;
+class ShelfView;
// Button used for items on the launcher, except for the AppList.
class ASH_EXPORT ShelfButton : public views::CustomButton {
@@ -38,13 +37,9 @@ class ASH_EXPORT ShelfButton : public views::CustomButton {
STATE_HIDDEN = 1 << 5,
};
+ explicit ShelfButton(ShelfView* shelf_view);
~ShelfButton() override;
- // Called to create an instance of a ShelfButton.
- static ShelfButton* Create(views::ButtonListener* listener,
- ShelfButtonHost* host,
- Shelf* shelf);
-
// Sets the image to display for this entry.
void SetImage(const gfx::ImageSkia& image);
@@ -55,7 +50,6 @@ class ASH_EXPORT ShelfButton : public views::CustomButton {
void AddState(State state);
void ClearState(State state);
int state() const { return state_; }
- const Shelf* shelf() const { return shelf_; }
// Returns the bounds of the icon.
gfx::Rect GetIconBounds() const;
@@ -68,37 +62,11 @@ class ASH_EXPORT ShelfButton : public views::CustomButton {
void OnMouseCaptureLost() override;
protected:
- ShelfButton(views::ButtonListener* listener,
- ShelfButtonHost* host,
- Shelf* shelf);
-
- // Class that draws the icon part of a button, so it can be animated
- // independently of the rest. This can be subclassed to provide a custom
- // implementation, by overriding CreateIconView().
- class IconView : public views::ImageView {
- public:
- IconView();
- ~IconView() override;
-
- void set_icon_size(int icon_size) { icon_size_ = icon_size; }
- int icon_size() const { return icon_size_; }
-
- private:
- // Set to non-zero to force icons to be resized to fit within a square,
- // while maintaining original proportions.
- int icon_size_;
-
- DISALLOW_COPY_AND_ASSIGN(IconView);
- };
-
// View overrides:
const char* GetClassName() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
- void OnMouseMoved(const ui::MouseEvent& event) override;
- void OnMouseEntered(const ui::MouseEvent& event) override;
- void OnMouseExited(const ui::MouseEvent& event) override;
void GetAccessibleState(ui::AXViewState* state) override;
void Layout() override;
void ChildPreferredSizeChanged(views::View* child) override;
@@ -111,12 +79,6 @@ class ASH_EXPORT ShelfButton : public views::CustomButton {
// Sets the icon image with a shadow.
void SetShadowedImage(const gfx::ImageSkia& bitmap);
- // Override for custom initialization.
- virtual void Init();
- // Override to subclass IconView.
- virtual IconView* CreateIconView();
- IconView* icon_view() const { return icon_view_; }
- ShelfButtonHost* host() const { return host_; }
private:
class BarView;
@@ -128,15 +90,17 @@ class ASH_EXPORT ShelfButton : public views::CustomButton {
// Updates the status bar (bitmap, orientation, visibility).
void UpdateBar();
- ShelfButtonHost* host_;
- IconView* icon_view_;
+ // The shelf view hosting this button.
+ ShelfView* shelf_view_;
+
+ // The icon part of a button can be animated independently of the rest.
+ views::ImageView* icon_view_;
+
// Draws a bar underneath the image to represent the state of the application.
BarView* bar_;
- // The current state of the application, multiple values of AppState are or'd
- // together.
- int state_;
- Shelf* shelf_;
+ // The current application state, a bitfield of State enum values.
+ int state_;
gfx::ShadowValues icon_shadows_;
diff --git a/ash/shelf/shelf_button_host.h b/ash/shelf/shelf_button_host.h
deleted file mode 100644
index b664c7f..0000000
--- a/ash/shelf/shelf_button_host.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 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_SHELF_SHELF_BUTTON_HOST_H_
-#define ASH_SHELF_SHELF_BUTTON_HOST_H_
-
-#include "ash/ash_export.h"
-#include "base/strings/string16.h"
-
-namespace ui {
-class LocatedEvent;
-}
-
-namespace views {
-class View;
-}
-
-namespace ash {
-
-// The shelf buttons communicate back to the host by way of this interface.
-// This interface is used to enable reordering the items on the shelf.
-class ASH_EXPORT ShelfButtonHost {
- public:
- enum Pointer {
- NONE,
- DRAG_AND_DROP,
- MOUSE,
- TOUCH,
- };
-
- // Invoked when a pointer device is pressed on a view.
- virtual void PointerPressedOnButton(views::View* view,
- Pointer pointer,
- const ui::LocatedEvent& event) = 0;
-
- // Invoked when a pointer device is dragged over a view.
- virtual void PointerDraggedOnButton(views::View* view,
- Pointer pointer,
- const ui::LocatedEvent& event) = 0;
-
- // Invoked either if a pointer device is released or mouse capture canceled.
- virtual void PointerReleasedOnButton(views::View* view,
- Pointer pointer,
- bool canceled) = 0;
-
- // Invoked when the mouse moves on the item.
- virtual void MouseMovedOverButton(views::View* view) = 0;
-
- // Invoked when the mouse enters the item.
- virtual void MouseEnteredButton(views::View* view) = 0;
-
- // Invoked when the mouse exits the item.
- virtual void MouseExitedButton(views::View* view) = 0;
-
- // Invoked to get the accessible name of the item.
- virtual base::string16 GetAccessibleName(const views::View* view) = 0;
-
- protected:
- virtual ~ShelfButtonHost() {}
-};
-
-} // namespace ash
-
-#endif // ASH_SHELF_SHELF_BUTTON_HOST_H_
diff --git a/ash/shelf/shelf_tooltip_manager.cc b/ash/shelf/shelf_tooltip_manager.cc
index 3252ae1c..5e25fb2 100644
--- a/ash/shelf/shelf_tooltip_manager.cc
+++ b/ash/shelf/shelf_tooltip_manager.cc
@@ -13,14 +13,11 @@
#include "base/bind.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/bubble/bubble_delegate.h"
-#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
@@ -50,36 +47,24 @@ class ShelfTooltipManager::ShelfTooltipBubble
: public views::BubbleDelegateView {
public:
ShelfTooltipBubble(views::View* anchor,
- views::BubbleBorder::Arrow arrow,
- ShelfTooltipManager* host);
-
- void SetText(const base::string16& text);
- void Close();
+ views::BubbleBorder::Arrow arrow,
+ const base::string16& text);
private:
- // views::WidgetDelegate overrides:
- void WindowClosing() override;
-
// views::View overrides:
gfx::Size GetPreferredSize() const override;
- ShelfTooltipManager* host_;
- views::Label* label_;
-
DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble);
};
ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble(
views::View* anchor,
views::BubbleBorder::Arrow arrow,
- ShelfTooltipManager* host)
- : views::BubbleDelegateView(anchor, arrow), host_(host) {
+ const base::string16& text)
+ : views::BubbleDelegateView(anchor, arrow) {
gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom,
- kArrowOffsetLeftRight,
- kArrowOffsetTopBottom,
kArrowOffsetLeftRight);
- // Shelf items can have an asymmetrical border for spacing reasons.
- // Adjust anchor location for this.
+ // Adjust the anchor location for asymmetrical borders of shelf item.
if (anchor->border())
insets += anchor->border()->GetInsets();
@@ -88,286 +73,151 @@ ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble(
set_close_on_deactivate(false);
set_can_activate(false);
set_accept_events(false);
- set_margins(gfx::Insets(kTooltipTopBottomMargin, kTooltipLeftRightMargin,
- kTooltipTopBottomMargin, kTooltipLeftRightMargin));
+ set_margins(gfx::Insets(kTooltipTopBottomMargin, kTooltipLeftRightMargin));
set_shadow(views::BubbleBorder::SMALL_SHADOW);
SetLayoutManager(new views::FillLayout());
// The anchor may not have the widget in tests.
- if (anchor->GetWidget() && anchor->GetWidget()->GetNativeView()) {
- aura::Window* root_window =
- anchor->GetWidget()->GetNativeView()->GetRootWindow();
- set_parent_window(ash::Shell::GetInstance()->GetContainer(
- root_window, ash::kShellWindowId_SettingBubbleContainer));
+ if (anchor->GetWidget() && anchor->GetWidget()->GetNativeWindow()) {
+ set_parent_window(ash::Shell::GetContainer(
+ anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
+ ash::kShellWindowId_SettingBubbleContainer));
}
- label_ = new views::Label;
- label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- label_->SetEnabledColor(kTooltipTextColor);
- AddChildView(label_);
+ views::Label* label = new views::Label(text);
+ label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ label->SetEnabledColor(kTooltipTextColor);
+ AddChildView(label);
views::BubbleDelegateView::CreateBubble(this);
-}
-
-void ShelfTooltipManager::ShelfTooltipBubble::SetText(
- const base::string16& text) {
- label_->SetText(text);
SizeToContents();
}
-void ShelfTooltipManager::ShelfTooltipBubble::Close() {
- if (GetWidget()) {
- host_ = NULL;
- GetWidget()->Close();
- }
-}
-
-void ShelfTooltipManager::ShelfTooltipBubble::WindowClosing() {
- views::BubbleDelegateView::WindowClosing();
- if (host_)
- host_->OnBubbleClosed(this);
-}
-
gfx::Size ShelfTooltipManager::ShelfTooltipBubble::GetPreferredSize() const {
- gfx::Size pref_size = views::BubbleDelegateView::GetPreferredSize();
- if (pref_size.height() < kTooltipMinHeight)
- pref_size.set_height(kTooltipMinHeight);
- if (pref_size.width() > kTooltipMaxWidth)
- pref_size.set_width(kTooltipMaxWidth);
- return pref_size;
+ const gfx::Size size = views::BubbleDelegateView::GetPreferredSize();
+ return gfx::Size(std::min(size.width(), kTooltipMaxWidth),
+ std::max(size.height(), kTooltipMinHeight));
}
-ShelfTooltipManager::ShelfTooltipManager(
- ShelfLayoutManager* shelf_layout_manager,
- ShelfView* shelf_view)
- : view_(NULL),
- widget_(NULL),
- anchor_(NULL),
- shelf_layout_manager_(shelf_layout_manager),
+ShelfTooltipManager::ShelfTooltipManager(ShelfView* shelf_view)
+ : timer_delay_(kTooltipAppearanceDelay),
shelf_view_(shelf_view),
- weak_factory_(this) {
- if (shelf_layout_manager)
- shelf_layout_manager->AddObserver(this);
- if (Shell::HasInstance())
- Shell::GetInstance()->AddPreTargetHandler(this);
-}
+ shelf_layout_manager_(nullptr),
+ bubble_(nullptr),
+ weak_factory_(this) {}
ShelfTooltipManager::~ShelfTooltipManager() {
- CancelHidingAnimation();
- Close();
- if (shelf_layout_manager_)
- shelf_layout_manager_->RemoveObserver(this);
- if (Shell::HasInstance())
- Shell::GetInstance()->RemovePreTargetHandler(this);
+ WillDeleteShelf();
}
-void ShelfTooltipManager::ShowDelayed(views::View* anchor,
- const base::string16& text) {
- if (view_) {
- if (timer_.get() && timer_->IsRunning()) {
- return;
- } else {
- CancelHidingAnimation();
- Close();
- }
- }
-
- if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible())
- return;
-
- CreateBubble(anchor, text);
- ResetTimer();
-}
-
-void ShelfTooltipManager::ShowImmediately(views::View* anchor,
- const base::string16& text) {
- if (view_) {
- if (timer_.get() && timer_->IsRunning())
- StopTimer();
- CancelHidingAnimation();
- Close();
- }
-
- if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible())
- return;
-
- CreateBubble(anchor, text);
- ShowInternal();
+void ShelfTooltipManager::Init() {
+ shelf_layout_manager_ = shelf_view_->shelf()->shelf_layout_manager();
+ shelf_layout_manager_->AddObserver(this);
+ // TODO(msw): Capture events outside the shelf to close tooltips?
+ shelf_view_->GetWidget()->GetNativeWindow()->AddPreTargetHandler(this);
}
void ShelfTooltipManager::Close() {
- StopTimer();
- if (view_) {
- view_->Close();
- view_ = NULL;
- widget_ = NULL;
- }
+ timer_.Stop();
+ if (bubble_)
+ bubble_->GetWidget()->Close();
+ bubble_ = nullptr;
}
-void ShelfTooltipManager::OnBubbleClosed(views::BubbleDelegateView* view) {
- if (view == view_) {
- view_ = NULL;
- widget_ = NULL;
- }
+bool ShelfTooltipManager::IsVisible() const {
+ return bubble_ && bubble_->GetWidget()->IsVisible();
}
-void ShelfTooltipManager::UpdateArrow() {
- if (view_) {
- CancelHidingAnimation();
- Close();
- ShowImmediately(anchor_, text_);
- }
+views::View* ShelfTooltipManager::GetCurrentAnchorView() const {
+ return bubble_ ? bubble_->GetAnchorView() : nullptr;
}
-void ShelfTooltipManager::ResetTimer() {
- if (timer_.get() && timer_->IsRunning()) {
- timer_->Reset();
- return;
+void ShelfTooltipManager::ShowTooltip(views::View* view) {
+ timer_.Stop();
+ if (bubble_) {
+ // Cancel the hiding animation to hide the old bubble immediately.
+ gfx::NativeView native_view = bubble_->GetWidget()->GetNativeView();
+ wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_NONE);
+ Close();
}
- // We don't start the timer if the shelf isn't visible.
if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible())
return;
- CreateTimer(kTooltipAppearanceDelay);
-}
-
-void ShelfTooltipManager::StopTimer() {
- timer_.reset();
-}
-
-bool ShelfTooltipManager::IsVisible() {
- if (timer_.get() && timer_->IsRunning())
- return false;
+ Shelf* shelf = shelf_view_->shelf();
+ views::BubbleBorder::Arrow arrow = shelf->SelectValueForShelfAlignment(
+ views::BubbleBorder::BOTTOM_CENTER, views::BubbleBorder::LEFT_CENTER,
+ views::BubbleBorder::RIGHT_CENTER, views::BubbleBorder::TOP_CENTER);
- return widget_ && widget_->IsVisible();
+ base::string16 text = shelf_view_->GetTitleForView(view);
+ bubble_ = new ShelfTooltipBubble(view, arrow, text);
+ gfx::NativeView native_view = bubble_->GetWidget()->GetNativeView();
+ wm::SetWindowVisibilityAnimationType(
+ native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL);
+ wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_HIDE);
+ bubble_->GetWidget()->Show();
}
-void ShelfTooltipManager::CreateZeroDelayTimerForTest() {
- CreateTimer(0);
+void ShelfTooltipManager::ShowTooltipWithDelay(views::View* view) {
+ if (!shelf_layout_manager_ || shelf_layout_manager_->IsVisible()) {
+ timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(timer_delay_),
+ base::Bind(&ShelfTooltipManager::ShowTooltip,
+ weak_factory_.GetWeakPtr(), view));
+ }
}
-void ShelfTooltipManager::OnMouseEvent(ui::MouseEvent* event) {
- DCHECK(event);
- DCHECK(event->target());
- if (!widget_ || !widget_->IsVisible())
- return;
-
- DCHECK(view_);
- DCHECK(shelf_view_);
-
- // Pressing the mouse button anywhere should close the tooltip.
- if (event->type() == ui::ET_MOUSE_PRESSED) {
- CloseSoon();
+void ShelfTooltipManager::OnEvent(ui::Event* event) {
+ // Close the tooltip on mouse press or exit, and on most non-mouse events.
+ if (event->type() == ui::ET_MOUSE_PRESSED ||
+ event->type() == ui::ET_MOUSE_EXITED || !event->IsMouseEvent()) {
+ if (!event->IsKeyEvent())
+ Close();
return;
}
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (widget_->GetNativeWindow()->GetRootWindow() != target->GetRootWindow()) {
- CloseSoon();
+ gfx::Point point = static_cast<ui::LocatedEvent*>(event)->location();
+ views::View::ConvertPointFromWidget(shelf_view_, &point);
+ if (IsVisible() && shelf_view_->ShouldHideTooltip(point)) {
+ Close();
return;
}
- gfx::Point location_in_shelf_view = event->location();
- aura::Window::ConvertPointToTarget(
- target, shelf_view_->GetWidget()->GetNativeWindow(),
- &location_in_shelf_view);
-
- if (shelf_view_->ShouldHideTooltip(location_in_shelf_view)) {
- // Because this mouse event may arrive to |view_|, here we just schedule
- // the closing event rather than directly calling Close().
- CloseSoon();
- }
-}
-
-void ShelfTooltipManager::OnTouchEvent(ui::TouchEvent* event) {
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (widget_ && widget_->IsVisible() && widget_->GetNativeWindow() != target)
- Close();
-}
+ views::View* view = shelf_view_->GetTooltipHandlerForPoint(point);
+ const bool should_show = shelf_view_->ShouldShowTooltipForView(view);
+ if (IsVisible() && bubble_->GetAnchorView() != view && should_show)
+ ShowTooltip(view);
-void ShelfTooltipManager::OnGestureEvent(ui::GestureEvent* event) {
- if (widget_ && widget_->IsVisible()) {
- // Because this mouse event may arrive to |view_|, here we just schedule
- // the closing event rather than directly calling Close().
- CloseSoon();
+ if (!IsVisible() && event->type() == ui::ET_MOUSE_MOVED) {
+ timer_.Stop();
+ if (should_show)
+ ShowTooltipWithDelay(view);
}
}
-void ShelfTooltipManager::OnCancelMode(ui::CancelModeEvent* event) {
- Close();
-}
-
void ShelfTooltipManager::WillDeleteShelf() {
- shelf_layout_manager_ = NULL;
+ if (shelf_layout_manager_)
+ shelf_layout_manager_->RemoveObserver(this);
+ shelf_layout_manager_ = nullptr;
+
+ views::Widget* widget = shelf_view_ ? shelf_view_->GetWidget() : nullptr;
+ if (widget && widget->GetNativeWindow())
+ widget->GetNativeWindow()->RemovePreTargetHandler(this);
+ shelf_view_ = nullptr;
}
void ShelfTooltipManager::WillChangeVisibilityState(
ShelfVisibilityState new_state) {
- if (new_state == SHELF_HIDDEN) {
- StopTimer();
+ if (new_state == SHELF_HIDDEN)
Close();
- }
}
void ShelfTooltipManager::OnAutoHideStateChanged(ShelfAutoHideState new_state) {
if (new_state == SHELF_AUTO_HIDE_HIDDEN) {
- StopTimer();
+ timer_.Stop();
// AutoHide state change happens during an event filter, so immediate close
// may cause a crash in the HandleMouseEvent() after the filter. So we just
// schedule the Close here.
- CloseSoon();
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&ShelfTooltipManager::Close, weak_factory_.GetWeakPtr()));
}
}
-void ShelfTooltipManager::CancelHidingAnimation() {
- if (!widget_ || !widget_->GetNativeView())
- return;
-
- gfx::NativeView native_view = widget_->GetNativeView();
- wm::SetWindowVisibilityAnimationTransition(
- native_view, wm::ANIMATE_NONE);
-}
-
-void ShelfTooltipManager::CloseSoon() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&ShelfTooltipManager::Close, weak_factory_.GetWeakPtr()));
-}
-
-void ShelfTooltipManager::ShowInternal() {
- if (view_)
- view_->GetWidget()->Show();
-
- timer_.reset();
-}
-
-void ShelfTooltipManager::CreateBubble(views::View* anchor,
- const base::string16& text) {
- DCHECK(!view_);
-
- anchor_ = anchor;
- text_ = text;
- Shelf* shelf = shelf_layout_manager_->shelf_widget()->shelf();
- views::BubbleBorder::Arrow arrow = shelf->SelectValueForShelfAlignment(
- views::BubbleBorder::BOTTOM_CENTER, views::BubbleBorder::LEFT_CENTER,
- views::BubbleBorder::RIGHT_CENTER, views::BubbleBorder::TOP_CENTER);
-
- view_ = new ShelfTooltipBubble(anchor, arrow, this);
- widget_ = view_->GetWidget();
- view_->SetText(text_);
-
- gfx::NativeView native_view = widget_->GetNativeView();
- wm::SetWindowVisibilityAnimationType(
- native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL);
- wm::SetWindowVisibilityAnimationTransition(
- native_view, wm::ANIMATE_HIDE);
-}
-
-void ShelfTooltipManager::CreateTimer(int delay_in_ms) {
- base::OneShotTimer* new_timer = new base::OneShotTimer();
- new_timer->Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(delay_in_ms),
- this,
- &ShelfTooltipManager::ShowInternal);
- timer_.reset(new_timer);
-}
-
} // namespace ash
diff --git a/ash/shelf/shelf_tooltip_manager.h b/ash/shelf/shelf_tooltip_manager.h
index 17eaee4..6768257 100644
--- a/ash/shelf/shelf_tooltip_manager.h
+++ b/ash/shelf/shelf_tooltip_manager.h
@@ -7,106 +7,72 @@
#include "ash/ash_export.h"
#include "ash/shelf/shelf_layout_manager_observer.h"
-#include "ash/shelf/shelf_types.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
+#include "base/timer/timer.h"
#include "ui/events/event_handler.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/views/bubble/bubble_border.h"
-#include "ui/views/bubble/bubble_delegate.h"
-
-namespace base {
-class Timer;
-}
namespace views {
class BubbleDelegateView;
-class Label;
+class View;
}
namespace ash {
-class ShelfView;
class ShelfLayoutManager;
+class ShelfView;
namespace test {
class ShelfTooltipManagerTest;
class ShelfViewTest;
}
-// ShelfTooltipManager manages the tooltip balloon poping up on shelf items.
+// ShelfTooltipManager manages the tooltip bubble that appears for shelf items.
class ASH_EXPORT ShelfTooltipManager : public ui::EventHandler,
public ShelfLayoutManagerObserver {
public:
- ShelfTooltipManager(ShelfLayoutManager* shelf_layout_manager,
- ShelfView* shelf_view);
+ explicit ShelfTooltipManager(ShelfView* shelf_view);
~ShelfTooltipManager() override;
- ShelfLayoutManager* shelf_layout_manager() { return shelf_layout_manager_; }
-
- // Called when the bubble is closed.
- void OnBubbleClosed(views::BubbleDelegateView* view);
-
- // Shows the tooltip after a delay. It also has the appearing animation.
- void ShowDelayed(views::View* anchor, const base::string16& text);
-
- // Shows the tooltip immediately. It omits the appearing animation.
- void ShowImmediately(views::View* anchor, const base::string16& text);
+ // Initializes the tooltip manager once the shelf is shown.
+ void Init();
// Closes the tooltip.
void Close();
- // Changes the arrow location of the tooltip in case that the launcher
- // arrangement has changed.
- void UpdateArrow();
-
- // Resets the timer for the delayed showing |view_|. If the timer isn't
- // running, it starts a new timer.
- void ResetTimer();
-
- // Stops the timer for the delayed showing |view_|.
- void StopTimer();
-
// Returns true if the tooltip is currently visible.
- bool IsVisible();
+ bool IsVisible() const;
+
+ // Returns the view to which the tooltip bubble is anchored. May be null.
+ views::View* GetCurrentAnchorView() const;
- // Returns the view to which the tooltip bubble is anchored. May be NULL.
- views::View* GetCurrentAnchorView() { return anchor_; }
+ // Show the tooltip bubble for the specified view.
+ void ShowTooltip(views::View* view);
+ void ShowTooltipWithDelay(views::View* view);
- // Create an instant timer for test purposes.
- void CreateZeroDelayTimerForTest();
+ // Set the timer delay in ms for testing.
+ void set_timer_delay_for_test(int timer_delay) { timer_delay_ = timer_delay; }
-protected:
+ protected:
// ui::EventHandler overrides:
- void OnMouseEvent(ui::MouseEvent* event) override;
- void OnTouchEvent(ui::TouchEvent* event) override;
- void OnGestureEvent(ui::GestureEvent* event) override;
- void OnCancelMode(ui::CancelModeEvent* event) override;
+ void OnEvent(ui::Event* event) override;
// ShelfLayoutManagerObserver overrides:
- void WillDeleteShelf() override;
- void WillChangeVisibilityState(ShelfVisibilityState new_state) override;
- void OnAutoHideStateChanged(ShelfAutoHideState new_state) override;
+ void WillDeleteShelf() override;
+ void WillChangeVisibilityState(ShelfVisibilityState new_state) override;
+ void OnAutoHideStateChanged(ShelfAutoHideState new_state) override;
private:
class ShelfTooltipBubble;
friend class test::ShelfViewTest;
friend class test::ShelfTooltipManagerTest;
- void CancelHidingAnimation();
- void CloseSoon();
- void ShowInternal();
- void CreateBubble(views::View* anchor, const base::string16& text);
- void CreateTimer(int delay_in_ms);
+ int timer_delay_;
+ base::OneShotTimer timer_;
- ShelfTooltipBubble* view_;
- views::Widget* widget_;
- views::View* anchor_;
- base::string16 text_;
- scoped_ptr<base::Timer> timer_;
-
- ShelfLayoutManager* shelf_layout_manager_;
ShelfView* shelf_view_;
+ ShelfLayoutManager* shelf_layout_manager_;
+ views::BubbleDelegateView* bubble_;
base::WeakPtrFactory<ShelfTooltipManager> weak_factory_;
diff --git a/ash/shelf/shelf_tooltip_manager_unittest.cc b/ash/shelf/shelf_tooltip_manager_unittest.cc
index 6ebb063..3f2b2e8 100644
--- a/ash/shelf/shelf_tooltip_manager_unittest.cc
+++ b/ash/shelf/shelf_tooltip_manager_unittest.cc
@@ -4,35 +4,19 @@
#include "ash/shelf/shelf_tooltip_manager.h"
-#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/shelf_test_api.h"
-#include "ash/wm/window_util.h"
-#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/events/event.h"
+#include "ash/test/shelf_view_test_api.h"
#include "ui/events/event_constants.h"
-#include "ui/events/event_handler.h"
-#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/events/test/events_test_utils.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/widget/widget.h"
-namespace {
-
-void SetEventTarget(ui::EventTarget* target,
- ui::Event* event) {
- ui::Event::DispatcherApi dispatch_helper(event);
- dispatch_helper.set_target(target);
-}
-
-}
-
namespace ash {
namespace test {
@@ -43,52 +27,38 @@ class ShelfTooltipManagerTest : public AshTestBase {
void SetUp() override {
AshTestBase::SetUp();
- RootWindowController* controller = Shell::GetPrimaryRootWindowController();
- tooltip_manager_.reset(new ShelfTooltipManager(
- controller->GetShelfLayoutManager(),
- ShelfTestAPI(controller->shelf()->shelf()).shelf_view()));
- }
-
- void TearDown() override {
- tooltip_manager_.reset();
- AshTestBase::TearDown();
+ shelf_ = Shelf::ForPrimaryDisplay();
+ ShelfView* shelf_view = test::ShelfTestAPI(shelf_).shelf_view();
+ tooltip_manager_ = test::ShelfViewTestAPI(shelf_view).tooltip_manager();
}
void ShowDelayed() {
CreateWidget();
- tooltip_manager_->ShowDelayed(dummy_anchor_.get(), base::string16());
+ tooltip_manager_->ShowTooltipWithDelay(dummy_anchor_.get());
}
void ShowImmediately() {
CreateWidget();
- tooltip_manager_->ShowImmediately(dummy_anchor_.get(), base::string16());
- }
-
- bool TooltipIsVisible() {
- return tooltip_manager_->IsVisible();
+ tooltip_manager_->ShowTooltip(dummy_anchor_.get());
}
- bool IsTimerRunning() {
- return tooltip_manager_->timer_.get() != NULL;
- }
-
- ui::EventHandler* GetEventHandler() {
- return tooltip_manager_.get();
- }
+ bool TooltipIsVisible() { return tooltip_manager_->IsVisible(); }
+ bool IsTimerRunning() { return tooltip_manager_->timer_.IsRunning(); }
- views::Widget* GetTooltipWidget() {
- return tooltip_manager_->widget_;
+ aura::Window* GetTooltipWindow() {
+ return tooltip_manager_->bubble_->GetWidget()->GetNativeWindow();
}
protected:
scoped_ptr<views::Widget> widget_;
scoped_ptr<views::View> dummy_anchor_;
- scoped_ptr<ShelfTooltipManager> tooltip_manager_;
+
+ Shelf* shelf_;
+ ShelfTooltipManager* tooltip_manager_;
private:
void CreateWidget() {
dummy_anchor_.reset(new views::View);
-
widget_.reset(new views::Widget);
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
@@ -96,7 +66,6 @@ class ShelfTooltipManagerTest : public AshTestBase {
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = Shell::GetContainer(Shell::GetPrimaryRootWindow(),
ash::kShellWindowId_ShelfContainer);
-
widget_->Init(params);
widget_->SetContentsView(dummy_anchor_.get());
}
@@ -129,10 +98,7 @@ TEST_F(ShelfTooltipManagerTest, HideWhenShelfIsHidden) {
widget->Show();
// Once the shelf is hidden, the tooltip should be invisible.
- ASSERT_EQ(
- SHELF_HIDDEN,
- Shell::GetPrimaryRootWindowController()->
- GetShelfLayoutManager()->visibility_state());
+ ASSERT_EQ(SHELF_HIDDEN, shelf_->shelf_layout_manager()->visibility_state());
EXPECT_FALSE(TooltipIsVisible());
// Do not show the view if the shelf is hidden.
@@ -156,11 +122,10 @@ TEST_F(ShelfTooltipManagerTest, HideWhenShelfIsAutoHide) {
ShowImmediately();
ASSERT_TRUE(TooltipIsVisible());
- ShelfLayoutManager* shelf =
- Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
- shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
- shelf->UpdateAutoHideState();
- ASSERT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+ ShelfLayoutManager* shelf_layout_manager = shelf_->shelf_layout_manager();
+ shelf_layout_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+ shelf_layout_manager->UpdateAutoHideState();
+ ASSERT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_layout_manager->auto_hide_state());
// Tooltip visibility change for auto hide may take time.
EXPECT_TRUE(TooltipIsVisible());
@@ -176,113 +141,67 @@ TEST_F(ShelfTooltipManagerTest, HideWhenShelfIsAutoHide) {
EXPECT_FALSE(IsTimerRunning());
}
-TEST_F(ShelfTooltipManagerTest, ShouldHideForEvents) {
+TEST_F(ShelfTooltipManagerTest, HideForEvents) {
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+ gfx::Rect shelf_bounds = shelf_->shelf_widget()->GetNativeWindow()->bounds();
+
+ // Should hide if the mouse exits the shelf area.
ShowImmediately();
ASSERT_TRUE(TooltipIsVisible());
-
- aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
- ui::EventHandler* event_handler = GetEventHandler();
-
- // Should not hide for key events.
- ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
- SetEventTarget(root_window, &key_event);
- event_handler->OnKeyEvent(&key_event);
- EXPECT_FALSE(key_event.handled());
- EXPECT_TRUE(TooltipIsVisible());
-
- // Should hide for touch events.
- ui::TouchEvent touch_event(
- ui::ET_TOUCH_PRESSED, gfx::Point(), 0, base::TimeDelta());
- SetEventTarget(root_window, &touch_event);
- event_handler->OnTouchEvent(&touch_event);
- EXPECT_FALSE(touch_event.handled());
+ generator.MoveMouseTo(shelf_bounds.CenterPoint());
+ generator.SendMouseExit();
EXPECT_FALSE(TooltipIsVisible());
- // Shouldn't hide if the touch happens on the tooltip.
+ // Should hide if the mouse is pressed in the shelf area.
ShowImmediately();
- views::Widget* tooltip_widget = GetTooltipWidget();
- SetEventTarget(tooltip_widget->GetNativeWindow(), &touch_event);
- event_handler->OnTouchEvent(&touch_event);
- EXPECT_FALSE(touch_event.handled());
- EXPECT_TRUE(TooltipIsVisible());
-
- // Should hide for gesture events.
- ui::GestureEvent gesture_event(
- 0,
- 0,
- ui::EF_NONE,
- base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
- ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
- SetEventTarget(tooltip_widget->GetNativeWindow(), &gesture_event);
- event_handler->OnGestureEvent(&gesture_event);
- EXPECT_FALSE(gesture_event.handled());
- RunAllPendingInMessageLoop();
+ ASSERT_TRUE(TooltipIsVisible());
+ generator.MoveMouseTo(shelf_bounds.CenterPoint());
+ generator.PressLeftButton();
EXPECT_FALSE(TooltipIsVisible());
-}
-TEST_F(ShelfTooltipManagerTest, HideForMouseMoveEvent) {
+ // Should hide for touch events in the shelf.
ShowImmediately();
ASSERT_TRUE(TooltipIsVisible());
+ generator.set_current_location(shelf_bounds.CenterPoint());
+ generator.PressTouch();
+ EXPECT_FALSE(TooltipIsVisible());
- aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
- ui::EventHandler* event_handler = GetEventHandler();
-
- gfx::Rect tooltip_rect = GetTooltipWidget()->GetNativeWindow()->bounds();
- ASSERT_FALSE(tooltip_rect.IsEmpty());
-
- // Shouldn't hide if the mouse is in the tooltip.
- ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, tooltip_rect.CenterPoint(),
- tooltip_rect.CenterPoint(), ui::EventTimeForNow(),
- ui::EF_NONE, ui::EF_NONE);
- ui::LocatedEventTestApi test_api(&mouse_event);
-
- SetEventTarget(root_window, &mouse_event);
- event_handler->OnMouseEvent(&mouse_event);
- EXPECT_FALSE(mouse_event.handled());
- EXPECT_TRUE(TooltipIsVisible());
-
- // Should hide if the mouse is out of the tooltip.
- test_api.set_location(tooltip_rect.origin() + gfx::Vector2d(-1, -1));
- event_handler->OnMouseEvent(&mouse_event);
- EXPECT_FALSE(mouse_event.handled());
- RunAllPendingInMessageLoop();
+ // Should hide for gesture events in the shelf.
+ ShowImmediately();
+ ASSERT_TRUE(TooltipIsVisible());
+ generator.GestureTapDownAndUp(shelf_bounds.CenterPoint());
EXPECT_FALSE(TooltipIsVisible());
}
-// Checks that tooltip is hidden when mouse is pressed in anywhere.
-TEST_F(ShelfTooltipManagerTest, HideForMouseClickEvent) {
+// TODO(msw): Hiding for touch and gesture events outside the shelf is broken.
+TEST_F(ShelfTooltipManagerTest, HideForEventsBroken) {
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
ShowImmediately();
ASSERT_TRUE(TooltipIsVisible());
- aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
- ui::EventHandler* event_handler = GetEventHandler();
-
- gfx::Rect tooltip_rect = GetTooltipWidget()->GetNativeWindow()->bounds();
- ASSERT_FALSE(tooltip_rect.IsEmpty());
+ generator.set_current_location(gfx::Point());
+ generator.PressTouch();
+ EXPECT_TRUE(TooltipIsVisible());
- // Should hide if the mouse is pressed in the tooltip.
- ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, tooltip_rect.CenterPoint(),
- tooltip_rect.CenterPoint(), ui::EventTimeForNow(),
- ui::EF_NONE, ui::EF_NONE);
+ generator.GestureTapDownAndUp(gfx::Point());
+ EXPECT_TRUE(TooltipIsVisible());
+}
- SetEventTarget(root_window, &mouse_event);
- event_handler->OnMouseEvent(&mouse_event);
- EXPECT_FALSE(mouse_event.handled());
- RunAllPendingInMessageLoop();
- EXPECT_FALSE(TooltipIsVisible());
+TEST_F(ShelfTooltipManagerTest, DoNotHideForEvents) {
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
- // Should hide if the mouse is pressed outside of the tooltip.
ShowImmediately();
ASSERT_TRUE(TooltipIsVisible());
- ui::LocatedEventTestApi test_api(&mouse_event);
- test_api.set_location(tooltip_rect.origin() + gfx::Vector2d(-1, -1));
+ // Should not hide for key events.
+ generator.PressKey(ui::VKEY_A, ui::EF_NONE);
+ EXPECT_TRUE(TooltipIsVisible());
- SetEventTarget(root_window, &mouse_event);
- event_handler->OnMouseEvent(&mouse_event);
- EXPECT_FALSE(mouse_event.handled());
- RunAllPendingInMessageLoop();
- EXPECT_FALSE(TooltipIsVisible());
+ // Should not hide for touch events on the tooltip.
+ generator.set_current_location(GetTooltipWindow()->bounds().CenterPoint());
+ generator.PressTouch();
+ EXPECT_TRUE(TooltipIsVisible());
}
} // namespace test
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index b3ddf68..3a19798 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -23,7 +23,6 @@
#include "ash/shelf/shelf_item_delegate_manager.h"
#include "ash/shelf/shelf_menu_model.h"
#include "ash/shelf/shelf_model.h"
-#include "ash/shelf/shelf_tooltip_manager.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
@@ -224,8 +223,7 @@ bool ShelfMenuModelAdapter::ShouldReserveSpaceForSubmenuIndicator() const {
class ShelfFocusSearch : public views::FocusSearch {
public:
explicit ShelfFocusSearch(views::ViewModel* view_model)
- : FocusSearch(NULL, true, true),
- view_model_(view_model) {}
+ : FocusSearch(nullptr, true, true), view_model_(view_model) {}
~ShelfFocusSearch() override {}
// views::FocusSearch overrides:
@@ -370,25 +368,26 @@ ShelfView::ShelfView(ShelfModel* model, ShelfDelegate* delegate, Shelf* shelf)
view_model_(new views::ViewModel),
first_visible_index_(0),
last_visible_index_(-1),
- overflow_button_(NULL),
- owner_overflow_bubble_(NULL),
+ overflow_button_(nullptr),
+ owner_overflow_bubble_(nullptr),
+ tooltip_(this),
drag_pointer_(NONE),
- drag_view_(NULL),
+ drag_view_(nullptr),
start_drag_index_(-1),
context_menu_id_(0),
leading_inset_(kDefaultLeadingInset),
cancelling_drag_model_changed_(false),
last_hidden_index_(0),
closing_event_time_(base::TimeDelta()),
- got_deleted_(NULL),
+ got_deleted_(nullptr),
drag_and_drop_item_pinned_(false),
drag_and_drop_shelf_id_(0),
drag_replaced_view_(nullptr),
dragged_off_shelf_(false),
- snap_back_from_rip_off_view_(NULL),
+ snap_back_from_rip_off_view_(nullptr),
item_manager_(Shell::GetInstance()->shelf_item_delegate_manager()),
overflow_mode_(false),
- main_shelf_(NULL),
+ main_shelf_(nullptr),
dragged_off_from_overflow_to_shelf_(false),
is_repost_event_(false),
last_pressed_index_(-1) {
@@ -397,7 +396,6 @@ ShelfView::ShelfView(ShelfModel* model, ShelfDelegate* delegate, Shelf* shelf)
bounds_animator_->AddObserver(this);
set_context_menu_controller(this);
focus_search_.reset(new ShelfFocusSearch(view_model_.get()));
- tooltip_.reset(new ShelfTooltipManager(shelf->shelf_layout_manager(), this));
}
ShelfView::~ShelfView() {
@@ -434,7 +432,7 @@ void ShelfView::OnShelfAlignmentChanged() {
if (i >= first_visible_index_ && i <= last_visible_index_)
view_model_->view_at(i)->Layout();
}
- tooltip_->Close();
+ tooltip_.Close();
if (overflow_bubble_)
overflow_bubble_->Hide();
}
@@ -517,7 +515,42 @@ views::View* ShelfView::GetAppListButtonView() const {
}
NOTREACHED() << "Applist button not found";
- return NULL;
+ return nullptr;
+}
+
+bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) const {
+ gfx::Rect tooltip_bounds;
+ for (int i = 0; i < child_count(); ++i) {
+ const views::View* child = child_at(i);
+ if (child != overflow_button_ && ShouldShowTooltipForView(child))
+ tooltip_bounds.Union(child->GetMirroredBounds());
+ }
+ return !tooltip_bounds.Contains(cursor_location);
+}
+
+bool ShelfView::ShouldShowTooltipForView(const views::View* view) const {
+ if (view == GetAppListButtonView() &&
+ Shell::GetInstance()->GetAppListWindow()) {
+ return false;
+ }
+ const ShelfItem* item = ShelfItemForView(view);
+ if (!item)
+ return false;
+ return item_manager_->GetShelfItemDelegate(item->id)->ShouldShowTooltip();
+}
+
+base::string16 ShelfView::GetTitleForView(const views::View* view) const {
+ const ShelfItem* item = ShelfItemForView(view);
+ if (!item)
+ return base::string16();
+ return item_manager_->GetShelfItemDelegate(item->id)->GetTitle();
+}
+
+gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
+ gfx::Size preferred_size = GetPreferredSize();
+ gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0);
+ ConvertPointToScreen(this, &origin);
+ return gfx::Rect(origin, preferred_size);
}
////////////////////////////////////////////////////////////////////////////////
@@ -560,7 +593,7 @@ void ShelfView::CreateDragIconProxy(
void ShelfView::UpdateDragIconProxy(
const gfx::Point& location_in_screen_coordinates) {
- // TODO(jennyz): Investigate why drag_image_ becomes NULL at this point per
+ // TODO(jennyz): Investigate why drag_image_ becomes null at this point per
// crbug.com/34722, while the app list item is still being dragged around.
if (drag_image_) {
drag_image_->SetScreenPosition(
@@ -621,9 +654,7 @@ bool ShelfView::StartDrag(const std::string& app_id,
ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root);
ui::MouseEvent event(ui::ET_MOUSE_PRESSED, pt, point_in_root,
ui::EventTimeForNow(), 0, 0);
- PointerPressedOnButton(drag_and_drop_view,
- ShelfButtonHost::DRAG_AND_DROP,
- event);
+ PointerPressedOnButton(drag_and_drop_view, DRAG_AND_DROP, event);
// Drag the item where it really belongs.
Drag(location_in_screen_coordinates);
@@ -644,9 +675,7 @@ bool ShelfView::Drag(const gfx::Point& location_in_screen_coordinates) {
ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root);
ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, point_in_root,
ui::EventTimeForNow(), 0, 0);
- PointerDraggedOnButton(drag_and_drop_view,
- ShelfButtonHost::DRAG_AND_DROP,
- event);
+ PointerDraggedOnButton(drag_and_drop_view, DRAG_AND_DROP, event);
return true;
}
@@ -656,8 +685,7 @@ void ShelfView::EndDrag(bool cancel) {
views::View* drag_and_drop_view = view_model_->view_at(
model_->ItemIndexByID(drag_and_drop_shelf_id_));
- PointerReleasedOnButton(
- drag_and_drop_view, ShelfButtonHost::DRAG_AND_DROP, cancel);
+ PointerReleasedOnButton(drag_and_drop_view, DRAG_AND_DROP, cancel);
// Either destroy the temporarily created item - or - make the item visible.
if (drag_and_drop_item_pinned_ && cancel) {
@@ -676,6 +704,69 @@ void ShelfView::EndDrag(bool cancel) {
drag_and_drop_shelf_id_ = 0;
}
+void ShelfView::PointerPressedOnButton(views::View* view,
+ Pointer pointer,
+ const ui::LocatedEvent& event) {
+ if (drag_view_)
+ return;
+
+ int index = view_model_->GetIndexOfView(view);
+ if (index == -1)
+ return;
+
+ ShelfItemDelegate* item_delegate =
+ item_manager_->GetShelfItemDelegate(model_->items()[index].id);
+ if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable())
+ return; // View is being deleted or not draggable, ignore request.
+
+ // Only when the repost event occurs on the same shelf item, we should ignore
+ // the call in ShelfView::ButtonPressed(...).
+ is_repost_event_ = IsRepostEvent(event) && (last_pressed_index_ == index);
+
+ CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
+ drag_view_ = static_cast<ShelfButton*>(view);
+ drag_origin_ = gfx::Point(event.x(), event.y());
+ UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
+ shelf_->SelectValueForShelfAlignment(
+ SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM,
+ SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT,
+ SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT, -1),
+ SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT);
+}
+
+void ShelfView::PointerDraggedOnButton(views::View* view,
+ Pointer pointer,
+ const ui::LocatedEvent& event) {
+ // To prepare all drag types (moving an item in the shelf and dragging off),
+ // we should check the x-axis and y-axis offset.
+ if (!dragging() && drag_view_ &&
+ ((std::abs(event.x() - drag_origin_.x()) >= kMinimumDragDistance) ||
+ (std::abs(event.y() - drag_origin_.y()) >= kMinimumDragDistance))) {
+ PrepareForDrag(pointer, event);
+ }
+ if (drag_pointer_ == pointer)
+ ContinueDrag(event);
+}
+
+void ShelfView::PointerReleasedOnButton(views::View* view,
+ Pointer pointer,
+ bool canceled) {
+ // Reset |is_repost_event| to false.
+ is_repost_event_ = false;
+
+ if (canceled) {
+ CancelDrag(-1);
+ } else if (drag_pointer_ == pointer) {
+ FinalizeRipOffDrag(false);
+ drag_pointer_ = NONE;
+ AnimateToIdealBounds();
+ }
+ // If the drag pointer is NONE, no drag operation is going on and the
+ // drag_view can be released.
+ if (drag_pointer_ == NONE)
+ drag_view_ = nullptr;
+}
+
void ShelfView::LayoutToIdealBounds() {
if (bounds_animator_->IsAnimating()) {
AnimateToIdealBounds();
@@ -883,7 +974,7 @@ void ShelfView::AnimateToIdealBounds() {
}
views::View* ShelfView::CreateViewForItem(const ShelfItem& item) {
- views::View* view = NULL;
+ views::View* view = nullptr;
switch (item.type) {
case TYPE_BROWSER_SHORTCUT:
case TYPE_APP_SHORTCUT:
@@ -891,7 +982,7 @@ views::View* ShelfView::CreateViewForItem(const ShelfItem& item) {
case TYPE_PLATFORM_APP:
case TYPE_DIALOG:
case TYPE_APP_PANEL: {
- ShelfButton* button = ShelfButton::Create(this, this, shelf_);
+ ShelfButton* button = new ShelfButton(this);
button->SetImage(item.image);
ReflectItemStatus(item, button);
view = button;
@@ -899,16 +990,15 @@ views::View* ShelfView::CreateViewForItem(const ShelfItem& item) {
}
case TYPE_APP_LIST: {
- view = new AppListButton(this, this, shelf_->shelf_widget());
+ view = new AppListButton(this);
break;
}
- default:
- break;
+ case TYPE_UNDEFINED:
+ return nullptr;
}
- view->set_context_menu_controller(this);
- DCHECK(view);
+ view->set_context_menu_controller(this);
ConfigureChildView(view);
return view;
}
@@ -1295,30 +1385,6 @@ void ShelfView::UpdateOverflowRange(ShelfView* overflow_view) const {
overflow_view->last_visible_index_ = last_overflow_index;
}
-bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) {
- gfx::Rect active_bounds;
-
- for (int i = 0; i < child_count(); ++i) {
- views::View* child = child_at(i);
- if (child == overflow_button_)
- continue;
- if (!ShouldShowTooltipForView(child))
- continue;
-
- gfx::Rect child_bounds = child->GetMirroredBounds();
- active_bounds.Union(child_bounds);
- }
-
- return !active_bounds.Contains(cursor_location);
-}
-
-gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
- gfx::Size preferred_size = GetPreferredSize();
- gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0);
- ConvertPointToScreen(this, &origin);
- return gfx::Rect(origin, preferred_size);
-}
-
gfx::Rect ShelfView::GetBoundsForDragInsertInScreen() {
gfx::Size preferred_size;
if (is_overflow_mode()) {
@@ -1366,7 +1432,7 @@ int ShelfView::CancelDrag(int modified_index) {
bool was_dragging = dragging();
int drag_view_index = view_model_->GetIndexOfView(drag_view_);
drag_pointer_ = NONE;
- drag_view_ = NULL;
+ drag_view_ = nullptr;
if (drag_view_index == modified_index) {
// The view that was being dragged is being modified. Don't do anything.
return modified_index;
@@ -1376,9 +1442,9 @@ int ShelfView::CancelDrag(int modified_index) {
// Restore previous position, tracking the position of the modified view.
bool at_end = modified_index == view_model_->view_size();
- views::View* modified_view =
- (modified_index >= 0 && !at_end) ?
- view_model_->view_at(modified_index) : NULL;
+ views::View* modified_view = (modified_index >= 0 && !at_end)
+ ? view_model_->view_at(modified_index)
+ : nullptr;
model_->Move(drag_view_index, start_drag_index_);
// If the modified view will be at the end of the list, return the new end of
@@ -1441,6 +1507,12 @@ void ShelfView::GetAccessibleState(ui::AXViewState* state) {
state->name = l10n_util::GetStringUTF16(IDS_ASH_SHELF_ACCESSIBLE_NAME);
}
+void ShelfView::ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) {
+ if (details.is_add && details.child == this && GetWidget())
+ tooltip_.Init();
+}
+
void ShelfView::OnGestureEvent(ui::GestureEvent* event) {
aura::Window* target_window = static_cast<views::View*>(event->target())
->GetWidget()
@@ -1523,10 +1595,8 @@ void ShelfView::ShelfItemRemoved(int model_index, ShelfID id) {
AnimateToIdealBounds();
}
- // Close the tooltip because it isn't needed any longer and its anchor view
- // will be deleted soon.
- if (tooltip_->GetCurrentAnchorView() == view)
- tooltip_->Close();
+ if (view == tooltip_.GetCurrentAnchorView())
+ tooltip_.Close();
}
void ShelfView::ShelfItemChanged(int model_index, const ShelfItem& old_item) {
@@ -1585,104 +1655,6 @@ void ShelfView::ShelfItemMoved(int start_index, int target_index) {
AnimateToIdealBounds();
}
-void ShelfView::PointerPressedOnButton(views::View* view,
- Pointer pointer,
- const ui::LocatedEvent& event) {
- if (drag_view_)
- return;
-
- int index = view_model_->GetIndexOfView(view);
- if (index == -1)
- return;
-
- ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
- model_->items()[index].id);
- if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable())
- return; // View is being deleted or not draggable, ignore request.
-
- // Only when the repost event occurs on the same shelf item, we should ignore
- // the call in ShelfView::ButtonPressed(...).
- is_repost_event_ = IsRepostEvent(event) && (last_pressed_index_ == index);
-
- CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
- drag_view_ = static_cast<ShelfButton*>(view);
- drag_origin_ = gfx::Point(event.x(), event.y());
- UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
- shelf_->SelectValueForShelfAlignment(
- SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM,
- SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT,
- SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT, -1),
- SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT);
-}
-
-void ShelfView::PointerDraggedOnButton(views::View* view,
- Pointer pointer,
- const ui::LocatedEvent& event) {
- // To prepare all drag types (moving an item in the shelf and dragging off),
- // we should check the x-axis and y-axis offset.
- if (!dragging() && drag_view_ &&
- ((std::abs(event.x() - drag_origin_.x()) >= kMinimumDragDistance) ||
- (std::abs(event.y() - drag_origin_.y()) >= kMinimumDragDistance))) {
- PrepareForDrag(pointer, event);
- }
- if (drag_pointer_ == pointer)
- ContinueDrag(event);
-}
-
-void ShelfView::PointerReleasedOnButton(views::View* view,
- Pointer pointer,
- bool canceled) {
- // Reset |is_repost_event| to false.
- is_repost_event_ = false;
-
- if (canceled) {
- CancelDrag(-1);
- } else if (drag_pointer_ == pointer) {
- FinalizeRipOffDrag(false);
- drag_pointer_ = NONE;
- AnimateToIdealBounds();
- }
- // If the drag pointer is NONE, no drag operation is going on and the
- // drag_view can be released.
- if (drag_pointer_ == NONE)
- drag_view_ = NULL;
-}
-
-void ShelfView::MouseMovedOverButton(views::View* view) {
- if (!ShouldShowTooltipForView(view))
- return;
-
- if (!tooltip_->IsVisible())
- tooltip_->ResetTimer();
-}
-
-void ShelfView::MouseEnteredButton(views::View* view) {
- if (!ShouldShowTooltipForView(view))
- return;
-
- if (tooltip_->IsVisible()) {
- tooltip_->ShowImmediately(view, GetAccessibleName(view));
- } else {
- tooltip_->ShowDelayed(view, GetAccessibleName(view));
- }
-}
-
-void ShelfView::MouseExitedButton(views::View* view) {
- if (!tooltip_->IsVisible())
- tooltip_->StopTimer();
-}
-
-base::string16 ShelfView::GetAccessibleName(const views::View* view) {
- int view_index = view_model_->GetIndexOfView(view);
- // May be -1 while in the process of animating closed.
- if (view_index == -1)
- return base::string16();
-
- ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
- model_->items()[view_index].id);
- return item_delegate->GetTitle();
-}
-
void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event) {
// Do not handle mouse release during drag.
if (dragging())
@@ -1882,7 +1854,7 @@ void ShelfView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
break;
}
}
- snap_back_from_rip_off_view_ = NULL;
+ snap_back_from_rip_off_view_ = nullptr;
}
}
}
@@ -1904,18 +1876,6 @@ const ShelfItem* ShelfView::ShelfItemForView(const views::View* view) const {
return (view_index < 0) ? nullptr : &(model_->items()[view_index]);
}
-bool ShelfView::ShouldShowTooltipForView(const views::View* view) const {
- if (view == GetAppListButtonView() &&
- Shell::GetInstance()->GetAppListTargetVisibility())
- return false;
- const ShelfItem* item = ShelfItemForView(view);
- if (!item)
- return true;
- ShelfItemDelegate* item_delegate =
- item_manager_->GetShelfItemDelegate(item->id);
- return item_delegate->ShouldShowTooltip();
-}
-
int ShelfView::CalculateShelfDistance(const gfx::Point& coordinate) const {
const gfx::Rect bounds = GetBoundsInScreen();
int distance = shelf_->SelectValueForShelfAlignment(
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index 1343283..6971374 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -9,10 +9,10 @@
#include <utility>
#include <vector>
-#include "ash/shelf/shelf_button_host.h"
#include "ash/shelf/shelf_button_pressed_metric_tracker.h"
#include "ash/shelf/shelf_item_delegate.h"
#include "ash/shelf/shelf_model_observer.h"
+#include "ash/shelf/shelf_tooltip_manager.h"
#include "ash/wm/gestures/shelf_gesture_handler.h"
#include "base/macros.h"
#include "base/observer_list.h"
@@ -44,7 +44,6 @@ class DragImageView;
class OverflowBubble;
class OverflowButton;
class ShelfButton;
-class ShelfTooltipManager;
namespace test {
class ShelfViewTestAPI;
@@ -58,7 +57,6 @@ extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT;
class ASH_EXPORT ShelfView : public views::View,
public ShelfModelObserver,
public views::ButtonListener,
- public ShelfButtonHost,
public views::ContextMenuController,
public views::FocusTraversable,
public views::BoundsAnimatorObserver,
@@ -67,8 +65,6 @@ class ASH_EXPORT ShelfView : public views::View,
ShelfView(ShelfModel* model, ShelfDelegate* delegate, Shelf* shelf);
~ShelfView() override;
- ShelfTooltipManager* tooltip_manager() { return tooltip_.get(); }
-
Shelf* shelf() const { return shelf_; }
ShelfModel* model() const { return model_; }
@@ -106,7 +102,13 @@ class ASH_EXPORT ShelfView : public views::View,
// There are thin gaps between launcher buttons but the tooltip shouldn't hide
// in the gaps, but the tooltip should hide if the mouse moved totally outside
// of the buttons area.
- bool ShouldHideTooltip(const gfx::Point& cursor_location);
+ bool ShouldHideTooltip(const gfx::Point& cursor_location) const;
+
+ // Returns true if a tooltip should be shown for the shelf item |view|.
+ bool ShouldShowTooltipForView(const views::View* view) const;
+
+ // Returns the title of the shelf item |view|.
+ base::string16 GetTitleForView(const views::View* view) const;
// Returns rectangle bounding all visible launcher items. Used screen
// coordinate system.
@@ -131,6 +133,18 @@ class ASH_EXPORT ShelfView : public views::View,
bool Drag(const gfx::Point& location_in_screen_coordinates) override;
void EndDrag(bool cancel) override;
+ // The shelf buttons use the Pointer interface to enable item reordering.
+ enum Pointer { NONE, DRAG_AND_DROP, MOUSE, TOUCH };
+ void PointerPressedOnButton(views::View* view,
+ Pointer pointer,
+ const ui::LocatedEvent& event);
+ void PointerDraggedOnButton(views::View* view,
+ Pointer pointer,
+ const ui::LocatedEvent& event);
+ void PointerReleasedOnButton(views::View* view,
+ Pointer pointer,
+ bool canceled);
+
// Return the view model for test purposes.
const views::ViewModel* view_model_for_test() const {
return view_model_.get();
@@ -246,6 +260,8 @@ class ASH_EXPORT ShelfView : public views::View,
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
FocusTraversable* GetPaneFocusTraversable() override;
void GetAccessibleState(ui::AXViewState* state) override;
+ void ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) override;
// Overridden from ui::EventHandler:
void OnGestureEvent(ui::GestureEvent* event) override;
@@ -256,21 +272,6 @@ class ASH_EXPORT ShelfView : public views::View,
void ShelfItemChanged(int model_index, const ShelfItem& old_item) override;
void ShelfItemMoved(int start_index, int target_index) override;
- // Overridden from ShelfButtonHost:
- void PointerPressedOnButton(views::View* view,
- Pointer pointer,
- const ui::LocatedEvent& event) override;
- void PointerDraggedOnButton(views::View* view,
- Pointer pointer,
- const ui::LocatedEvent& event) override;
- void PointerReleasedOnButton(views::View* view,
- Pointer pointer,
- bool canceled) override;
- void MouseMovedOverButton(views::View* view) override;
- void MouseEnteredButton(views::View* view) override;
- void MouseExitedButton(views::View* view) override;
- base::string16 GetAccessibleName(const views::View* view) override;
-
// Overridden from views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
@@ -309,9 +310,6 @@ class ASH_EXPORT ShelfView : public views::View,
// Convenience accessor to model_->items().
const ShelfItem* ShelfItemForView(const views::View* view) const;
- // Returns true if a tooltip should be shown for |view|.
- bool ShouldShowTooltipForView(const views::View* view) const;
-
// Get the distance from the given |coordinate| to the closest point on this
// launcher/shelf.
int CalculateShelfDistance(const gfx::Point& coordinate) const;
@@ -344,7 +342,7 @@ class ASH_EXPORT ShelfView : public views::View,
OverflowBubble* owner_overflow_bubble_;
- scoped_ptr<ShelfTooltipManager> tooltip_;
+ ShelfTooltipManager tooltip_;
// Pointer device that initiated the current drag operation. If there is no
// current dragging operation, this is NONE.
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 71e5e7f..68ebf31 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -106,9 +106,7 @@ class ShelfViewIconObserverTest : public AshTestBase {
TestShelfIconObserver* observer() { return observer_.get(); }
- ShelfViewTestAPI* shelf_view_test() {
- return shelf_view_test_.get();
- }
+ ShelfViewTestAPI* shelf_view_test() { return shelf_view_test_.get(); }
Shelf* ShelfForSecondaryDisplay() {
return Shelf::ForWindow(Shell::GetAllRootWindows()[1]);
@@ -432,52 +430,46 @@ class ShelfViewTest : public AshTestBase {
}
}
- ShelfButton* SimulateButtonPressed(ShelfButtonHost::Pointer pointer,
+ ShelfButton* SimulateButtonPressed(ShelfView::Pointer pointer,
int button_index) {
- ShelfButtonHost* button_host = shelf_view_;
ShelfButton* button = test_api_->GetButton(button_index);
ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(),
button->GetBoundsInScreen().origin(),
ui::EventTimeForNow(), 0, 0);
- button_host->PointerPressedOnButton(button, pointer, click_event);
+ shelf_view_->PointerPressedOnButton(button, pointer, click_event);
return button;
}
// Simulates a single mouse click.
void SimulateClick(int button_index) {
- ShelfButtonHost* button_host = shelf_view_;
- ShelfButton* button =
- SimulateButtonPressed(ShelfButtonHost::MOUSE, button_index);
+ ShelfButton* button = SimulateButtonPressed(ShelfView::MOUSE, button_index);
ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
button->GetBoundsInScreen().origin(),
ui::EventTimeForNow(), 0, 0);
test_api_->ButtonPressed(button, release_event);
- button_host->PointerReleasedOnButton(button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(button, ShelfView::MOUSE, false);
}
// Simulates the second click of a double click.
void SimulateDoubleClick(int button_index) {
- ShelfButtonHost* button_host = shelf_view_;
- ShelfButton* button =
- SimulateButtonPressed(ShelfButtonHost::MOUSE, button_index);
+ ShelfButton* button = SimulateButtonPressed(ShelfView::MOUSE, button_index);
ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
button->GetBoundsInScreen().origin(),
ui::EventTimeForNow(), ui::EF_IS_DOUBLE_CLICK,
0);
test_api_->ButtonPressed(button, release_event);
- button_host->PointerReleasedOnButton(button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(button, ShelfView::MOUSE, false);
}
void DoDrag(int dist_x,
int dist_y,
views::View* button,
- ShelfButtonHost::Pointer pointer,
+ ShelfView::Pointer pointer,
views::View* to) {
ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, gfx::Point(dist_x, dist_y),
to->GetBoundsInScreen().origin(),
ui::EventTimeForNow(), 0, 0);
- static_cast<ShelfButtonHost*>(shelf_view_)
- ->PointerDraggedOnButton(button, pointer, drag_event);
+ shelf_view_->PointerDraggedOnButton(button, pointer, drag_event);
}
/*
@@ -487,7 +479,7 @@ class ShelfViewTest : public AshTestBase {
* drag behavior.
*/
void ContinueDrag(views::View* button,
- ShelfButtonHost::Pointer pointer,
+ ShelfView::Pointer pointer,
int from_index,
int to_index,
bool progressively) {
@@ -511,7 +503,7 @@ class ShelfViewTest : public AshTestBase {
* series of changes of the posistion of dragged item) like the behavior of
* user drags.
*/
- views::View* SimulateDrag(ShelfButtonHost::Pointer pointer,
+ views::View* SimulateDrag(ShelfView::Pointer pointer,
int button_index,
int destination_index,
bool progressively) {
@@ -534,12 +526,12 @@ class ShelfViewTest : public AshTestBase {
void DragAndVerify(
int from,
int to,
- ShelfButtonHost* button_host,
+ ShelfView* shelf_view,
const std::vector<std::pair<int, views::View*>>& expected_id_map) {
views::View* dragged_button =
- SimulateDrag(ShelfButtonHost::MOUSE, from, to, true);
- button_host->PointerReleasedOnButton(dragged_button, ShelfButtonHost::MOUSE,
- false);
+ SimulateDrag(ShelfView::MOUSE, from, to, true);
+ shelf_view->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE,
+ false);
test_api_->RunMessageLoopUntilAnimationsDone();
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(expected_id_map));
}
@@ -564,10 +556,6 @@ class ShelfViewTest : public AshTestBase {
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
}
- views::View* GetTooltipAnchorView() {
- return shelf_view_->tooltip_manager()->anchor_;
- }
-
void AddButtonsUntilOverflow() {
int items_added = 0;
while (!test_api_->IsOverflowButtonVisible()) {
@@ -577,10 +565,6 @@ class ShelfViewTest : public AshTestBase {
}
}
- void ShowTooltip() {
- shelf_view_->tooltip_manager()->ShowInternal();
- }
-
void TestDraggingAnItemFromOverflowToShelf(bool cancel) {
test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->overflow_bubble() &&
@@ -1106,107 +1090,97 @@ TEST_F(ShelfViewTest, AddButtonQuickly) {
// Check that model changes are handled correctly while a shelf icon is being
// dragged.
TEST_F(ShelfViewTest, ModelChangesWhileDragging) {
- ShelfButtonHost* button_host = shelf_view_;
-
std::vector<std::pair<ShelfID, views::View*> > id_map;
SetupForDragTest(&id_map);
// Dragging browser shortcut at index 1.
EXPECT_TRUE(model_->items()[1].type == TYPE_BROWSER_SHORTCUT);
- views::View* dragged_button =
- SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
+ views::View* dragged_button = SimulateDrag(ShelfView::MOUSE, 1, 3, false);
std::rotate(id_map.begin() + 1,
id_map.begin() + 2,
id_map.begin() + 4);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
- button_host->PointerReleasedOnButton(
- dragged_button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE, false);
EXPECT_TRUE(model_->items()[3].type == TYPE_BROWSER_SHORTCUT);
// Dragging changes model order.
- dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
+ dragged_button = SimulateDrag(ShelfView::MOUSE, 1, 3, false);
std::rotate(id_map.begin() + 1,
id_map.begin() + 2,
id_map.begin() + 4);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Cancelling the drag operation restores previous order.
- button_host->PointerReleasedOnButton(
- dragged_button, ShelfButtonHost::MOUSE, true);
+ shelf_view_->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE, true);
std::rotate(id_map.begin() + 1,
id_map.begin() + 3,
id_map.begin() + 4);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Deleting an item keeps the remaining intact.
- dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
+ dragged_button = SimulateDrag(ShelfView::MOUSE, 1, 3, false);
model_->RemoveItemAt(1);
id_map.erase(id_map.begin() + 1);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
- button_host->PointerReleasedOnButton(
- dragged_button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE, false);
// Adding a shelf item cancels the drag and respects the order.
- dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
+ dragged_button = SimulateDrag(ShelfView::MOUSE, 1, 3, false);
ShelfID new_id = AddAppShortcut();
id_map.insert(id_map.begin() + 6,
std::make_pair(new_id, GetButtonByID(new_id)));
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
- button_host->PointerReleasedOnButton(
- dragged_button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE, false);
// Adding a shelf item at the end (i.e. a panel) canels drag and respects
// the order.
- dragged_button = SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
+ dragged_button = SimulateDrag(ShelfView::MOUSE, 1, 3, false);
new_id = AddPanel();
id_map.insert(id_map.begin() + 7,
std::make_pair(new_id, GetButtonByID(new_id)));
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
- button_host->PointerReleasedOnButton(
- dragged_button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE, false);
}
// Check that 2nd drag from the other pointer would be ignored.
TEST_F(ShelfViewTest, SimultaneousDrag) {
- ShelfButtonHost* button_host = shelf_view_;
-
std::vector<std::pair<ShelfID, views::View*> > id_map;
SetupForDragTest(&id_map);
// Start a mouse drag.
views::View* dragged_button_mouse =
- SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
+ SimulateDrag(ShelfView::MOUSE, 1, 3, false);
std::rotate(id_map.begin() + 1,
id_map.begin() + 2,
id_map.begin() + 4);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Attempt a touch drag before the mouse drag finishes.
views::View* dragged_button_touch =
- SimulateDrag(ShelfButtonHost::TOUCH, 4, 2, false);
+ SimulateDrag(ShelfView::TOUCH, 4, 2, false);
// Nothing changes since 2nd drag is ignored.
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Finish the mouse drag.
- button_host->PointerReleasedOnButton(
- dragged_button_mouse, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button_mouse, ShelfView::MOUSE,
+ false);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Now start a touch drag.
- dragged_button_touch = SimulateDrag(ShelfButtonHost::TOUCH, 4, 2, false);
+ dragged_button_touch = SimulateDrag(ShelfView::TOUCH, 4, 2, false);
std::rotate(id_map.begin() + 3,
id_map.begin() + 4,
id_map.begin() + 5);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// And attempt a mouse drag before the touch drag finishes.
- dragged_button_mouse = SimulateDrag(ShelfButtonHost::MOUSE, 1, 2, false);
+ dragged_button_mouse = SimulateDrag(ShelfView::MOUSE, 1, 2, false);
// Nothing changes since 2nd drag is ignored.
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
- button_host->PointerReleasedOnButton(
- dragged_button_touch, ShelfButtonHost::TOUCH, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button_touch, ShelfView::TOUCH,
+ false);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
}
@@ -1235,8 +1209,6 @@ TEST_F(ShelfViewTest, DragWithNotDraggableItemInFront) {
// Check that clicking first on one item and then dragging another works as
// expected.
TEST_F(ShelfViewTest, ClickOneDragAnother) {
- ShelfButtonHost* button_host = shelf_view_;
-
std::vector<std::pair<ShelfID, views::View*> > id_map;
SetupForDragTest(&id_map);
@@ -1245,14 +1217,10 @@ TEST_F(ShelfViewTest, ClickOneDragAnother) {
// Dragging browser index at 0 should change the model order correctly.
EXPECT_TRUE(model_->items()[1].type == TYPE_BROWSER_SHORTCUT);
- views::View* dragged_button =
- SimulateDrag(ShelfButtonHost::MOUSE, 1, 3, false);
- std::rotate(id_map.begin() + 1,
- id_map.begin() + 2,
- id_map.begin() + 4);
+ views::View* dragged_button = SimulateDrag(ShelfView::MOUSE, 1, 3, false);
+ std::rotate(id_map.begin() + 1, id_map.begin() + 2, id_map.begin() + 4);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
- button_host->PointerReleasedOnButton(
- dragged_button, ShelfButtonHost::MOUSE, false);
+ shelf_view_->PointerReleasedOnButton(dragged_button, ShelfView::MOUSE, false);
EXPECT_TRUE(model_->items()[3].type == TYPE_BROWSER_SHORTCUT);
}
@@ -1375,8 +1343,7 @@ TEST_F(ShelfViewTest, ShelfItemBoundsCheck) {
}
TEST_F(ShelfViewTest, ShelfTooltipTest) {
- ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
- test_api_->GetButtonCount());
+ ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1, test_api_->GetButtonCount());
// Prepare some items to the shelf.
ShelfID app_button_id = AddAppShortcut();
@@ -1385,53 +1352,53 @@ TEST_F(ShelfViewTest, ShelfTooltipTest) {
ShelfButton* app_button = GetButtonByID(app_button_id);
ShelfButton* platform_button = GetButtonByID(platform_button_id);
- ShelfButtonHost* button_host = shelf_view_;
- ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
+ ShelfTooltipManager* tooltip_manager = test_api_->tooltip_manager();
+ EXPECT_TRUE(test_api_->shelf_view()->GetWidget()->GetNativeWindow());
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
- button_host->MouseEnteredButton(app_button);
+ generator.MoveMouseTo(app_button->GetBoundsInScreen().CenterPoint());
// There's a delay to show the tooltip, so it's not visible yet.
EXPECT_FALSE(tooltip_manager->IsVisible());
- EXPECT_EQ(app_button, GetTooltipAnchorView());
+ EXPECT_EQ(nullptr, tooltip_manager->GetCurrentAnchorView());
- ShowTooltip();
+ tooltip_manager->ShowTooltip(app_button);
EXPECT_TRUE(tooltip_manager->IsVisible());
-
- // Once it's visible, it keeps visibility and is pointing to the same
- // item.
- button_host->MouseExitedButton(app_button);
+ EXPECT_EQ(app_button, tooltip_manager->GetCurrentAnchorView());
+
+ // The tooltip will continue showing while the cursor moves between buttons.
+ const gfx::Point midpoint =
+ gfx::UnionRects(app_button->GetBoundsInScreen(),
+ platform_button->GetBoundsInScreen())
+ .CenterPoint();
+ generator.MoveMouseTo(midpoint);
EXPECT_TRUE(tooltip_manager->IsVisible());
- EXPECT_EQ(app_button, GetTooltipAnchorView());
+ EXPECT_EQ(app_button, tooltip_manager->GetCurrentAnchorView());
- // When entered to another item, it switches to the new item. There is no
- // delay for the visibility.
- button_host->MouseEnteredButton(platform_button);
+ // When the cursor moves over another item, its tooltip shows immediately.
+ generator.MoveMouseTo(platform_button->GetBoundsInScreen().CenterPoint());
EXPECT_TRUE(tooltip_manager->IsVisible());
- EXPECT_EQ(platform_button, GetTooltipAnchorView());
-
- button_host->MouseExitedButton(platform_button);
+ EXPECT_EQ(platform_button, tooltip_manager->GetCurrentAnchorView());
tooltip_manager->Close();
- // Next time: enter app_button -> move immediately to tab_button.
- button_host->MouseEnteredButton(app_button);
- button_host->MouseExitedButton(app_button);
- button_host->MouseEnteredButton(platform_button);
+ // Now cursor over the app_button and move immediately to the platform_button.
+ generator.MoveMouseTo(app_button->GetBoundsInScreen().CenterPoint());
+ generator.MoveMouseTo(midpoint);
+ generator.MoveMouseTo(platform_button->GetBoundsInScreen().CenterPoint());
EXPECT_FALSE(tooltip_manager->IsVisible());
- EXPECT_EQ(platform_button, GetTooltipAnchorView());
+ EXPECT_EQ(nullptr, tooltip_manager->GetCurrentAnchorView());
}
// Verify a fix for crash caused by a tooltip update for a deleted shelf
// button, see crbug.com/288838.
TEST_F(ShelfViewTest, RemovingItemClosesTooltip) {
- ShelfButtonHost* button_host = shelf_view_;
- ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
+ ShelfTooltipManager* tooltip_manager = test_api_->tooltip_manager();
// Add an item to the shelf.
ShelfID app_button_id = AddAppShortcut();
ShelfButton* app_button = GetButtonByID(app_button_id);
// Spawn a tooltip on that item.
- button_host->MouseEnteredButton(app_button);
- ShowTooltip();
+ tooltip_manager->ShowTooltip(app_button);
EXPECT_TRUE(tooltip_manager->IsVisible());
// Remove the app shortcut while the tooltip is open. The tooltip should be
@@ -1446,16 +1413,14 @@ TEST_F(ShelfViewTest, RemovingItemClosesTooltip) {
// Changing the shelf alignment closes any open tooltip.
TEST_F(ShelfViewTest, ShelfAlignmentClosesTooltip) {
- ShelfButtonHost* button_host = shelf_view_;
- ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
+ ShelfTooltipManager* tooltip_manager = test_api_->tooltip_manager();
// Add an item to the shelf.
ShelfID app_button_id = AddAppShortcut();
ShelfButton* app_button = GetButtonByID(app_button_id);
// Spawn a tooltip on the item.
- button_host->MouseEnteredButton(app_button);
- ShowTooltip();
+ tooltip_manager->ShowTooltip(app_button);
EXPECT_TRUE(tooltip_manager->IsVisible());
// Changing shelf alignment hides the tooltip.
@@ -1539,8 +1504,8 @@ TEST_F(ShelfViewTest, ShouldHideTooltipWithAppListWindowTest) {
// Test that by moving the mouse cursor off the button onto the bubble it closes
// the bubble.
TEST_F(ShelfViewTest, ShouldHideTooltipWhenHoveringOnTooltip) {
- ShelfTooltipManager* tooltip_manager = shelf_view_->tooltip_manager();
- tooltip_manager->CreateZeroDelayTimerForTest();
+ ShelfTooltipManager* tooltip_manager = test_api_->tooltip_manager();
+ tooltip_manager->set_timer_delay_for_test(0);
ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
// Move the mouse off any item and check that no tooltip is shown.
diff --git a/ash/test/shelf_test_api.cc b/ash/test/shelf_test_api.cc
index d050f73..83bc841 100644
--- a/ash/test/shelf_test_api.cc
+++ b/ash/test/shelf_test_api.cc
@@ -9,12 +9,9 @@
namespace ash {
namespace test {
-ShelfTestAPI::ShelfTestAPI(Shelf* shelf)
- : shelf_(shelf) {
-}
+ShelfTestAPI::ShelfTestAPI(Shelf* shelf) : shelf_(shelf) {}
-ShelfTestAPI::~ShelfTestAPI() {
-}
+ShelfTestAPI::~ShelfTestAPI() {}
ShelfView* ShelfTestAPI::shelf_view() { return shelf_->shelf_view_; }
diff --git a/ash/test/shelf_view_test_api.cc b/ash/test/shelf_view_test_api.cc
index 1ab9dcb..780274e 100644
--- a/ash/test/shelf_view_test_api.cc
+++ b/ash/test/shelf_view_test_api.cc
@@ -101,6 +101,10 @@ OverflowBubble* ShelfViewTestAPI::overflow_bubble() {
return shelf_view_->overflow_bubble_.get();
}
+ShelfTooltipManager* ShelfViewTestAPI::tooltip_manager() {
+ return &shelf_view_->tooltip_;
+}
+
gfx::Size ShelfViewTestAPI::GetPreferredSize() {
return shelf_view_->GetPreferredSize();
}
diff --git a/ash/test/shelf_view_test_api.h b/ash/test/shelf_view_test_api.h
index 9d5f594..9b03588 100644
--- a/ash/test/shelf_view_test_api.h
+++ b/ash/test/shelf_view_test_api.h
@@ -27,6 +27,7 @@ class OverflowBubble;
class ShelfButton;
class ShelfButtonPressedMetricTracker;
class ShelfDelegate;
+class ShelfTooltipManager;
class ShelfView;
namespace test {
@@ -68,6 +69,9 @@ class ShelfViewTestAPI {
// An accessor for |shelf_view|.
ShelfView* shelf_view() { return shelf_view_; }
+ // An accessor for the shelf tooltip manager.
+ ShelfTooltipManager* tooltip_manager();
+
// An accessor for overflow bubble.
OverflowBubble* overflow_bubble();