Merge lp:~3v1n0/unity/spread-launcher-desaturate into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 3577
Proposed branch: lp:~3v1n0/unity/spread-launcher-desaturate
Merge into: lp:unity
Diff against target: 764 lines (+378/-74)
10 files modified
dash/DashController.h (+1/-1)
hud/HudController.h (+1/-1)
launcher/Launcher.cpp (+50/-9)
launcher/Launcher.h (+1/-0)
tests/autopilot/unity/tests/test_spread.py (+72/-2)
tests/mock-base-window.h (+8/-6)
tests/test_dash_controller.cpp (+21/-22)
tests/test_hud_controller.cpp (+29/-19)
tests/test_launcher.cpp (+194/-8)
tests/test_switcher_controller_class.cpp (+1/-6)
To merge this branch: bzr merge lp:~3v1n0/unity/spread-launcher-desaturate
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Brandon Schaefer (community) Approve
Review via email: mp+192066@code.launchpad.net

This proposal supersedes a proposal from 2013-10-11.

Commit message

Launcher: desaturate the inactive icons when in Spread mode

Description of the change

Desaturate the Launcher and hide tooltips when spread is initiated as designed.

Added unit and autopilot tests.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Christopher Townsend (townsend) wrote : Posted in a previous version of this proposal

Seems Jenkins CI is segfaulting:

[ RUN ] TestLauncher.DesaturateAllIconsOnSpread
Segmentation fault

I don't see that locally:(

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

LGTM

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Still looks good!

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dash/DashController.h'
2--- dash/DashController.h 2013-10-03 13:18:57 +0000
3+++ dash/DashController.h 2013-10-21 23:51:09 +0000
4@@ -41,7 +41,7 @@
5 namespace dash
6 {
7
8-class Controller : public unity::debug::Introspectable
9+class Controller : public unity::debug::Introspectable, public sigc::trackable
10 {
11 public:
12 typedef std::shared_ptr<Controller> Ptr;
13
14=== modified file 'hud/HudController.h'
15--- hud/HudController.h 2013-10-16 03:42:03 +0000
16+++ hud/HudController.h 2013-10-21 23:51:09 +0000
17@@ -40,7 +40,7 @@
18 namespace hud
19 {
20
21-class Controller : public unity::debug::Introspectable
22+class Controller : public unity::debug::Introspectable, public sigc::trackable
23 {
24 public:
25 typedef std::shared_ptr<Controller> Ptr;
26
27=== modified file 'launcher/Launcher.cpp'
28--- launcher/Launcher.cpp 2013-10-04 03:55:52 +0000
29+++ launcher/Launcher.cpp 2013-10-21 23:51:09 +0000
30@@ -94,6 +94,7 @@
31 const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";
32 const std::string SCROLL_TIMEOUT = "scroll-timeout";
33 const std::string ANIMATION_IDLE = "animation-idle";
34+const std::string SCALE_DESATURATE_IDLE = "scale-desaturate-idle";
35 const std::string URGENT_TIMEOUT = "urgent-timeout";
36 }
37
38@@ -173,9 +174,9 @@
39 ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
40
41 WindowManager& wm = WindowManager::Default();
42- wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
43+ wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnSpreadChanged));
44+ wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnSpreadChanged));
45 wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
46- wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
47 wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
48 wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::QueueDraw));
49
50@@ -1125,23 +1126,30 @@
51 }
52 }
53
54+// FIXME: add monitor-aware quirks!
55 void Launcher::DesaturateIcons()
56 {
57- for (auto icon : *model_)
58+ bool inactive_only = WindowManager::Default().IsScaleActiveForGroup();
59+
60+ for (auto const& icon : *model_)
61 {
62+ bool desaturate = false;
63+
64 if (icon->GetIconType () != AbstractLauncherIcon::IconType::HOME &&
65- icon->GetIconType () != AbstractLauncherIcon::IconType::HUD)
66+ icon->GetIconType () != AbstractLauncherIcon::IconType::HUD &&
67+ (!inactive_only || !icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE)))
68 {
69- icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
70+ desaturate = true;
71 }
72
73+ icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, desaturate);
74 icon->HideTooltip();
75 }
76 }
77
78 void Launcher::SaturateIcons()
79 {
80- for (auto icon : *model_)
81+ for (auto const& icon : *model_)
82 {
83 icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
84 }
85@@ -1243,7 +1251,7 @@
86
87 bool Launcher::IsOverlayOpen() const
88 {
89- return dash_is_open_ || hud_is_open_;
90+ return dash_is_open_ || hud_is_open_ || WindowManager::Default().IsScaleActive();
91 }
92
93 void Launcher::SetHidden(bool hide_launcher)
94@@ -1303,8 +1311,34 @@
95 void Launcher::OnPluginStateChanged()
96 {
97 WindowManager& wm = WindowManager::Default();
98- hide_machine_.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, wm.IsExpoActive());
99- hide_machine_.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, wm.IsScaleActive());
100+ bool expo_active = wm.IsExpoActive();
101+ hide_machine_.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, expo_active);
102+
103+ if (expo_active && icon_under_mouse_)
104+ icon_under_mouse_->HideTooltip();
105+}
106+
107+void Launcher::OnSpreadChanged()
108+{
109+ WindowManager& wm = WindowManager::Default();
110+ bool active = wm.IsScaleActive();
111+ hide_machine_.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, active);
112+
113+ bg_effect_helper_.enabled = active;
114+
115+ if (active && icon_under_mouse_)
116+ icon_under_mouse_->HideTooltip();
117+
118+ if (active && (!hovered_ || wm.IsScaleActiveForGroup()))
119+ {
120+ // The icons can take some ms to update their active state, this can protect us.
121+ sources_.AddIdle([this] { DesaturateIcons(); return false; }, SCALE_DESATURATE_IDLE);
122+ }
123+ else
124+ {
125+ sources_.Remove(SCALE_DESATURATE_IDLE);
126+ SaturateIcons();
127+ }
128 }
129
130 LauncherHideMode Launcher::GetHideMode() const
131@@ -2231,6 +2265,13 @@
132 if (!hidden_)
133 UpdateChangeInMousePosition(dx, dy);
134
135+ if (WindowManager::Default().IsScaleActiveForGroup())
136+ {
137+ auto icon = MouseIconIntersection(x, y);
138+ if (icon && !icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
139+ SaturateIcons();
140+ }
141+
142 // Every time the mouse moves, we check if it is inside an icon...
143 EventLogic();
144
145
146=== modified file 'launcher/Launcher.h'
147--- launcher/Launcher.h 2013-09-30 15:08:09 +0000
148+++ launcher/Launcher.h 2013-10-21 23:51:09 +0000
149@@ -200,6 +200,7 @@
150 #endif
151
152 void OnPluginStateChanged();
153+ void OnSpreadChanged();
154
155 void OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection);
156
157
158=== modified file 'tests/autopilot/unity/tests/test_spread.py'
159--- tests/autopilot/unity/tests/test_spread.py 2013-10-08 14:08:52 +0000
160+++ tests/autopilot/unity/tests/test_spread.py 2013-10-21 23:51:09 +0000
161@@ -8,9 +8,11 @@
162
163 from __future__ import absolute_import
164
165+from autopilot.display import Display
166 from autopilot.matchers import Eventually
167 from testtools.matchers import Equals, NotEquals
168 from time import sleep
169+from unity.emulators.icons import BFBLauncherIcon
170
171 from unity.tests import UnityTestCase
172
173@@ -18,6 +20,10 @@
174 class SpreadTests(UnityTestCase):
175 """Spread tests"""
176
177+ def setUp(self):
178+ super(SpreadTests, self).setUp()
179+ self.launcher = self.unity.launcher.get_launcher_for_monitor(self.display.get_primary_screen())
180+
181 def start_test_application_windows(self, app_name, num_windows=2):
182 """Start a given number of windows of the requested application"""
183 self.process_manager.close_all_app(app_name)
184@@ -44,10 +50,9 @@
185 """Initiate the Spread for windows of the given app"""
186 icon = self.unity.launcher.model.get_icon(desktop_id=desktop_id)
187 self.assertThat(icon, NotEquals(None))
188- launcher = self.unity.launcher.get_launcher_for_monitor(self.display.get_primary_screen())
189
190 self.addCleanup(self.unity.window_manager.terminate_spread)
191- launcher.click_launcher_icon(icon)
192+ self.launcher.click_launcher_icon(icon, move_mouse_after=False)
193 self.assertThat(self.unity.window_manager.scale_active_for_group, Eventually(Equals(True)))
194
195 def assertWindowIsNotScaled(self, window):
196@@ -60,6 +65,17 @@
197 refresh_fn = lambda: xid in [w.x_id for w in self.process_manager.get_open_windows()]
198 self.assertThat(refresh_fn, Eventually(Equals(False)))
199
200+ def assertLauncherIconsSaturated(self):
201+ for icon in self.unity.launcher.model.get_launcher_icons():
202+ self.assertThat(icon.desaturated, Eventually(Equals(False)))
203+
204+ def assertLauncherIconsDesaturated(self, also_active=True):
205+ for icon in self.unity.launcher.model.get_launcher_icons():
206+ if isinstance(icon, BFBLauncherIcon) or (not also_active and icon.active):
207+ self.assertThat(icon.desaturated, Eventually(Equals(False)))
208+ else:
209+ self.assertThat(icon.desaturated, Eventually(Equals(True)))
210+
211 def test_scale_application_windows(self):
212 """All the windows of an application must be scaled when application
213 spread is initiated
214@@ -120,3 +136,57 @@
215
216 self.assertWindowIsNotScaled(target_win)
217 self.assertWindowIsClosed(target_xid)
218+
219+ def test_spread_desaturate_launcher_icons(self):
220+ """Test that the screen spread desaturates the launcher icons"""
221+ self.start_test_application_windows("Calculator", 1)
222+ self.initiate_spread_for_screen()
223+ self.launcher.move_mouse_to_right_of_launcher()
224+ self.assertLauncherIconsDesaturated()
225+
226+ def test_spread_saturate_launcher_icons_on_mouse_over(self):
227+ """Test that the screen spread re-saturates the launcher icons on mouse over"""
228+ win = self.start_test_application_windows("Calculator", 2)[0]
229+ self.initiate_spread_for_application(win.application.desktop_file)
230+ self.launcher.move_mouse_over_launcher()
231+ self.assertLauncherIconsSaturated()
232+
233+ def test_app_spread_desaturate_inactive_launcher_icons(self):
234+ """Test that the app spread desaturates the inactive launcher icons"""
235+ win = self.start_test_application_windows("Calculator", 2)[0]
236+ self.initiate_spread_for_application(win.application.desktop_file)
237+ self.assertLauncherIconsDesaturated(also_active=False)
238+
239+ def test_app_spread_saturate_launcher_icons_on_mouse_move(self):
240+ """Test that the app spread re-saturates the launcher icons on mouse move"""
241+ win = self.start_test_application_windows("Calculator", 2)[0]
242+ self.initiate_spread_for_application(win.application.desktop_file)
243+ self.launcher.move_mouse_to_icon(self.unity.launcher.model.get_bfb_icon())
244+ self.assertLauncherIconsSaturated()
245+
246+ def test_app_spread_saturate_launcher_icons_on_mouse_over(self):
247+ """Test that the app spread re-saturates the launcher icons on mouse over"""
248+ win = self.start_test_application_windows("Calculator", 2)[0]
249+ self.initiate_spread_for_application(win.application.desktop_file)
250+ self.launcher.move_mouse_over_launcher()
251+ self.assertLauncherIconsSaturated()
252+
253+ def test_app_spread_desaturate_launcher_icons_switching_application(self):
254+ """Test that the app spread desaturates the launcher icons on mouse over"""
255+ cal_win = self.start_test_application_windows("Calculator", 2)[0]
256+ char_win = self.start_test_application_windows("Character Map", 2)[0]
257+ self.initiate_spread_for_application(char_win.application.desktop_file)
258+ self.initiate_spread_for_application(cal_win.application.desktop_file)
259+ self.assertLauncherIconsDesaturated(also_active=False)
260+
261+ def test_spread_hides_icon_tooltip(self):
262+ """Tests that the screen spread hides the active tooltip."""
263+ [win] = self.start_test_application_windows("Calculator", 1)
264+ icon = self.unity.launcher.model.get_icon(desktop_id=win.application.desktop_file)
265+ self.mouse.move(icon.center_x, icon.center_y)
266+
267+ self.assertThat(lambda: icon.get_tooltip(), Eventually(NotEquals(None)))
268+ self.assertThat(icon.get_tooltip().active, Eventually(Equals(True)))
269+
270+ self.initiate_spread_for_screen()
271+ self.assertThat(icon.get_tooltip().active, Eventually(Equals(False)))
272\ No newline at end of file
273
274=== modified file 'tests/mock-base-window.h'
275--- tests/mock-base-window.h 2013-02-07 16:55:11 +0000
276+++ tests/mock-base-window.h 2013-10-21 23:51:09 +0000
277@@ -16,6 +16,7 @@
278 #ifndef TESTS_MOCK_BASEWINDOW_H
279 #define TESTS_MOCK_BASEWINDOW_H
280
281+#include <gmock/gmock.h>
282 #include "ResizingBaseWindow.h"
283
284 namespace unity
285@@ -23,25 +24,26 @@
286 namespace testmocks
287 {
288
289+using namespace testing;
290+
291 class MockBaseWindow : public ResizingBaseWindow
292 {
293 public:
294 typedef nux::ObjectPtr<MockBaseWindow> Ptr;
295+ typedef NiceMock<MockBaseWindow> Nice;
296
297 MockBaseWindow(ResizingBaseWindow::GeometryAdjuster const& input_adjustment, const char *name = "Mock")
298 : ResizingBaseWindow(name, input_adjustment)
299- {}
300+ {
301+ ON_CALL(*this, SetOpacity(_)).WillByDefault(Invoke([this] (float o) { ResizingBaseWindow::SetOpacity(o); }));
302+ }
303
304 MockBaseWindow(const char *name = "Mock")
305- : ResizingBaseWindow(name, [](nux::Geometry const& geo) { return geo; })
306+ : MockBaseWindow([](nux::Geometry const& geo) { return geo; }, name)
307 {}
308
309 MOCK_METHOD2(ShowWindow, void(bool, bool));
310 MOCK_METHOD1(SetOpacity, void(float));
311-
312- // Really invoke the SetOpacity member function, a callthrough for use with
313- // ::testing::Invoke().
314- void RealSetOpacity(float opacity) { ResizingBaseWindow::SetOpacity(opacity); }
315 };
316
317 } // namespace testmocks
318
319=== modified file 'tests/test_dash_controller.cpp'
320--- tests/test_dash_controller.cpp 2013-02-07 16:56:07 +0000
321+++ tests/test_dash_controller.cpp 2013-10-21 23:51:09 +0000
322@@ -21,6 +21,7 @@
323 #include "unity-shared/DashStyle.h"
324 #include "unity-shared/PanelStyle.h"
325 #include "unity-shared/UnitySettings.h"
326+#include "unity-shared/WindowManager.h"
327 #include "test_utils.h"
328
329 #include <NuxCore/AnimationController.h>
330@@ -32,42 +33,32 @@
331 namespace
332 {
333
334-class TestDashController : public Test
335+struct TestDashController : Test
336 {
337-public:
338 TestDashController()
339 : animation_controller(tick_source)
340- , base_window_(new NiceMock<testmocks::MockBaseWindow>())
341- { }
342-
343- virtual void SetUp()
344- {
345- ON_CALL(*base_window_, SetOpacity(_))
346- .WillByDefault(Invoke(base_window_.GetPointer(),
347- &testmocks::MockBaseWindow::RealSetOpacity));
348-
349- // Set expectations for creating the controller
350- EXPECT_CALL(*base_window_, SetOpacity(0.0f))
351- .WillOnce(Invoke(base_window_.GetPointer(),
352- &testmocks::MockBaseWindow::RealSetOpacity));
353-
354- controller_.reset(new dash::Controller([&](){ return base_window_.GetPointer();}));
355- Mock::VerifyAndClearExpectations(base_window_.GetPointer());
356- }
357+ , base_window_(new testmocks::MockBaseWindow::Nice())
358+ , controller_(std::make_shared<dash::Controller>([this] { return base_window_.GetPointer(); }))
359+ {}
360
361 protected:
362 nux::animation::TickSource tick_source;
363 nux::animation::AnimationController animation_controller;
364
365- dash::Controller::Ptr controller_;
366- testmocks::MockBaseWindow::Ptr base_window_;
367-
368 // required to create hidden secret global variables
369 Settings unity_settings_;
370 dash::Style dash_style_;
371 panel::Style panel_style_;
372+
373+ testmocks::MockBaseWindow::Ptr base_window_;
374+ dash::Controller::Ptr controller_;
375 };
376
377+TEST_F(TestDashController, Construction)
378+{
379+ EXPECT_CALL(*base_window_, SetOpacity(0.0f));
380+ controller_ = std::make_shared<dash::Controller>([this] { return base_window_.GetPointer(); });
381+}
382
383 TEST_F(TestDashController, TestShowAndHideDash)
384 {
385@@ -100,5 +91,13 @@
386 EXPECT_EQ(base_window_->GetOpacity(), 0.0);
387 }
388
389+TEST_F(TestDashController, DisconnectWMSignalsOnDestruction)
390+{
391+ auto& signal = WindowManager::Default().initiate_spread;
392+ size_t before = signal.size();
393+ { auto controller = std::make_shared<dash::Controller>([this] { return base_window_.GetPointer(); }); }
394+ ASSERT_EQ(before, signal.size());
395+ signal.emit();
396 }
397
398+}
399
400=== modified file 'tests/test_hud_controller.cpp'
401--- tests/test_hud_controller.cpp 2013-02-19 15:07:36 +0000
402+++ tests/test_hud_controller.cpp 2013-10-21 23:51:09 +0000
403@@ -28,6 +28,7 @@
404 #include "unity-shared/DashStyle.h"
405 #include "unity-shared/PanelStyle.h"
406 #include "unity-shared/UnitySettings.h"
407+#include "unity-shared/WindowManager.h"
408 #include "test_utils.h"
409 using namespace unity;
410
411@@ -62,35 +63,32 @@
412 };
413
414
415-class TestHudController : public Test
416+struct TestHudController : Test
417 {
418-public:
419 TestHudController()
420- : view_(new NiceMock<MockHudView>)
421- , base_window_(new NiceMock<testmocks::MockBaseWindow>())
422- {
423- ON_CALL(*base_window_, SetOpacity(_))
424- .WillByDefault(Invoke(base_window_.GetPointer(),
425- &testmocks::MockBaseWindow::RealSetOpacity));
426-
427- // Set expectations for creating the controller
428- EXPECT_CALL(*base_window_, SetOpacity(0.0f));
429-
430- controller_.reset(new hud::Controller([&](){ return view_.GetPointer(); },
431- [&](){ return base_window_.GetPointer();}));
432- }
433+ : view_(new NiceMock<MockHudView>)
434+ , base_window_(new testmocks::MockBaseWindow::Nice())
435+ , controller_(std::make_shared<hud::Controller>([this] { return view_.GetPointer(); },
436+ [this] { return base_window_.GetPointer(); }))
437+ {}
438
439 protected:
440- hud::Controller::Ptr controller_;
441- MockHudView::Ptr view_;
442- testmocks::MockBaseWindow::Ptr base_window_;
443-
444 // required to create hidden secret global variables
445 Settings unity_settings_;
446 dash::Style dash_style_;
447 panel::Style panel_style_;
448+
449+ MockHudView::Ptr view_;
450+ testmocks::MockBaseWindow::Ptr base_window_;
451+ hud::Controller::Ptr controller_;
452 };
453
454+TEST_F(TestHudController, Construction)
455+{
456+ EXPECT_CALL(*base_window_, SetOpacity(0.0f));
457+ controller_ = std::make_shared<hud::Controller>([this] { return view_.GetPointer(); },
458+ [this] { return base_window_.GetPointer(); });
459+}
460
461 TEST_F(TestHudController, TestShowAndHideHud)
462 {
463@@ -141,4 +139,16 @@
464 EXPECT_EQ(base_window_->GetOpacity(), 0.0);
465 }
466
467+TEST_F(TestHudController, DisconnectWMSignalsOnDestruction)
468+{
469+ auto& signal = WindowManager::Default().initiate_spread;
470+ size_t before = signal.size();
471+ {
472+ auto controller = std::make_shared<hud::Controller>([this] { return view_.GetPointer(); },
473+ [this] { return base_window_.GetPointer(); });
474+ }
475+ ASSERT_EQ(before, signal.size());
476+ signal.emit();
477+}
478+
479 }
480
481=== modified file 'tests/test_launcher.cpp'
482--- tests/test_launcher.cpp 2013-10-04 00:19:56 +0000
483+++ tests/test_launcher.cpp 2013-10-21 23:51:09 +0000
484@@ -31,6 +31,7 @@
485 #include "unity-shared/PanelStyle.h"
486 #include "unity-shared/UnitySettings.h"
487 #include "unity-shared/IconRenderer.h"
488+#include "StandaloneWindowManager.h"
489 #include "test_utils.h"
490
491 namespace unity
492@@ -46,6 +47,7 @@
493 {
494 public:
495 typedef nux::ObjectPtr<MockMockLauncherIcon> Ptr;
496+ typedef testing::NiceMock<MockMockLauncherIcon> Nice;
497 MockMockLauncherIcon(IconType type = IconType::APPLICATION)
498 : MockLauncherIcon(type)
499 {}
500@@ -53,6 +55,7 @@
501 MOCK_METHOD1(ShouldHighlightOnDrag, bool(DndData const&));
502 MOCK_METHOD1(Stick, void(bool));
503 MOCK_METHOD2(PerformScroll, void(ScrollDirection, Time));
504+ MOCK_METHOD0(HideTooltip, void());
505 };
506
507 }
508@@ -115,6 +118,7 @@
509 using Launcher::SetHidden;
510 using Launcher::HandleUrgentIcon;
511 using Launcher::SetUrgentTimer;
512+ using Launcher::SetIconUnderMouse;
513 using Launcher::urgent_timer_running_;
514 using Launcher::urgent_finished_time_;
515 using Launcher::urgent_wiggle_time_;
516@@ -140,7 +144,8 @@
517 };
518
519 TestLauncher()
520- : parent_window_(new MockableBaseWindow("TestLauncherWindow"))
521+ : WM(dynamic_cast<StandaloneWindowManager*>(&WindowManager::Default()))
522+ , parent_window_(new MockableBaseWindow("TestLauncherWindow"))
523 , model_(new LauncherModel)
524 , options_(new Options)
525 , launcher_(new MockLauncher(parent_window_.GetPointer()))
526@@ -149,6 +154,15 @@
527 launcher_->SetModel(model_);
528 }
529
530+ ~TestLauncher()
531+ {
532+ WM->SetScaleActiveForGroup(false);
533+ WM->SetScaleActive(false);
534+
535+ if (WM->IsExpoActive())
536+ WM->TerminateExpo();
537+ }
538+
539 std::vector<MockMockLauncherIcon::Ptr> AddMockIcons(unsigned number)
540 {
541 std::vector<MockMockLauncherIcon::Ptr> icons;
542@@ -159,7 +173,7 @@
543
544 for (unsigned i = 0; i < number; ++i)
545 {
546- MockMockLauncherIcon::Ptr icon(new MockMockLauncherIcon);
547+ MockMockLauncherIcon::Ptr icon(new MockMockLauncherIcon::Nice);
548 icon->SetCenter(nux::Point3(launcher_geo.x + icon_size/2.0f, launcher_geo.y + icon_size/2.0f * (i+1) + 1, 0), monitor);
549
550 icons.push_back(icon);
551@@ -173,6 +187,7 @@
552 }
553
554 MockUScreen uscreen;
555+ StandaloneWindowManager* WM;
556 nux::ObjectPtr<MockableBaseWindow> parent_window_;
557 Settings settings;
558 panel::Style panel_style;
559@@ -688,9 +703,180 @@
560 launcher_->HandleUrgentIcon(icon, current);
561
562 EXPECT_THAT(launcher_->urgent_finished_time_.tv_sec, Gt(0));
563- EXPECT_THAT(launcher_->urgent_finished_time_.tv_nsec, Gt(0));
564-}
565-
566-}
567-}
568-
569+ EXPECT_THAT(launcher_->urgent_finished_time_.tv_nsec, Gt(0));
570+}
571+
572+TEST_F(TestLauncher, DesaturateAllIconsOnSpread)
573+{
574+ auto const& icons = AddMockIcons(5);
575+ icons[g_random_int()%icons.size()]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
576+
577+ WM->SetScaleActiveForGroup(false);
578+ WM->SetScaleActive(true);
579+ WM->initiate_spread.emit();
580+
581+ Utils::WaitUntilMSec([&icons] {
582+ for (auto const& icon : icons)
583+ {
584+ if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT))
585+ return false;
586+ }
587+ return true;
588+ });
589+
590+ for (auto const& icon : icons)
591+ ASSERT_TRUE(icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
592+}
593+
594+TEST_F(TestLauncher, SaturateAllIconsOnSpreadTerminated)
595+{
596+ auto const& icons = AddMockIcons(5);
597+ icons[g_random_int()%icons.size()]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
598+
599+ for (auto const& icon : icons)
600+ icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
601+
602+ WM->SetScaleActiveForGroup(false);
603+ WM->SetScaleActive(false);
604+ WM->terminate_spread.emit();
605+
606+ for (auto const& icon : icons)
607+ ASSERT_FALSE(icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
608+}
609+
610+TEST_F(TestLauncher, SaturatesAllIconsOnSpreadWithMouseOver)
611+{
612+ auto const& icons = AddMockIcons(5);
613+ icons[g_random_int()%icons.size()]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
614+
615+ for (auto const& icon : icons)
616+ icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
617+
618+ launcher_->SetHover(true);
619+ WM->SetScaleActiveForGroup(false);
620+ WM->SetScaleActive(true);
621+ WM->initiate_spread.emit();
622+
623+ Utils::WaitPendingEvents();
624+
625+ for (auto const& icon : icons)
626+ ASSERT_FALSE(icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
627+}
628+
629+TEST_F(TestLauncher, DesaturateInactiveIconsOnAppSpread)
630+{
631+ auto const& icons = AddMockIcons(5);
632+ icons[g_random_int()%icons.size()]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
633+
634+ WM->SetScaleActiveForGroup(true);
635+ WM->SetScaleActive(true);
636+ WM->initiate_spread.emit();
637+
638+ Utils::WaitUntilMSec([&icons] {
639+ for (auto const& icon : icons)
640+ {
641+ if (icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE) == icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT))
642+ return false;
643+ }
644+ return true;
645+ });
646+
647+ for (auto const& icon : icons)
648+ ASSERT_NE(icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE), icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
649+}
650+
651+TEST_F(TestLauncher, SaturatesAllIconsOnAppSpreadMouseMove)
652+{
653+ auto const& icons = AddMockIcons(5);
654+ unsigned active_idx = g_random_int()%icons.size();
655+ icons[active_idx]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
656+
657+ launcher_->SetHover(true);
658+ WM->SetScaleActiveForGroup(true);
659+ WM->SetScaleActive(true);
660+ WM->initiate_spread.emit();
661+
662+ Utils::WaitUntilMSec([&icons] {
663+ for (auto const& icon : icons)
664+ {
665+ if (icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE) == icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT))
666+ return false;
667+ }
668+ return true;
669+ });
670+
671+ for (auto const& icon : icons)
672+ ASSERT_NE(icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE), icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
673+
674+ auto const& active_center = icons[active_idx]->GetCenter(launcher_->monitor());
675+ launcher_->mouse_move.emit(active_center.x, active_center.y, 0, 0, 0, 0);
676+
677+ for (auto const& icon : icons)
678+ ASSERT_NE(icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE), icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
679+
680+ auto const& other_center = icons[(active_idx+1)%icons.size()]->GetCenter(launcher_->monitor());
681+ launcher_->mouse_move.emit(other_center.x, other_center.y, 0, 0, 0, 0);
682+
683+ for (auto const& icon : icons)
684+ ASSERT_FALSE(icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
685+
686+ launcher_->SetHover(false);
687+ for (auto const& icon : icons)
688+ ASSERT_NE(icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE), icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
689+
690+ launcher_->SetHover(true);
691+ for (auto const& icon : icons)
692+ ASSERT_FALSE(icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
693+}
694+
695+TEST_F(TestLauncher, DesaturateActiveIconOnAppSpreadIconUpdate)
696+{
697+ auto const& icons = AddMockIcons(5);
698+ unsigned active_idx = g_random_int()%icons.size();
699+ icons[active_idx]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
700+
701+ launcher_->SetHover(true);
702+ WM->SetScaleActiveForGroup(true);
703+ WM->SetScaleActive(true);
704+ WM->initiate_spread.emit();
705+
706+ Utils::WaitPendingEvents();
707+ for (auto const& icon : icons)
708+ ASSERT_NE(icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE), icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
709+
710+ unsigned new_active_idx = (active_idx+1)%icons.size();
711+ icons[active_idx]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, false);
712+ icons[new_active_idx]->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
713+
714+ WM->terminate_spread.emit();
715+ WM->initiate_spread.emit();
716+
717+ Utils::WaitPendingEvents();
718+ for (auto const& icon : icons)
719+ ASSERT_NE(icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE), icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT));
720+}
721+
722+TEST_F(TestLauncher, HideTooltipOnSpread)
723+{
724+ auto icon = AddMockIcons(1).front();
725+ EXPECT_CALL(*icon, HideTooltip());
726+
727+ launcher_->SetIconUnderMouse(icon);
728+ WM->SetScaleActive(true);
729+ WM->initiate_spread.emit();
730+}
731+
732+TEST_F(TestLauncher, HideTooltipOnExpo)
733+{
734+ auto icon = AddMockIcons(1).front();
735+ EXPECT_CALL(*icon, HideTooltip());
736+
737+ if (!WM->IsExpoActive())
738+ WM->InitiateExpo();
739+
740+ launcher_->SetIconUnderMouse(icon);
741+ WM->initiate_expo.emit();
742+}
743+
744+} // namespace launcher
745+} // namespace unity
746
747=== modified file 'tests/test_switcher_controller_class.cpp'
748--- tests/test_switcher_controller_class.cpp 2013-06-26 17:10:45 +0000
749+++ tests/test_switcher_controller_class.cpp 2013-10-21 23:51:09 +0000
750@@ -78,13 +78,8 @@
751 : WM(dynamic_cast<StandaloneWindowManager*>(&WindowManager::Default()))
752 , animation_controller_(tick_source_)
753 , mock_window_(new NiceMock<testmocks::MockBaseWindow>())
754+ , controller_(std::make_shared<Controller>([this] { return mock_window_; }))
755 {
756- ON_CALL(*mock_window_, SetOpacity(_))
757- .WillByDefault(Invoke(mock_window_.GetPointer(),
758- &testmocks::MockBaseWindow::RealSetOpacity));
759-
760- auto create_window = [this] { return mock_window_; };
761- controller_.reset(new Controller(create_window));
762 controller_->timeout_length = 0;
763
764 icons_.push_back(launcher::AbstractLauncherIcon::Ptr(new launcher::DesktopLauncherIcon()));