summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/views/corewm/tooltip_controller.cc10
-rw-r--r--ui/views/corewm/tooltip_controller.h3
-rw-r--r--ui/views/corewm/tooltip_controller_unittest.cc171
-rw-r--r--ui/views/widget/tooltip_manager_aura.cc3
-rw-r--r--ui/wm/public/tooltip_client.cc10
-rw-r--r--ui/wm/public/tooltip_client.h8
6 files changed, 202 insertions, 3 deletions
diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index 86e9fd6..b1ffc1c 100644
--- a/ui/views/corewm/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -115,6 +115,7 @@ aura::Window* GetTooltipTarget(const ui::MouseEvent& event,
TooltipController::TooltipController(scoped_ptr<Tooltip> tooltip)
: tooltip_window_(NULL),
+ tooltip_id_(NULL),
tooltip_window_at_mouse_press_(NULL),
tooltip_(tooltip.Pass()),
tooltips_enabled_(true) {
@@ -282,12 +283,19 @@ void TooltipController::UpdateIfRequired() {
tooltip_window_at_mouse_press_ = NULL;
}
+ // If the uniqueness indicator is different from the previously encountered
+ // one, we should force tooltip update
+ const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_);
+ bool ids_differ = false;
+ ids_differ = tooltip_id_ != tooltip_id;
+ tooltip_id_ = tooltip_id;
+
// We add the !tooltip_->IsVisible() below because when we come here from
// TooltipTimerFired(), the tooltip_text may not have changed but we still
// want to update the tooltip because the timer has fired.
// If we come here from UpdateTooltip(), we have already checked for tooltip
// visibility and this check below will have no effect.
- if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible()) {
+ if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) {
tooltip_shown_timer_.Stop();
tooltip_text_ = tooltip_text;
base::string16 trimmed_text(tooltip_text_);
diff --git a/ui/views/corewm/tooltip_controller.h b/ui/views/corewm/tooltip_controller.h
index 9815df1..e045334 100644
--- a/ui/views/corewm/tooltip_controller.h
+++ b/ui/views/corewm/tooltip_controller.h
@@ -61,7 +61,7 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
void TooltipShownTimerFired();
// Updates the tooltip if required (if there is any change in the tooltip
- // text or the aura::Window.
+ // text, tooltip id or the aura::Window).
void UpdateIfRequired();
// Only used in tests.
@@ -81,6 +81,7 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
aura::Window* tooltip_window_;
base::string16 tooltip_text_;
+ const void* tooltip_id_;
// These fields are for tracking state when the user presses a mouse button.
aura::Window* tooltip_window_at_mouse_press_;
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
index f09a2a0..5460227 100644
--- a/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -671,6 +671,7 @@ class TestTooltip : public Tooltip {
const base::string16& tooltip_text,
const gfx::Point& location) OVERRIDE {
tooltip_text_ = tooltip_text;
+ location_ = location;
}
virtual void Show() OVERRIDE {
is_visible_ = true;
@@ -681,10 +682,12 @@ class TestTooltip : public Tooltip {
virtual bool IsVisible() OVERRIDE {
return is_visible_;
}
+ const gfx::Point& location() { return location_; }
private:
bool is_visible_;
base::string16 tooltip_text_;
+ gfx::Point location_;
DISALLOW_COPY_AND_ASSIGN(TestTooltip);
};
@@ -766,6 +769,174 @@ TEST_F(TooltipControllerTest2, CloseOnCancelMode) {
EXPECT_TRUE(helper_->GetTooltipWindow() == NULL);
}
+// Use for tests that need both views and a TestTooltip.
+class TooltipControllerTest3 : public aura::test::AuraTestBase {
+ public:
+ TooltipControllerTest3() : test_tooltip_(new TestTooltip) {}
+ virtual ~TooltipControllerTest3() {}
+
+ virtual void SetUp() OVERRIDE {
+ wm_state_.reset(new wm::WMState);
+ aura::test::AuraTestBase::SetUp();
+ new wm::DefaultActivationClient(root_window());
+
+ widget_.reset(CreateWidget(root_window()));
+ widget_->SetContentsView(new View);
+ view_ = new TooltipTestView;
+ widget_->GetContentsView()->AddChildView(view_);
+ view_->SetBoundsRect(widget_->GetContentsView()->GetLocalBounds());
+
+ generator_.reset(new aura::test::EventGenerator(GetRootWindow()));
+ controller_.reset(new TooltipController(
+ scoped_ptr<views::corewm::Tooltip>(test_tooltip_)));
+ GetRootWindow()->RemovePreTargetHandler(
+ static_cast<TooltipController*>(aura::client::GetTooltipClient(
+ widget_->GetNativeWindow()->GetRootWindow())));
+ GetRootWindow()->AddPreTargetHandler(controller_.get());
+ helper_.reset(new TooltipControllerTestHelper(controller_.get()));
+ SetTooltipClient(GetRootWindow(), controller_.get());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ GetRootWindow()->RemovePreTargetHandler(controller_.get());
+ aura::client::SetTooltipClient(GetRootWindow(), NULL);
+
+ controller_.reset();
+ generator_.reset();
+ helper_.reset();
+ widget_.reset();
+ aura::test::AuraTestBase::TearDown();
+ wm_state_.reset();
+ }
+
+ aura::Window* GetWindow() { return widget_->GetNativeWindow(); }
+
+ protected:
+ // Owned by |controller_|.
+ TestTooltip* test_tooltip_;
+ scoped_ptr<TooltipControllerTestHelper> helper_;
+ scoped_ptr<aura::test::EventGenerator> generator_;
+ scoped_ptr<views::Widget> widget_;
+ TooltipTestView* view_;
+
+ private:
+ scoped_ptr<TooltipController> controller_;
+ scoped_ptr<wm::WMState> wm_state_;
+
+#if defined(OS_WIN)
+ ui::ScopedOleInitializer ole_initializer_;
+#endif
+
+ aura::Window* GetRootWindow() { return GetWindow()->GetRootWindow(); }
+
+ DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest3);
+};
+
+TEST_F(TooltipControllerTest3, TooltipPositionChangesOnTwoViewsWithSameLabel) {
+ // Owned by |view_|.
+ // These two views have the same tooltip text
+ TooltipTestView* v1 = new TooltipTestView;
+ TooltipTestView* v2 = new TooltipTestView;
+ // v1_1 is a view inside v1 that has an identical tooltip text to that of v1
+ // and v2
+ TooltipTestView* v1_1 = new TooltipTestView;
+ // v2_1 is a view inside v2 that has an identical tooltip text to that of v1
+ // and v2
+ TooltipTestView* v2_1 = new TooltipTestView;
+ // v2_2 is a view inside v2 with the tooltip text different from all the
+ // others
+ TooltipTestView* v2_2 = new TooltipTestView;
+
+ // Setup all the views' relations
+ view_->AddChildView(v1);
+ view_->AddChildView(v2);
+ v1->AddChildView(v1_1);
+ v2->AddChildView(v2_1);
+ v2->AddChildView(v2_2);
+ const base::string16 reference_string(
+ base::ASCIIToUTF16("Identical Tooltip Text"));
+ const base::string16 alternative_string(
+ base::ASCIIToUTF16("Another Shrubbery"));
+ v1->set_tooltip_text(reference_string);
+ v2->set_tooltip_text(reference_string);
+ v1_1->set_tooltip_text(reference_string);
+ v2_1->set_tooltip_text(reference_string);
+ v2_2->set_tooltip_text(alternative_string);
+
+ // Set views' bounds
+ gfx::Rect view_bounds(view_->GetLocalBounds());
+ view_bounds.set_height(view_bounds.height() / 2);
+ v1->SetBoundsRect(view_bounds);
+ v1_1->SetBounds(0, 0, 3, 3);
+ view_bounds.set_y(view_bounds.height());
+ v2->SetBoundsRect(view_bounds);
+ v2_2->SetBounds(view_bounds.width() - 3, view_bounds.height() - 3, 3, 3);
+ v2_1->SetBounds(0, 0, 3, 3);
+
+ // Test whether a toolbar appears on v1
+ gfx::Point center = v1->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+ gfx::Point tooltip_bounds1 = test_tooltip_->location();
+
+ // Test whether the toolbar changes position on mouse over v2
+ center = v2->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+ gfx::Point tooltip_bounds2 = test_tooltip_->location();
+
+ EXPECT_NE(tooltip_bounds1, gfx::Point());
+ EXPECT_NE(tooltip_bounds2, gfx::Point());
+ EXPECT_NE(tooltip_bounds1, tooltip_bounds2);
+
+ // Test if the toolbar does not change position on encountering a contained
+ // view with the same tooltip text
+ center = v2_1->GetLocalBounds().CenterPoint();
+ views::View::ConvertPointToTarget(v2_1, view_, &center);
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ gfx::Point tooltip_bounds2_1 = test_tooltip_->location();
+
+ EXPECT_NE(tooltip_bounds2, tooltip_bounds2_1);
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+
+ // Test if the toolbar changes position on encountering a contained
+ // view with a different tooltip text
+ center = v2_2->GetLocalBounds().CenterPoint();
+ views::View::ConvertPointToTarget(v2_2, view_, &center);
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ gfx::Point tooltip_bounds2_2 = test_tooltip_->location();
+
+ EXPECT_NE(tooltip_bounds2_1, tooltip_bounds2_2);
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(alternative_string, helper_->GetTooltipText());
+
+ // Test if moving from a view that is contained by a larger view, both with
+ // the same tooltip text, does not change tooltip's position.
+ center = v1_1->GetLocalBounds().CenterPoint();
+ views::View::ConvertPointToTarget(v1_1, view_, &center);
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ gfx::Point tooltip_bounds1_1 = test_tooltip_->location();
+
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+
+ center = v1->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ tooltip_bounds1 = test_tooltip_->location();
+
+ EXPECT_NE(tooltip_bounds1_1, tooltip_bounds1);
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+}
+
} // namespace test
} // namespace corewm
} // namespace views
diff --git a/ui/views/widget/tooltip_manager_aura.cc b/ui/views/widget/tooltip_manager_aura.cc
index 986ea5d..99ae9e6 100644
--- a/ui/views/widget/tooltip_manager_aura.cc
+++ b/ui/views/widget/tooltip_manager_aura.cc
@@ -133,6 +133,9 @@ void TooltipManagerAura::UpdateTooltipForTarget(View* target,
} else {
tooltip_text_.clear();
}
+
+ aura::client::SetTooltipId(GetWindow(), target);
+
aura::client::GetTooltipClient(root_window)->UpdateTooltip(GetWindow());
}
diff --git a/ui/wm/public/tooltip_client.cc b/ui/wm/public/tooltip_client.cc
index b473238..844cca5 100644
--- a/ui/wm/public/tooltip_client.cc
+++ b/ui/wm/public/tooltip_client.cc
@@ -9,6 +9,7 @@
DECLARE_WINDOW_PROPERTY_TYPE(aura::client::TooltipClient*)
DECLARE_WINDOW_PROPERTY_TYPE(base::string16*)
+DECLARE_WINDOW_PROPERTY_TYPE(void**)
namespace aura {
namespace client {
@@ -16,6 +17,7 @@ namespace client {
DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
TooltipClient*, kRootWindowTooltipClientKey, NULL);
DEFINE_LOCAL_WINDOW_PROPERTY_KEY(base::string16*, kTooltipTextKey, NULL);
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(void*, kTooltipIdKey, NULL);
void SetTooltipClient(Window* root_window, TooltipClient* client) {
DCHECK_EQ(root_window->GetRootWindow(), root_window);
@@ -33,10 +35,18 @@ void SetTooltipText(Window* window, base::string16* tooltip_text) {
window->SetProperty(kTooltipTextKey, tooltip_text);
}
+void SetTooltipId(Window* window, void* id) {
+ window->SetProperty(kTooltipIdKey, id);
+}
+
const base::string16 GetTooltipText(Window* window) {
base::string16* string_ptr = window->GetProperty(kTooltipTextKey);
return string_ptr ? *string_ptr : base::string16();
}
+const void* GetTooltipId(Window* window) {
+ return window->GetProperty(kTooltipIdKey);
+}
+
} // namespace client
} // namespace aura
diff --git a/ui/wm/public/tooltip_client.h b/ui/wm/public/tooltip_client.h
index f592b21..f2b97cd 100644
--- a/ui/wm/public/tooltip_client.h
+++ b/ui/wm/public/tooltip_client.h
@@ -36,8 +36,14 @@ AURA_EXPORT void SetTooltipClient(Window* root_window,
TooltipClient* client);
AURA_EXPORT TooltipClient* GetTooltipClient(Window* root_window);
-AURA_EXPORT void SetTooltipText(Window* window, base::string16* tooltip_text);
+// Sets the text for the tooltip. The id is used to determine uniqueness when
+// the text does not change. For example, if the tooltip text does not change,
+// but the id does then the position of the tooltip is updated.
+AURA_EXPORT void SetTooltipText(Window* window,
+ base::string16* tooltip_text);
+AURA_EXPORT void SetTooltipId(Window* window, void* id);
AURA_EXPORT const base::string16 GetTooltipText(Window* window);
+AURA_EXPORT const void* GetTooltipId(Window* window);
} // namespace client
} // namespace aura