Merge lp:~jjed/unity/tooltips-redux into lp:unity

Proposed by Jjed
Status: Merged
Approved by: Stephen M. Webb
Approved revision: 3198
Merged at revision: 3191
Proposed branch: lp:~jjed/unity/tooltips-redux
Merge into: lp:unity
Diff against target: 564 lines (+356/-36)
11 files modified
launcher/AbstractLauncherIcon.h (+1/-0)
launcher/CMakeLists.txt (+1/-0)
launcher/Launcher.cpp (+21/-24)
launcher/Launcher.h (+3/-0)
launcher/LauncherIcon.cpp (+0/-11)
launcher/MockLauncherIcon.h (+5/-1)
launcher/TooltipManager.cpp (+126/-0)
launcher/TooltipManager.h (+57/-0)
tests/CMakeLists.txt (+1/-0)
tests/autopilot/unity/tests/launcher/test_tooltips.py (+87/-0)
tests/test_tooltip_manager.cpp (+54/-0)
To merge this branch: bzr merge lp:~jjed/unity/tooltips-redux
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Stephen M. Webb (community) Approve
Marco Trevisan (Treviño) Approve
Jjed (community) Needs Resubmitting
Thomi Richards Pending
Review via email: mp+150942@code.launchpad.net

Commit message

Add a 1s delay between hovering on a launcher icon and showing its tooltip.
Further tooltips before clicking or unhovering launcher will appear instantly.

Description of the change

== Problem

There is currently no delay between hovering on a Launcher icon and displaying its tooltip.

This proposal supercedes the (long defunct) lp:~j-johan-edwards/unity/tooltip-delay/ merge proposal.

== Fix implementation

I've removed the ability of `LauncherIcon` to prompt its own tooltip display. Instead, a new object `TooltipManager`
(notified of events by a monitor's `Launcher`) controls launcher tooltip logic according to a `_hover_timer` which resets on mouse movement. A `LauncherIcon` may refuse to display based on its local condition (eg if it is the BFB and active, or being dragged).

Clicking an icon causes its tooltip to disappear, and the `_hover_clock` to be "locked" until the mouse moves to another icon. This behavior feels right to me (as otherwise tooltips appear while you hover over an app you just clicked, waiting for it to open) but I'm open to changing it.

Tooltip delay is 1s per lp:#687956. Let me know if the design has changed.

== Testing

There are three new autopilot tests in `test_tooltips`. Dash tooltip behavior is further tested in `test_icon_behavior`.

`autopilot run unity.tests.launcher` passes. I have only one monitor.

== Old feedback

I'm using `assertTrue` in my tooltips test because the behavior tested is time-specific, and `assertThat(.... Eventually(Equals(bool))` doesn't distinguish between instantaneous and delayed tooltip display. Maybe there's some other way...?

To post a comment you must log in.
Revision history for this message
Stephen M. Webb (bregma) wrote :

(1) Please fix the copyright dates in the new source files.
(2) Please do not prepend an underscore wart to indicate a member variable: the Unity style is to use appended underscore warts.
(3) You need to add a commit message to this MP.

Other than that, this seems OK.

review: Needs Fixing
lp:~jjed/unity/tooltips-redux updated
3184. By Jacob Edwards

Fix copyright messages in new source files

3185. By Jacob Edwards

Rename _tooltip_manager to tooltip_manager_

3186. By Jacob Edwards

Obey Unity Style guide for private variable naming in new modules

Revision history for this message
Jjed (jjed) wrote :

I believe that should fix them. Thanks for the quick review!

review: Needs Resubmitting
Revision history for this message
Andrea Azzarone (azzar1) wrote :

+#define NULL_ICON (AbstractLauncherIcon::Ptr)nullptr

Don't do this please :)

314 +void TooltipManager::StopTimer() {
315 + hover_timer_.reset(new glib::Timeout(TOOLTIPS_SHOW_TIMEOUT_LENGTH));
316 +}

Is this the right way to stop the timeout?

Also I think you can unit test the new class ;)

lp:~jjed/unity/tooltips-redux updated
3187. By Jacob Edwards

Remove readability NULL_ICON macro in Launcher.cpp

3188. By Jacob Edwards

Add a unit test for TooltipManager, which tests its one outside interaction.

3189. By Jacob Edwards

Merge with trunk

Revision history for this message
Jjed (jjed) wrote :

> Don't do this please :)

Okay, removed.

> Is this the right way to stop the timeout?

It seems to be (you can `grep -R "reset(new glib::Timeout" to see similar uses). `hover_timer_->Remove() would also stop it, but then I'd just need add the same line afterwards to set a new timeout.

> Also I think you can unit test the new class

Okay, added. There's not much to test, as the modules only interaction with the outside world is calling `icon_->ShowTooltip()` and `icon_->HideTooltip()`. Tell me if there are any other test cases you'd like to see.

lp:~jjed/unity/tooltips-redux updated
3190. By Jacob Edwards

Merge with trunk

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

324 +void TooltipManager::StopTimer() {
325 + hover_timer_.reset(new glib::Timeout(TOOLTIPS_SHOW_TIMEOUT_LENGTH));
326 +}

Please just call hover_timer_.reset();

Then when you need to start it again, reset it to a new one.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> > Don't do this please :)
>
> Okay, removed.
>
> > Is this the right way to stop the timeout?
>
> It seems to be (you can `grep -R "reset(new glib::Timeout" to see similar
> uses). `hover_timer_->Remove() would also stop it, but then I'd just need add
> the same line afterwards to set a new timeout.

hover_timer_->reset() should just work.

>
> > Also I think you can unit test the new class
>
> Okay, added. There's not much to test, as the modules only interaction with
> the outside world is calling `icon_->ShowTooltip()` and
> `icon_->HideTooltip()`. Tell me if there are any other test cases you'd like
> to see.

lp:~jjed/unity/tooltips-redux updated
3191. By Jacob Edwards

Use correct timer reset for StopTimer() and StartTimer()

Revision history for this message
Jjed (jjed) wrote :

Okay, that works (and does fewer glib::Timeout allocations too).

lp:~jjed/unity/tooltips-redux updated
3192. By Jacob Edwards

Merge trunk

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

81 + SetIconUnderMouse((AbstractLauncherIcon::Ptr)nullptr);

Please pass an empty icon PTR to the function as it expects:
SetIconUnderMouse(AbstractLauncherIcon::Ptr());

245 + : show_tooltips_(false)
246 + , hovered_(false)
247 + , icon_(nullptr)
248 + , icon_clicked_(false)

This is pure style, but we use 2-spaces to indent initialization list, also you don't need to initialize the icon_ at all.

366 +class TooltipManager : public sigc::trackable

You don't need sigc::trackable, but you probably want this to be non-copyable instead.

371 + void SetHover(bool on_launcher);

What about a nux::Property<bool> for this?

258 + if (show_tooltips_) {

Please add a space after the if statements (so that the brace is on the new line)

539 + tm.SetIcon((AbstractLauncherIcon::Ptr)icon);

Pass to it an icon ptr: tm.SetIcon(AbstractLauncherIcon::Ptr(icon));

lp:~jjed/unity/tooltips-redux updated
3193. By Jacob Edwards

Adhere to Unity brace style

3194. By Jacob Edwards

Tidy up private declarations

3195. By Jacob Edwards

Replace AbstractLauncherIcon type hints with constructors.

3196. By Jacob Edwards

Make TooltipMananger noncopyable.

Revision history for this message
Jjed (jjed) wrote :

Okay, changed most of that.

> 371 + void SetHover(bool on_launcher);
>
> What about a nux::Property<bool> for this?

I don't think that makes sense, given that `hover_` is private and the TooltipMannager doesn't need any internal hooks for when it changes. LauncherHoverMachine already has a signal for changing hover-state as well.

lp:~jjed/unity/tooltips-redux updated
3197. By Jacob Edwards

Merge trunk

3198. By Jacob Edwards

Fitz around with a variable name for readability

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Cool, this is fine now..

Stephen, are you ok now with removing the "Needs fixing" flag? :)

review: Approve
Revision history for this message
Stephen M. Webb (bregma) wrote :

Looks good.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)
Revision history for this message
Adolfo Jayme (fitojb) wrote :

As Launcher icons don't visually change at all when hovered with the mouse, Unity again feels so sluggish/unresponsive, that I have to wonder if it has freezed. I reported that as bug 1152390.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'launcher/AbstractLauncherIcon.h'
2--- launcher/AbstractLauncherIcon.h 2013-02-22 10:55:18 +0000
3+++ launcher/AbstractLauncherIcon.h 2013-03-05 21:56:20 +0000
4@@ -135,6 +135,7 @@
5 nux::Property<Position> position;
6 nux::Property<bool> removed;
7
8+ virtual void ShowTooltip() = 0;
9 virtual void HideTooltip() = 0;
10
11 virtual void SetShortcut(guint64 shortcut) = 0;
12
13=== modified file 'launcher/CMakeLists.txt'
14--- launcher/CMakeLists.txt 2012-12-19 20:53:12 +0000
15+++ launcher/CMakeLists.txt 2013-03-05 21:56:20 +0000
16@@ -57,6 +57,7 @@
17 SoftwareCenterLauncherIcon.cpp
18 SpacerLauncherIcon.cpp
19 Tooltip.cpp
20+ TooltipManager.cpp
21 TrashLauncherIcon.cpp
22 VolumeImp.cpp
23 VolumeLauncherIcon.cpp
24
25=== modified file 'launcher/Launcher.cpp'
26--- launcher/Launcher.cpp 2013-03-05 15:59:56 +0000
27+++ launcher/Launcher.cpp 2013-03-05 21:56:20 +0000
28@@ -286,6 +286,21 @@
29 _hide_machine.SetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER, over_launcher);
30 _hide_machine.SetQuirk(LauncherHideMachine::REVEAL_PRESSURE_PASS, false);
31 _hover_machine.SetQuirk(LauncherHoverMachine::MOUSE_OVER_LAUNCHER, over_launcher);
32+ tooltip_manager_.SetHover(over_launcher);
33+}
34+
35+void Launcher::SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon)
36+{
37+ if (_icon_under_mouse == icon)
38+ return;
39+
40+ if (_icon_under_mouse)
41+ _icon_under_mouse->mouse_leave.emit(monitor);
42+ if (icon)
43+ icon->mouse_enter.emit(monitor);
44+
45+ _icon_under_mouse = icon;
46+ tooltip_manager_.SetIcon(icon);
47 }
48
49 bool Launcher::MouseBeyondDragThreshold() const
50@@ -1603,8 +1618,7 @@
51 if (icon->needs_redraw_connection.connected())
52 icon->needs_redraw_connection.disconnect();
53
54- if (icon == _icon_under_mouse)
55- _icon_under_mouse = nullptr;
56+ SetIconUnderMouse(AbstractLauncherIcon::Ptr());
57 if (icon == _icon_mouse_down)
58 _icon_mouse_down = nullptr;
59 if (icon == _drag_icon)
60@@ -1923,11 +1937,7 @@
61 // if we are still waiting…
62 if (GetActionState() == ACTION_NONE)
63 {
64- if (_icon_under_mouse)
65- {
66- _icon_under_mouse->mouse_leave.emit(monitor);
67- _icon_under_mouse = nullptr;
68- }
69+ SetIconUnderMouse(AbstractLauncherIcon::Ptr());
70 _initial_drag_animation = true;
71 StartIconDragRequest(x, y);
72 }
73@@ -2166,11 +2176,7 @@
74 GetActionState() == ACTION_NONE)
75 return;
76
77- if (_icon_under_mouse)
78- {
79- _icon_under_mouse->mouse_leave.emit(monitor);
80- _icon_under_mouse = nullptr;
81- }
82+ SetIconUnderMouse(AbstractLauncherIcon::Ptr());
83
84 if (GetActionState() == ACTION_NONE)
85 {
86@@ -2222,6 +2228,7 @@
87 void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
88 {
89 SetMousePosition(x, y);
90+ tooltip_manager_.MouseMoved();
91
92 if (!_hidden)
93 UpdateChangeInMousePosition(dx, dy);
94@@ -2370,18 +2377,7 @@
95 launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
96 }
97
98-
99- if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
100- {
101- _icon_under_mouse->mouse_leave.emit(monitor);
102- _icon_under_mouse = nullptr;
103- }
104-
105- if (launcher_icon && (_icon_under_mouse != launcher_icon))
106- {
107- launcher_icon->mouse_enter.emit(monitor);
108- _icon_under_mouse = launcher_icon;
109- }
110+ SetIconUnderMouse(launcher_icon);
111 }
112
113 void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
114@@ -2396,6 +2392,7 @@
115 sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT);
116
117 launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
118+ tooltip_manager_.IconClicked();
119 }
120 }
121
122
123=== modified file 'launcher/Launcher.h'
124--- launcher/Launcher.h 2013-03-05 14:30:46 +0000
125+++ launcher/Launcher.h 2013-03-05 21:56:20 +0000
126@@ -42,6 +42,7 @@
127 #include "unity-shared/MockableBaseWindow.h"
128 #include "unity-shared/UBusWrapper.h"
129 #include "SoftwareCenterLauncherIcon.h"
130+#include "TooltipManager.h"
131
132 #ifdef USE_X11
133 # include "PointerBarrier.h"
134@@ -223,6 +224,7 @@
135 bool OnScrollTimeout();
136
137 void SetMousePosition(int x, int y);
138+ void SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon);
139
140 void SetStateMouseOverLauncher(bool over_launcher);
141
142@@ -389,6 +391,7 @@
143 nux::ObjectPtr<LauncherDragWindow> _drag_window;
144 LauncherHideMachine _hide_machine;
145 LauncherHoverMachine _hover_machine;
146+ TooltipManager tooltip_manager_;
147
148 unity::DndData _dnd_data;
149 nux::DndAction _drag_action;
150
151=== modified file 'launcher/LauncherIcon.cpp'
152--- launcher/LauncherIcon.cpp 2013-02-22 10:55:18 +0000
153+++ launcher/LauncherIcon.cpp 2013-03-05 21:56:20 +0000
154@@ -528,23 +528,12 @@
155 LauncherIcon::RecvMouseEnter(int monitor)
156 {
157 _last_monitor = monitor;
158- if (QuicklistManager::Default()->Current())
159- {
160- // A quicklist is active
161- return;
162- }
163-
164- ShowTooltip();
165 }
166
167 void LauncherIcon::RecvMouseLeave(int monitor)
168 {
169 _last_monitor = -1;
170 _allow_quicklist_to_show = true;
171-
172- if (_tooltip)
173- _tooltip->ShowWindow(false);
174- tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr));
175 }
176
177 bool LauncherIcon::OpenQuicklist(bool select_first_item, int monitor)
178
179=== modified file 'launcher/MockLauncherIcon.h'
180--- launcher/MockLauncherIcon.h 2012-11-28 22:00:12 +0000
181+++ launcher/MockLauncherIcon.h 2013-03-05 21:56:20 +0000
182@@ -68,6 +68,7 @@
183 , type_(type)
184 , sort_priority_(DefaultPriority(type))
185 , remote_uri_("fake")
186+ , is_tooltip_visible_(false)
187 {
188 tooltip_text = "Mock Icon";
189 position = Position::FLOATING;
190@@ -80,7 +81,9 @@
191
192 void AddProperties(GVariantBuilder* builder) {}
193
194- void HideTooltip() {}
195+ void ShowTooltip() { is_tooltip_visible_ = true; }
196+ void HideTooltip() { is_tooltip_visible_ = false; }
197+ bool IsTooltipVisible() { return is_tooltip_visible_; }
198
199 void SetShortcut(guint64 shortcut) {}
200
201@@ -366,6 +369,7 @@
202 timespec quirk_times_[unsigned(Quirk::LAST)];
203 std::map<int, nux::Point3> center_;
204 std::string remote_uri_;
205+ bool is_tooltip_visible_;
206 };
207
208 }
209
210=== added file 'launcher/TooltipManager.cpp'
211--- launcher/TooltipManager.cpp 1970-01-01 00:00:00 +0000
212+++ launcher/TooltipManager.cpp 2013-03-05 21:56:20 +0000
213@@ -0,0 +1,126 @@
214+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
215+/*
216+ * Copyright (C) 2013 Canonical Ltd
217+ *
218+ * This program is free software: you can redistribute it and/or modify
219+ * it under the terms of the GNU General Public License version 3 as
220+ * published by the Free Software Foundation.
221+ *
222+ * This program is distributed in the hope that it will be useful,
223+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
224+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
225+ * GNU General Public License for more details.
226+ *
227+ * You should have received a copy of the GNU General Public License
228+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
229+ *
230+ * Authored by: Jacob Edwards <j.johan.edwards@gmail.com>
231+ */
232+
233+#include "TooltipManager.h"
234+
235+namespace unity
236+{
237+namespace launcher
238+{
239+
240+namespace
241+{
242+const unsigned int TOOLTIPS_SHOW_TIMEOUT_LENGTH = 1000;
243+}
244+
245+TooltipManager::TooltipManager()
246+ : show_tooltips_(false)
247+ , hovered_(false)
248+ , timer_locked_(false)
249+{}
250+
251+void TooltipManager::SetIcon(AbstractLauncherIcon::Ptr const& newIcon)
252+{
253+ if (icon_ == newIcon)
254+ return;
255+
256+ // Unlock hover timer, in case the previous icon had no valid tooltip
257+ timer_locked_ = false;
258+
259+ if (show_tooltips_)
260+ {
261+ // Show new tooltip, get rid of the old olne
262+ if (icon_)
263+ icon_->HideTooltip();
264+ if (newIcon)
265+ newIcon->ShowTooltip();
266+ }
267+ else if (!newIcon)
268+ {
269+ // Stop the hover timer for null launcher space
270+ StopTimer();
271+ }
272+ else
273+ {
274+ AbstractLauncherIcon::IconType type = newIcon->GetIconType();
275+ if ((type == AbstractLauncherIcon::IconType::HOME ||
276+ type == AbstractLauncherIcon::IconType::HUD) &&
277+ newIcon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
278+ {
279+ // Lock the hover timer for no valid tooltip cases
280+ timer_locked_ = true;
281+ StopTimer();
282+ }
283+ }
284+
285+ icon_ = newIcon;
286+}
287+
288+void TooltipManager::SetHover(bool on_launcher)
289+{
290+ if (hovered_ == on_launcher)
291+ return;
292+ hovered_ = on_launcher;
293+
294+ if (show_tooltips_ && !hovered_)
295+ {
296+ show_tooltips_ = false;
297+ if (icon_)
298+ icon_->HideTooltip();
299+ }
300+}
301+
302+void TooltipManager::MouseMoved()
303+{
304+ if (!icon_ || show_tooltips_)
305+ return;
306+
307+ ResetTimer();
308+}
309+
310+void TooltipManager::IconClicked()
311+{
312+ StopTimer();
313+ if (show_tooltips_ && icon_)
314+ icon_->HideTooltip();
315+
316+ show_tooltips_ = false;
317+ timer_locked_ = true;
318+}
319+
320+void TooltipManager::ResetTimer()
321+{
322+ if (timer_locked_)
323+ return;
324+
325+ hover_timer_.reset(new glib::Timeout(TOOLTIPS_SHOW_TIMEOUT_LENGTH));
326+ hover_timer_->Run([&] () {
327+ show_tooltips_ = true;
328+ icon_->ShowTooltip();
329+ return false;
330+ });
331+}
332+
333+void TooltipManager::StopTimer()
334+{
335+ hover_timer_.reset();
336+}
337+
338+} // namespace launcher
339+} // namespace unity
340
341=== added file 'launcher/TooltipManager.h'
342--- launcher/TooltipManager.h 1970-01-01 00:00:00 +0000
343+++ launcher/TooltipManager.h 2013-03-05 21:56:20 +0000
344@@ -0,0 +1,57 @@
345+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
346+/*
347+ * Copyright (C) 2013 Canonical Ltd
348+ *
349+ * This program is free software: you can redistribute it and/or modify
350+ * it under the terms of the GNU General Public License version 3 as
351+ * published by the Free Software Foundation.
352+ *
353+ * This program is distributed in the hope that it will be useful,
354+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
355+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
356+ * GNU General Public License for more details.
357+ *
358+ * You should have received a copy of the GNU General Public License
359+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
360+ *
361+ * Authored by: Jacob Edwards <j.johan.edwards@gmail.com>
362+ */
363+
364+#ifndef TOOLTIPMANAGER
365+#define TOOLTIPMANAGER
366+
367+#include <boost/noncopyable.hpp>
368+#include <UnityCore/GLibSource.h>
369+
370+#include "AbstractLauncherIcon.h"
371+
372+namespace unity
373+{
374+namespace launcher
375+{
376+
377+class TooltipManager : public boost::noncopyable
378+{
379+public:
380+ TooltipManager();
381+
382+ void SetHover(bool on_launcher);
383+ void SetIcon(AbstractLauncherIcon::Ptr const& newIcon);
384+ void MouseMoved();
385+ void IconClicked();
386+
387+private:
388+ void ResetTimer();
389+ void StopTimer();
390+
391+ bool show_tooltips_;
392+ bool hovered_;
393+ AbstractLauncherIcon::Ptr icon_;
394+ glib::Source::UniquePtr hover_timer_;
395+ bool timer_locked_;
396+};
397+
398+} // namespace launcher
399+} // namespace unity
400+
401+#endif
402
403=== modified file 'tests/CMakeLists.txt'
404--- tests/CMakeLists.txt 2013-03-05 03:21:11 +0000
405+++ tests/CMakeLists.txt 2013-03-05 21:56:20 +0000
406@@ -250,6 +250,7 @@
407 test_texture_cache.cpp
408 test_text_input.cpp
409 test_thumbnail_generator.cpp
410+ test_tooltip_manager.cpp
411 test_trash_launcher_icon.cpp
412 test_launcher_minimize_speed.cpp
413 test_unity_settings.cpp
414
415=== added file 'tests/autopilot/unity/tests/launcher/test_tooltips.py'
416--- tests/autopilot/unity/tests/launcher/test_tooltips.py 1970-01-01 00:00:00 +0000
417+++ tests/autopilot/unity/tests/launcher/test_tooltips.py 2013-03-05 21:56:20 +0000
418@@ -0,0 +1,87 @@
419+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
420+# Copyright 2013 Canonical
421+# Authors: Jacob Edwards
422+#
423+# This program is free software: you can redistribute it and/or modify it
424+# under the terms of the GNU General Public License version 3, as published
425+# by the Free Software Foundation.
426+
427+from autopilot.matchers import Eventually
428+from testtools.matchers import Equals
429+from time import sleep
430+
431+from unity.tests.launcher import LauncherTestCase, _make_scenarios
432+
433+class LauncherTooltipTests(LauncherTestCase):
434+ """Tests whether tooltips display only at appropriate times."""
435+
436+ def setUp(self):
437+ super(LauncherTooltipTests, self).setUp()
438+ self.set_unity_option('launcher_hide_mode', 0)
439+ self.launcher_instance.move_mouse_to_right_of_launcher()
440+ self.icons = self.unity.launcher.model.get_launcher_icons(visible_only=True)
441+
442+ def test_launcher_tooltip_show(self):
443+ """Tests whether icon tooltips delay showing themselves and,
444+ once shown, whether subsequent icons show them instantly."""
445+ for i in self.icons:
446+ tooltip = i.get_tooltip()
447+ if not tooltip:
448+ continue
449+ self.assertThat(tooltip.active, Eventually(Equals(False)))
450+
451+ # only reveal tooltips after short wait
452+ self.assertEqual(self.get_reveal_behavior(self.icons[0]), self.DELAYED)
453+
454+ # subsequent tooltips reveal instantly, but hide on exit
455+ a, b = 0, 1
456+ while b < len(self.icons):
457+ self.mouse.move(self.icons[b].center_x, self.icons[b].center_y)
458+ self.assertTrue(self.icons[b].get_tooltip().active)
459+ self.assertFalse(self.icons[a].get_tooltip().active)
460+ a, b = a + 1, b + 1
461+ b -= 1
462+
463+ # leaving launcher clears tooltips, and instant reveal
464+ self.launcher_instance.move_mouse_to_right_of_launcher()
465+ self.assertEqual(self.get_reveal_behavior(self.icons[b]), self.DELAYED)
466+
467+ def test_launcher_tooltip_disabling(self):
468+ """Tests whether clicking on an icon hides its tooltip."""
469+ bfb, other = self.icons[0], self.icons[1]
470+ self.assertEqual(self.get_reveal_behavior(bfb), self.DELAYED)
471+
472+ # clicking icon hides its launcher until further input
473+ self.mouse.click()
474+ self.assertEqual(self.get_reveal_behavior(bfb), self.NEVER)
475+ self.mouse.click()
476+
477+ # normal behavior resumes on moving away from icon
478+ self.assertEqual(self.get_reveal_behavior(other), self.DELAYED)
479+ self.assertEqual(self.get_reveal_behavior(bfb), self.INSTANT)
480+
481+ def test_launcher_bfb_tooltip_when_open(self):
482+ """Tests whether hovering over the active BFB starts a tooltip timer"""
483+ self.unity.dash.ensure_visible()
484+ self.addCleanup(self.unity.dash.ensure_hidden)
485+ bfb, other = self.icons[0], self.icons[1]
486+
487+ # hovering an open dash's BFB does not show a tooltip ...
488+ self.assertEqual(self.get_reveal_behavior(bfb), self.NEVER)
489+
490+ # ... nor did it timeout instant tooltips for other icons
491+ self.assertEqual(self.get_reveal_behavior(other), self.DELAYED)
492+
493+ # Tooltip reveal types
494+ (INSTANT, DELAYED, NEVER) = range(3)
495+
496+ def get_reveal_behavior(self, icon):
497+ self.mouse.move(icon.center_x, icon.center_y)
498+ tooltip = icon.get_tooltip()
499+ if tooltip and tooltip.active:
500+ return self.INSTANT
501+ sleep(1.2)
502+ tooltip = icon.get_tooltip()
503+ if tooltip and tooltip.active:
504+ return self.DELAYED
505+ return self.NEVER
506
507=== added file 'tests/test_tooltip_manager.cpp'
508--- tests/test_tooltip_manager.cpp 1970-01-01 00:00:00 +0000
509+++ tests/test_tooltip_manager.cpp 2013-03-05 21:56:20 +0000
510@@ -0,0 +1,54 @@
511+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
512+/*
513+ * Copyright (C) 2013 Canonical Ltd
514+ *
515+ * This program is free software: you can redistribute it and/or modify
516+ * it under the terms of the GNU General Public License version 3 as
517+ * published by the Free Software Foundation.
518+ *
519+ * This program is distributed in the hope that it will be useful,
520+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
521+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
522+ * GNU General Public License for more details.
523+ *
524+ * You should have received a copy of the GNU General Public License
525+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
526+ *
527+ * Authored by: Jacob Edwards <j.johan.edwards@gmail.com>
528+ */
529+
530+#include <gtest/gtest.h>
531+using namespace testing;
532+
533+#include "launcher/TooltipManager.h"
534+#include "launcher/MockLauncherIcon.h"
535+#include "test_utils.h"
536+
537+namespace unity
538+{
539+namespace launcher
540+{
541+
542+namespace
543+{
544+
545+TEST(TestTooltipManager, TestHideAndShowTooltip)
546+{
547+ // Makes sure that TooltipManager calls icon->ShowTooltip() when the mouse
548+ // hovers it, and icon->HideTooltip() after the mouse dehovers it.
549+ TooltipManager tm;
550+ MockLauncherIcon* icon = new MockLauncherIcon();
551+
552+ tm.SetIcon(AbstractLauncherIcon::Ptr(icon));
553+ tm.MouseMoved();
554+ Utils::WaitForTimeoutMSec(1050);
555+
556+ EXPECT_TRUE(icon->IsTooltipVisible());
557+ tm.SetIcon(AbstractLauncherIcon::Ptr());
558+ EXPECT_FALSE(icon->IsTooltipVisible());
559+}
560+
561+}
562+
563+} // launcher
564+} // unity