Merge lp:~3v1n0/unity/expo-terminate-fix into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 2777
Proposed branch: lp:~3v1n0/unity/expo-terminate-fix
Merge into: lp:unity
Diff against target: 649 lines (+253/-146)
8 files modified
launcher/ExpoLauncherIcon.cpp (+11/-1)
plugins/unityshell/src/unityshell.cpp (+34/-25)
tests/autopilot/unity/tests/launcher/test_icon_behavior.py (+50/-8)
unity-shared/PluginAdapter.h (+17/-13)
unity-shared/PluginAdapterCompiz.cpp (+96/-77)
unity-shared/PluginAdapterStandalone.cpp (+39/-22)
unity-shared/WindowManager.cpp (+5/-0)
unity-shared/WindowManager.h (+1/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/expo-terminate-fix
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Review via email: mp+127350@code.launchpad.net

Commit message

ExpoLauncherIcon: Correctly toggle the expo on activation

PluginAdapter: change the internals of MultiActionList to use a map to reference actions by name
WindowManager: add TerminateExpo function to hide the expo plugin

Description of the change

The expo is not always terminated by calling again PluginAdapter::InitiateExpo().
Made some refactoring to allow to define a PluginAdapter::TerminateExpo() function that calls the expo action to close the view.

Added new tests.

To post a comment you must log in.
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Looks good to me. Test pass, and works manually.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'launcher/ExpoLauncherIcon.cpp'
2--- launcher/ExpoLauncherIcon.cpp 2012-09-11 10:59:53 +0000
3+++ launcher/ExpoLauncherIcon.cpp 2012-10-01 19:11:21 +0000
4@@ -41,7 +41,17 @@
5 void ExpoLauncherIcon::ActivateLauncherIcon(ActionArg arg)
6 {
7 SimpleLauncherIcon::ActivateLauncherIcon(arg);
8- WindowManager::Default()->InitiateExpo();
9+
10+ auto wm = WindowManager::Default();
11+
12+ if (!wm->IsExpoActive())
13+ {
14+ wm->InitiateExpo();
15+ }
16+ else
17+ {
18+ wm->TerminateExpo();
19+ }
20 }
21
22 void ExpoLauncherIcon::Stick(bool save)
23
24=== modified file 'plugins/unityshell/src/unityshell.cpp'
25--- plugins/unityshell/src/unityshell.cpp 2012-10-01 14:43:57 +0000
26+++ plugins/unityshell/src/unityshell.cpp 2012-10-01 19:11:21 +0000
27@@ -2242,17 +2242,24 @@
28
29 if (p)
30 {
31- MultiActionList expoActions(0);
32+ MultiActionList expoActions;
33
34- foreach(CompOption & option, p->vTable->getOptions())
35+ for (CompOption& option : p->vTable->getOptions())
36 {
37- if (option.name() == "expo_key" ||
38- option.name() == "expo_button" ||
39- option.name() == "expo_edge")
40- {
41- CompAction* action = &option.value().action();
42- expoActions.AddNewAction(action, false);
43- break;
44+ std::string const& option_name = option.name();
45+
46+ if (!expoActions.HasPrimary() &&
47+ (option_name == "expo_key" ||
48+ option_name == "expo_button" ||
49+ option_name == "expo_edge"))
50+ {
51+ CompAction* action = &option.value().action();
52+ expoActions.AddNewAction(option_name, action, true);
53+ }
54+ else if (option_name == "exit_button")
55+ {
56+ CompAction* action = &option.value().action();
57+ expoActions.AddNewAction(option_name, action, false);
58 }
59 }
60
61@@ -2263,29 +2270,31 @@
62
63 if (p)
64 {
65- MultiActionList scaleActions(0);
66+ MultiActionList scaleActions;
67
68- foreach(CompOption & option, p->vTable->getOptions())
69+ for (CompOption& option : p->vTable->getOptions())
70 {
71- if (option.name() == "initiate_all_key" ||
72- option.name() == "initiate_all_edge" ||
73- option.name() == "initiate_key" ||
74- option.name() == "initiate_button" ||
75- option.name() == "initiate_edge" ||
76- option.name() == "initiate_group_key" ||
77- option.name() == "initiate_group_button" ||
78- option.name() == "initiate_group_edge" ||
79- option.name() == "initiate_output_key" ||
80- option.name() == "initiate_output_button" ||
81- option.name() == "initiate_output_edge")
82+ std::string const& option_name = option.name();
83+
84+ if (option_name == "initiate_all_key" ||
85+ option_name == "initiate_all_edge" ||
86+ option_name == "initiate_key" ||
87+ option_name == "initiate_button" ||
88+ option_name == "initiate_edge" ||
89+ option_name == "initiate_group_key" ||
90+ option_name == "initiate_group_button" ||
91+ option_name == "initiate_group_edge" ||
92+ option_name == "initiate_output_key" ||
93+ option_name == "initiate_output_button" ||
94+ option_name == "initiate_output_edge")
95 {
96 CompAction* action = &option.value().action();
97- scaleActions.AddNewAction(action, false);
98+ scaleActions.AddNewAction(option_name, action, false);
99 }
100- else if (option.name() == "initiate_all_button")
101+ else if (option_name == "initiate_all_button")
102 {
103 CompAction* action = &option.value().action();
104- scaleActions.AddNewAction(action, true);
105+ scaleActions.AddNewAction(option_name, action, true);
106 }
107 }
108
109
110=== modified file 'tests/autopilot/unity/tests/launcher/test_icon_behavior.py'
111--- tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2012-09-25 22:54:22 +0000
112+++ tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2012-10-01 19:11:21 +0000
113@@ -15,7 +15,7 @@
114 from testtools.matchers import Equals, NotEquals
115 from time import sleep
116
117-from unity.emulators.icons import BamfLauncherIcon
118+from unity.emulators.icons import BamfLauncherIcon, ExpoLauncherIcon
119 from unity.emulators.launcher import IconDragType
120 from unity.tests.launcher import LauncherTestCase, _make_scenarios
121
122@@ -29,6 +29,25 @@
123 super(LauncherIconsTests, self).setUp()
124 self.set_unity_option('launcher_hide_mode', 0)
125
126+ def ensure_expo_launcher_icon(self):
127+ EXPO_URI = "'unity://expo-icon'"
128+ old_fav = self.call_gsettings_cmd('get', 'com.canonical.Unity.Launcher', 'favorites')
129+
130+ if not EXPO_URI in old_fav:
131+ if old_fav[:-2] == "[]":
132+ new_fav = "["+EXPO_URI+"]"
133+ else:
134+ new_fav = old_fav[:-1]+", "+EXPO_URI+"]"
135+
136+ self.addCleanup(self.call_gsettings_cmd, 'set', 'com.canonical.Unity.Launcher', 'favorites', old_fav)
137+ self.call_gsettings_cmd('set', 'com.canonical.Unity.Launcher', 'favorites', new_fav)
138+
139+ icon = self.launcher.model.get_children_by_type(ExpoLauncherIcon)[0]
140+ self.assertThat(icon, NotEquals(None))
141+ self.assertThat(icon.visible, Eventually(Equals(True)))
142+
143+ return icon
144+
145 def test_bfb_tooltip_disappear_when_dash_is_opened(self):
146 """Tests that the bfb tooltip disappear when the dash is opened."""
147 bfb = self.launcher.model.get_bfb_icon()
148@@ -155,7 +174,11 @@
149 and show the quicklist.
150
151 """
152+ if self.workspace.num_workspaces <= 1:
153+ self.skipTest("This test requires enabled workspaces.")
154+
155 self.keybinding("expo/start")
156+ self.assertThat(self.window_manager.expo_active, Eventually(Equals(True)))
157 self.addCleanup(self.keybinding, "expo/cancel")
158
159 bfb = self.launcher.model.get_bfb_icon()
160@@ -163,13 +186,32 @@
161 self.mouse.click(button=3)
162
163 self.assertThat(self.launcher_instance.quicklist_open, Eventually(Equals(True)))
164-
165- monitor = self.screen_geo.get_primary_monitor()
166- self.panel = self.panels.get_panel_for_monitor(monitor)
167-
168- # When workspace switcher is opened the panel title is "Ubuntu Desktop" so we check
169- # to make sure that workspace switcher end.
170- self.assertThat(self.panels.get_active_panel().title, Eventually(NotEquals("Ubuntu Desktop")))
171+ self.assertThat(self.window_manager.expo_active, Eventually(Equals(False)))
172+
173+ def test_expo_launcher_icon_initiates_expo(self):
174+ """Clicking on the expo launcher icon must start the expo."""
175+ if self.workspace.num_workspaces <= 1:
176+ self.skipTest("This test requires enabled workspaces.")
177+
178+ expo = self.ensure_expo_launcher_icon()
179+ self.addCleanup(self.keybinding, "expo/cancel")
180+ self.launcher_instance.click_launcher_icon(expo)
181+
182+ self.assertThat(self.window_manager.expo_active, Eventually(Equals(True)))
183+
184+ def test_expo_launcher_icon_terminates_expo(self):
185+ """Clicking on the expo launcher icon when expo is active must close it."""
186+ if self.workspace.num_workspaces <= 1:
187+ self.skipTest("This test requires enabled workspaces.")
188+
189+ self.keybinding("expo/start")
190+ self.assertThat(self.window_manager.expo_active, Eventually(Equals(True)))
191+ self.addCleanup(self.keybinding, "expo/cancel")
192+
193+ expo = self.ensure_expo_launcher_icon()
194+ self.launcher_instance.click_launcher_icon(expo)
195+
196+ self.assertThat(self.window_manager.expo_active, Eventually(Equals(False)))
197
198
199 class LauncherDragIconsBehavior(LauncherTestCase):
200
201=== modified file 'unity-shared/PluginAdapter.h'
202--- unity-shared/PluginAdapter.h 2012-09-24 09:27:57 +0000
203+++ unity-shared/PluginAdapter.h 2012-10-01 19:11:21 +0000
204@@ -40,20 +40,23 @@
205 class MultiActionList
206 {
207 public:
208-
209- MultiActionList(int n) :
210- m_ActionList(n),
211- _primary_action(NULL) {};
212-
213- void InitiateAll(CompOption::Vector& extraArgs, int state);
214- void TerminateAll(CompOption::Vector& extraArgs);
215-
216- void AddNewAction(CompAction*, bool primary);
217- void RemoveAction(CompAction*);
218+ MultiActionList() :
219+ primary_action_(nullptr)
220+ {}
221+
222+ void Initiate(std::string const& name, CompOption::Vector const& extra_args = CompOption::Vector(), int state = 0) const;
223+ void InitiateAll(CompOption::Vector const& extra_args = CompOption::Vector(), int state = 0) const;
224+ void TerminateAll(CompOption::Vector const& extra_args = CompOption::Vector()) const;
225+
226+ void AddNewAction(std::string const& name, CompAction*, bool primary);
227+ void RemoveAction(std::string const& name);
228+ bool HasPrimary() const;
229+
230 private:
231+ CompAction* GetAction(std::string const& name) const;
232
233- std::list <CompAction*> m_ActionList;
234- CompAction* _primary_action;
235+ CompAction* primary_action_;
236+ std::map<std::string, CompAction*> actions_;
237 };
238
239
240@@ -96,6 +99,7 @@
241 bool IsScaleActiveForGroup() const;
242
243 void InitiateExpo();
244+ void TerminateExpo();
245 bool IsExpoActive() const;
246
247 bool IsWallActive() const;
248@@ -174,7 +178,7 @@
249 void AddProperties(GVariantBuilder* builder);
250
251 private:
252- std::string MatchStringForXids(std::vector<Window> *windows);
253+ std::string MatchStringForXids(std::vector<Window> const& windows);
254 void InitiateScale(std::string const& match, int state = 0);
255
256 bool CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) const;
257
258=== modified file 'unity-shared/PluginAdapterCompiz.cpp'
259--- unity-shared/PluginAdapterCompiz.cpp 2012-09-24 10:31:04 +0000
260+++ unity-shared/PluginAdapterCompiz.cpp 2012-10-01 19:11:21 +0000
261@@ -62,8 +62,6 @@
262
263 PluginAdapter::PluginAdapter(CompScreen* screen) :
264 m_Screen(screen),
265- m_ExpoActionList(0),
266- m_ScaleActionList(0),
267 _in_show_desktop (false),
268 _last_focused_window(nullptr)
269 {
270@@ -223,70 +221,103 @@
271 }
272
273 void
274-MultiActionList::AddNewAction(CompAction* a, bool primary)
275+MultiActionList::AddNewAction(std::string const& name, CompAction* a, bool primary)
276 {
277- if (std::find(m_ActionList.begin(), m_ActionList.end(), a) == m_ActionList.end())
278- m_ActionList.push_back(a);
279+ actions_[name] = a;
280
281 if (primary)
282- _primary_action = a;
283-}
284-
285-void
286-MultiActionList::RemoveAction(CompAction* a)
287-{
288- m_ActionList.remove(a);
289-}
290-
291-void
292-MultiActionList::InitiateAll(CompOption::Vector& extraArgs, int state)
293-{
294- CompOption::Vector argument;
295- if (m_ActionList.empty())
296- return;
297-
298- argument.resize(1);
299+ primary_action_ = a;
300+}
301+
302+void MultiActionList::RemoveAction(std::string const& name)
303+{
304+ actions_.erase(name);
305+}
306+
307+CompAction* MultiActionList::GetAction(std::string const& name) const
308+{
309+ auto it = actions_.find(name);
310+
311+ if (it == actions_.end())
312+ return nullptr;
313+
314+ return it->second;
315+}
316+
317+bool MultiActionList::HasPrimary() const
318+{
319+ return bool(primary_action_);
320+}
321+
322+void MultiActionList::Initiate(std::string const& name, CompOption::Vector const& extra_args, int state) const
323+{
324+ if (name.empty())
325+ return;
326+
327+ CompAction* action = GetAction(name);
328+
329+ if (!action)
330+ return;
331+
332+ CompOption::Vector argument(1);
333 argument[0].setName("root", CompOption::TypeInt);
334 argument[0].value().set((int) screen->root());
335- foreach(CompOption & arg, extraArgs)
336- {
337+
338+ for (CompOption const& arg : extra_args)
339 argument.push_back(arg);
340+
341+ /* Initiate the selected action with the arguments */
342+ action->initiate()(action, state, argument);
343+}
344+
345+void MultiActionList::InitiateAll(CompOption::Vector const& extra_args, int state) const
346+{
347+ if (actions_.empty())
348+ return;
349+
350+ std::string action_name;
351+
352+ if (primary_action_)
353+ {
354+ for (auto const& it : actions_)
355+ {
356+ if (it.second == primary_action_)
357+ {
358+ action_name = it.first;
359+ break;
360+ }
361+ }
362 }
363-
364- CompAction* a;
365-
366- if (_primary_action)
367- a = _primary_action;
368 else
369- a = m_ActionList.front();
370+ {
371+ action_name = actions_.begin()->first;
372+ }
373
374- /* Initiate the first available action with the arguments */
375- a->initiate()(a, state, argument);
376+ Initiate(action_name, extra_args, state);
377 }
378
379-void
380-MultiActionList::TerminateAll(CompOption::Vector& extraArgs)
381+void MultiActionList::TerminateAll(CompOption::Vector const& extra_args) const
382 {
383- CompOption::Vector argument;
384- CompOption::Value value;
385- if (m_ActionList.empty())
386+ if (actions_.empty())
387 return;
388
389- argument.resize(1);
390+ CompOption::Vector argument(1);
391 argument[0].setName("root", CompOption::TypeInt);
392 argument[0].value().set((int) screen->root());
393
394- foreach(CompOption & a, extraArgs)
395- argument.push_back(a);
396+ for (CompOption const& a : extra_args)
397+ argument.push_back(a);
398
399- if (_primary_action)
400+ if (primary_action_)
401 {
402- _primary_action->terminate()(_primary_action, 0, argument);
403+ primary_action_->terminate()(primary_action_, 0, argument);
404 return;
405 }
406
407- foreach(CompAction * action, m_ActionList)
408+ for (auto const& it : actions_)
409 {
410+ CompAction* action = it.second;
411+
412 if (action->state() & (CompAction::StateTermKey |
413 CompAction::StateTermButton |
414 CompAction::StateTermEdge |
415@@ -331,31 +362,24 @@
416 }
417
418 std::string
419-PluginAdapter::MatchStringForXids(std::vector<Window> *windows)
420+PluginAdapter::MatchStringForXids(std::vector<Window> const& windows)
421 {
422- std::ostringstream sout;
423-
424- sout << "any & (";
425-
426- std::vector<Window>::iterator it;
427- for (it = windows->begin(); it != windows->end(); ++it)
428- {
429- sout << "| xid=" << static_cast<int>(*it) << " ";
430- }
431- sout << ")";
432-
433- return sout.str();
434+ std::string out_string = "any & (";
435+
436+ for (auto const& xid : windows)
437+ out_string += "| xid=" + std::to_string(xid) + " ";
438+
439+ out_string += ")";
440+
441+ return out_string;
442 }
443
444 void
445 PluginAdapter::InitiateScale(std::string const& match, int state)
446 {
447- CompOption::Vector argument;
448- CompMatch m(match);
449-
450- argument.resize(1);
451+ CompOption::Vector argument(1);
452 argument[0].setName("match", CompOption::TypeMatch);
453- argument[0].value().set(m);
454+ argument[0].value().set(CompMatch(match));
455
456 m_ScaleActionList.InitiateAll(argument, state);
457 }
458@@ -363,8 +387,7 @@
459 void
460 PluginAdapter::TerminateScale()
461 {
462- CompOption::Vector argument(0);
463- m_ScaleActionList.TerminateAll(argument);
464+ m_ScaleActionList.TerminateAll();
465 }
466
467 bool
468@@ -391,12 +414,14 @@
469 return m_Screen->grabExist("wall");
470 }
471
472-void
473-PluginAdapter::InitiateExpo()
474+void PluginAdapter::InitiateExpo()
475 {
476- CompOption::Vector argument(0);
477+ m_ExpoActionList.InitiateAll();
478+}
479
480- m_ExpoActionList.InitiateAll(argument, 0);
481+void PluginAdapter::TerminateExpo()
482+{
483+ m_ExpoActionList.Initiate("exit_button");
484 }
485
486 // WindowManager implementation
487@@ -819,7 +844,7 @@
488 std::size_t num_windows = windows.size();
489 if (num_windows > 1 || (force && num_windows))
490 {
491- std::string match = MatchStringForXids(&windows);
492+ std::string const& match = MatchStringForXids(windows);
493 InitiateScale(match, state);
494 _spread_windows_state = true;
495 return true;
496@@ -1189,9 +1214,7 @@
497 if (!_grab_show_action || !window)
498 return;
499
500- CompOption::Vector argument;
501-
502- argument.resize(3);
503+ CompOption::Vector argument(3);
504 argument[0].setName("root", CompOption::TypeInt);
505 argument[0].value().set((int) screen->root());
506 argument[1].setName("window", CompOption::TypeInt);
507@@ -1209,9 +1232,7 @@
508 if (!_grab_hide_action || !window)
509 return;
510
511- CompOption::Vector argument;
512-
513- argument.resize(2);
514+ CompOption::Vector argument(2);
515 argument[0].setName("root", CompOption::TypeInt);
516 argument[0].value().set((int) screen->root());
517 argument[1].setName("window", CompOption::TypeInt);
518@@ -1227,9 +1248,7 @@
519 if (!_grab_toggle_action || !window)
520 return;
521
522- CompOption::Vector argument;
523-
524- argument.resize(2);
525+ CompOption::Vector argument(2);
526 argument[0].setName("root", CompOption::TypeInt);
527 argument[0].value().set((int) screen->root());
528 argument[1].setName("window", CompOption::TypeInt);
529
530=== modified file 'unity-shared/PluginAdapterStandalone.cpp'
531--- unity-shared/PluginAdapterStandalone.cpp 2012-09-10 22:44:29 +0000
532+++ unity-shared/PluginAdapterStandalone.cpp 2012-10-01 19:11:21 +0000
533@@ -52,8 +52,6 @@
534
535 PluginAdapter::PluginAdapter(CompScreen* screen)
536 : m_Screen(screen)
537- , m_ExpoActionList(0)
538- , m_ScaleActionList(0)
539 , _expo_state(false)
540 , _in_show_desktop(false)
541 , _last_focused_window(nullptr)
542@@ -106,24 +104,37 @@
543 }
544
545 void
546-MultiActionList::AddNewAction(CompAction* a, bool primary)
547-{
548-}
549-
550-void
551-MultiActionList::RemoveAction(CompAction* a)
552-{
553-}
554-
555-void
556-MultiActionList::InitiateAll(CompOption::Vector& extraArgs, int state)
557-{
558-}
559-
560-void
561-MultiActionList::TerminateAll(CompOption::Vector& extraArgs)
562-{
563-}
564+MultiActionList::AddNewAction(std::string const& n, CompAction* a, bool primary)
565+{
566+}
567+
568+void
569+MultiActionList::RemoveAction(std::string const& n)
570+{
571+}
572+
573+void
574+MultiActionList::InitiateAll(CompOption::Vector const& extraArgs, int state) const
575+{
576+}
577+
578+void
579+MultiActionList::TerminateAll(CompOption::Vector const& extraArgs) const
580+{
581+}
582+
583+bool
584+MultiActionList::HasPrimary() const
585+{
586+ return false;
587+}
588+
589+CompAction*
590+MultiActionList::GetAction(std::string const& name) const
591+{
592+ return nullptr;
593+}
594+
595
596 unsigned long long
597 PluginAdapter::GetWindowActiveNumber (guint32 xid) const
598@@ -142,7 +153,7 @@
599 }
600
601 std::string
602-PluginAdapter::MatchStringForXids(std::vector<Window> *windows)
603+PluginAdapter::MatchStringForXids(std::vector<Window> const& windows)
604 {
605 return "";
606 }
607@@ -178,7 +189,13 @@
608 void
609 PluginAdapter::InitiateExpo()
610 {
611- _expo_state = !_expo_state;
612+ _expo_state = true;
613+}
614+
615+void
616+PluginAdapter::TerminateExpo()
617+{
618+ _expo_state = false;
619 }
620
621 bool
622
623=== modified file 'unity-shared/WindowManager.cpp'
624--- unity-shared/WindowManager.cpp 2012-09-10 22:44:29 +0000
625+++ unity-shared/WindowManager.cpp 2012-10-01 19:11:21 +0000
626@@ -214,6 +214,11 @@
627 g_debug("%s", G_STRFUNC);
628 }
629
630+ void TerminateExpo()
631+ {
632+ g_debug("%s", G_STRFUNC);
633+ }
634+
635 bool IsExpoActive() const
636 {
637 g_debug("%s", G_STRFUNC);
638
639=== modified file 'unity-shared/WindowManager.h'
640--- unity-shared/WindowManager.h 2012-09-10 22:44:29 +0000
641+++ unity-shared/WindowManager.h 2012-10-01 19:11:21 +0000
642@@ -79,6 +79,7 @@
643 virtual bool IsScaleActiveForGroup() const = 0;
644
645 virtual void InitiateExpo() = 0;
646+ virtual void TerminateExpo() = 0;
647 virtual bool IsExpoActive() const = 0;
648
649 virtual bool IsWallActive() const = 0;