Refine ash shelf tooltip closing on non-mash ChromeOS.
Fixes a regression from: https://codereview.chromium.org/1816753002 Also reverse expected behavior for touching tooltips. (closes on stable, tests expected them to stay open...) Inline bubble function definitions. Call WillDeleteShelf earlier to fix a test crash... TODO: Encapsulate more ShelfLayoutManager code. BUG=595853 TEST=ChromeOS tooltips stay open on hover; close for external touches. R=sky@chromium.org Review URL: https://codereview.chromium.org/1828133004 Cr-Commit-Position: refs/heads/master@{#383404}
This commit is contained in:
@ -236,6 +236,7 @@ void ShelfLayoutManager::PrepareForShutdown() {
|
|||||||
// Stop observing window change, otherwise we can attempt to update a
|
// Stop observing window change, otherwise we can attempt to update a
|
||||||
// partially destructed shelf.
|
// partially destructed shelf.
|
||||||
aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
|
aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
|
||||||
|
FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, WillDeleteShelf());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShelfLayoutManager::IsVisible() const {
|
bool ShelfLayoutManager::IsVisible() const {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
namespace ash {
|
namespace ash {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const int kTooltipTopBottomMargin = 3;
|
const int kTooltipTopBottomMargin = 3;
|
||||||
const int kTooltipLeftRightMargin = 10;
|
const int kTooltipLeftRightMargin = 10;
|
||||||
const int kTooltipAppearanceDelay = 1000; // msec
|
const int kTooltipAppearanceDelay = 1000; // msec
|
||||||
@ -48,54 +49,47 @@ class ShelfTooltipManager::ShelfTooltipBubble
|
|||||||
public:
|
public:
|
||||||
ShelfTooltipBubble(views::View* anchor,
|
ShelfTooltipBubble(views::View* anchor,
|
||||||
views::BubbleBorder::Arrow arrow,
|
views::BubbleBorder::Arrow arrow,
|
||||||
const base::string16& text);
|
const base::string16& text)
|
||||||
|
: views::BubbleDelegateView(anchor, arrow) {
|
||||||
|
gfx::Insets insets =
|
||||||
|
gfx::Insets(kArrowOffsetTopBottom, kArrowOffsetLeftRight);
|
||||||
|
// Adjust the anchor location for asymmetrical borders of shelf item.
|
||||||
|
if (anchor->border())
|
||||||
|
insets += anchor->border()->GetInsets();
|
||||||
|
|
||||||
|
set_anchor_view_insets(insets);
|
||||||
|
set_close_on_esc(false);
|
||||||
|
set_close_on_deactivate(false);
|
||||||
|
set_can_activate(false);
|
||||||
|
set_accept_events(false);
|
||||||
|
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()->GetNativeWindow()) {
|
||||||
|
set_parent_window(ash::Shell::GetContainer(
|
||||||
|
anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
|
||||||
|
ash::kShellWindowId_SettingBubbleContainer));
|
||||||
|
}
|
||||||
|
views::Label* label = new views::Label(text);
|
||||||
|
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
||||||
|
label->SetEnabledColor(kTooltipTextColor);
|
||||||
|
AddChildView(label);
|
||||||
|
views::BubbleDelegateView::CreateBubble(this);
|
||||||
|
SizeToContents();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// views::View overrides:
|
// views::View overrides:
|
||||||
gfx::Size GetPreferredSize() const override;
|
gfx::Size GetPreferredSize() const override {
|
||||||
|
const gfx::Size size = views::BubbleDelegateView::GetPreferredSize();
|
||||||
|
return gfx::Size(std::min(size.width(), kTooltipMaxWidth),
|
||||||
|
std::max(size.height(), kTooltipMinHeight));
|
||||||
|
}
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble);
|
DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble);
|
||||||
};
|
};
|
||||||
|
|
||||||
ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble(
|
|
||||||
views::View* anchor,
|
|
||||||
views::BubbleBorder::Arrow arrow,
|
|
||||||
const base::string16& text)
|
|
||||||
: views::BubbleDelegateView(anchor, arrow) {
|
|
||||||
gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom,
|
|
||||||
kArrowOffsetLeftRight);
|
|
||||||
// Adjust the anchor location for asymmetrical borders of shelf item.
|
|
||||||
if (anchor->border())
|
|
||||||
insets += anchor->border()->GetInsets();
|
|
||||||
|
|
||||||
set_anchor_view_insets(insets);
|
|
||||||
set_close_on_esc(false);
|
|
||||||
set_close_on_deactivate(false);
|
|
||||||
set_can_activate(false);
|
|
||||||
set_accept_events(false);
|
|
||||||
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()->GetNativeWindow()) {
|
|
||||||
set_parent_window(ash::Shell::GetContainer(
|
|
||||||
anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
|
|
||||||
ash::kShellWindowId_SettingBubbleContainer));
|
|
||||||
}
|
|
||||||
views::Label* label = new views::Label(text);
|
|
||||||
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
|
||||||
label->SetEnabledColor(kTooltipTextColor);
|
|
||||||
AddChildView(label);
|
|
||||||
views::BubbleDelegateView::CreateBubble(this);
|
|
||||||
SizeToContents();
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx::Size ShelfTooltipManager::ShelfTooltipBubble::GetPreferredSize() const {
|
|
||||||
const gfx::Size size = views::BubbleDelegateView::GetPreferredSize();
|
|
||||||
return gfx::Size(std::min(size.width(), kTooltipMaxWidth),
|
|
||||||
std::max(size.height(), kTooltipMinHeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
ShelfTooltipManager::ShelfTooltipManager(ShelfView* shelf_view)
|
ShelfTooltipManager::ShelfTooltipManager(ShelfView* shelf_view)
|
||||||
: timer_delay_(kTooltipAppearanceDelay),
|
: timer_delay_(kTooltipAppearanceDelay),
|
||||||
shelf_view_(shelf_view),
|
shelf_view_(shelf_view),
|
||||||
@ -110,8 +104,10 @@ ShelfTooltipManager::~ShelfTooltipManager() {
|
|||||||
void ShelfTooltipManager::Init() {
|
void ShelfTooltipManager::Init() {
|
||||||
shelf_layout_manager_ = shelf_view_->shelf()->shelf_layout_manager();
|
shelf_layout_manager_ = shelf_view_->shelf()->shelf_layout_manager();
|
||||||
shelf_layout_manager_->AddObserver(this);
|
shelf_layout_manager_->AddObserver(this);
|
||||||
// TODO(msw): Capture events outside the shelf to close tooltips?
|
|
||||||
shelf_view_->GetWidget()->GetNativeWindow()->AddPreTargetHandler(this);
|
// TODO(msw): Observe events outside the shelf in mash, to close tooltips.
|
||||||
|
aura::Window* shelf_window = shelf_view_->GetWidget()->GetNativeWindow();
|
||||||
|
shelf_window->GetRootWindow()->AddPreTargetHandler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShelfTooltipManager::Close() {
|
void ShelfTooltipManager::Close() {
|
||||||
@ -164,31 +160,29 @@ void ShelfTooltipManager::ShowTooltipWithDelay(views::View* view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ShelfTooltipManager::OnEvent(ui::Event* event) {
|
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 ||
|
if (event->type() == ui::ET_MOUSE_PRESSED ||
|
||||||
event->type() == ui::ET_MOUSE_EXITED || !event->IsMouseEvent()) {
|
event->type() == ui::ET_MOUSE_EXITED || !event->IsMouseEvent() ||
|
||||||
|
event->target() != shelf_view_->GetWidget()->GetNativeWindow()) {
|
||||||
if (!event->IsKeyEvent())
|
if (!event->IsKeyEvent())
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Point point = static_cast<ui::LocatedEvent*>(event)->location();
|
gfx::Point point = static_cast<ui::LocatedEvent*>(event)->location();
|
||||||
|
aura::Window::ConvertPointToTarget(
|
||||||
|
static_cast<aura::Window*>(event->target()),
|
||||||
|
shelf_view_->GetWidget()->GetNativeWindow(), &point);
|
||||||
views::View::ConvertPointFromWidget(shelf_view_, &point);
|
views::View::ConvertPointFromWidget(shelf_view_, &point);
|
||||||
if (IsVisible() && shelf_view_->ShouldHideTooltip(point)) {
|
|
||||||
Close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
views::View* view = shelf_view_->GetTooltipHandlerForPoint(point);
|
views::View* view = shelf_view_->GetTooltipHandlerForPoint(point);
|
||||||
const bool should_show = shelf_view_->ShouldShowTooltipForView(view);
|
const bool should_show = shelf_view_->ShouldShowTooltipForView(view);
|
||||||
if (IsVisible() && bubble_->GetAnchorView() != view && should_show)
|
|
||||||
ShowTooltip(view);
|
|
||||||
|
|
||||||
if (!IsVisible() && event->type() == ui::ET_MOUSE_MOVED) {
|
timer_.Stop();
|
||||||
timer_.Stop();
|
if (IsVisible() && should_show && bubble_->GetAnchorView() != view)
|
||||||
if (should_show)
|
ShowTooltip(view);
|
||||||
ShowTooltipWithDelay(view);
|
else if (!IsVisible() && should_show && event->type() == ui::ET_MOUSE_MOVED)
|
||||||
}
|
ShowTooltipWithDelay(view);
|
||||||
|
else if (IsVisible() && shelf_view_->ShouldHideTooltip(point))
|
||||||
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShelfTooltipManager::WillDeleteShelf() {
|
void ShelfTooltipManager::WillDeleteShelf() {
|
||||||
@ -196,9 +190,11 @@ void ShelfTooltipManager::WillDeleteShelf() {
|
|||||||
shelf_layout_manager_->RemoveObserver(this);
|
shelf_layout_manager_->RemoveObserver(this);
|
||||||
shelf_layout_manager_ = nullptr;
|
shelf_layout_manager_ = nullptr;
|
||||||
|
|
||||||
views::Widget* widget = shelf_view_ ? shelf_view_->GetWidget() : nullptr;
|
if (shelf_view_ && shelf_view_->GetWidget()) {
|
||||||
if (widget && widget->GetNativeWindow())
|
aura::Window* shelf_window = shelf_view_->GetWidget()->GetNativeWindow();
|
||||||
widget->GetNativeWindow()->RemovePreTargetHandler(this);
|
if (shelf_window && shelf_window->GetRootWindow())
|
||||||
|
shelf_window->GetRootWindow()->RemovePreTargetHandler(this);
|
||||||
|
}
|
||||||
shelf_view_ = nullptr;
|
shelf_view_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,34 +173,40 @@ TEST_F(ShelfTooltipManagerTest, HideForEvents) {
|
|||||||
EXPECT_FALSE(TooltipIsVisible());
|
EXPECT_FALSE(TooltipIsVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(msw): Hiding for touch and gesture events outside the shelf is broken.
|
TEST_F(ShelfTooltipManagerTest, HideForExternalEvents) {
|
||||||
TEST_F(ShelfTooltipManagerTest, HideForEventsBroken) {
|
|
||||||
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
|
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
|
||||||
|
// TODO(msw): Observe events outside the shelf in mash, to close tooltips.
|
||||||
|
aura::Window* shelf_window = shelf_->shelf_widget()->GetNativeWindow();
|
||||||
|
bool closes = shelf_window->GetRootWindow() == Shell::GetPrimaryRootWindow();
|
||||||
|
|
||||||
|
// Should hide for touches outside the shelf.
|
||||||
ShowImmediately();
|
ShowImmediately();
|
||||||
ASSERT_TRUE(TooltipIsVisible());
|
ASSERT_TRUE(TooltipIsVisible());
|
||||||
|
|
||||||
generator.set_current_location(gfx::Point());
|
generator.set_current_location(gfx::Point());
|
||||||
generator.PressTouch();
|
generator.PressTouch();
|
||||||
EXPECT_TRUE(TooltipIsVisible());
|
EXPECT_EQ(TooltipIsVisible(), !closes);
|
||||||
|
|
||||||
generator.GestureTapDownAndUp(gfx::Point());
|
|
||||||
EXPECT_TRUE(TooltipIsVisible());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ShelfTooltipManagerTest, DoNotHideForEvents) {
|
|
||||||
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
|
|
||||||
|
|
||||||
|
// Should hide for touch events on the tooltip.
|
||||||
ShowImmediately();
|
ShowImmediately();
|
||||||
ASSERT_TRUE(TooltipIsVisible());
|
ASSERT_TRUE(TooltipIsVisible());
|
||||||
|
|
||||||
// Should not hide for key events.
|
|
||||||
generator.PressKey(ui::VKEY_A, ui::EF_NONE);
|
|
||||||
EXPECT_TRUE(TooltipIsVisible());
|
|
||||||
|
|
||||||
// Should not hide for touch events on the tooltip.
|
|
||||||
generator.set_current_location(GetTooltipWindow()->bounds().CenterPoint());
|
generator.set_current_location(GetTooltipWindow()->bounds().CenterPoint());
|
||||||
generator.PressTouch();
|
generator.PressTouch();
|
||||||
|
EXPECT_EQ(TooltipIsVisible(), !closes);
|
||||||
|
|
||||||
|
// Should hide for gestures outside the shelf.
|
||||||
|
ShowImmediately();
|
||||||
|
ASSERT_TRUE(TooltipIsVisible());
|
||||||
|
generator.GestureTapDownAndUp(gfx::Point());
|
||||||
|
EXPECT_EQ(TooltipIsVisible(), !closes);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ShelfTooltipManagerTest, DoNotHideForKeyEvents) {
|
||||||
|
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
|
||||||
|
|
||||||
|
// Should not hide for key events.
|
||||||
|
ShowImmediately();
|
||||||
|
ASSERT_TRUE(TooltipIsVisible());
|
||||||
|
generator.PressKey(ui::VKEY_A, ui::EF_NONE);
|
||||||
EXPECT_TRUE(TooltipIsVisible());
|
EXPECT_TRUE(TooltipIsVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user