Merge lp:~3v1n0/unity/super-tab-switcher 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: 1834
Proposed branch: lp:~3v1n0/unity/super-tab-switcher
Merge into: lp:unity
Diff against target: 443 lines (+225/-54)
8 files modified
manual-tests/SuperTab.txt (+22/-0)
plugins/unityshell/src/Launcher.cpp (+133/-46)
plugins/unityshell/src/Launcher.h (+10/-1)
plugins/unityshell/src/UBusMessages.h (+2/-0)
plugins/unityshell/src/unity-root-accessible.cpp (+8/-3)
plugins/unityshell/src/unityshell.cpp (+36/-4)
plugins/unityshell/src/unityshell.h (+4/-0)
plugins/unityshell/unityshell.xml.in (+10/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/super-tab-switcher
Reviewer Review Type Date Requested Status
Mirco Müller (community) Needs Fixing
Review via email: mp+87851@code.launchpad.net

Description of the change

Fixed bug #891620 to support the Super+Tab switcher.

Added a new launcher key switcher that matches design bug #891620, the key bindings are set to default to Super+Tab and Super+Shift+Tab by default, but they can be changed from compiz settings.

I've added some new functions to Launcher to manage the KeySwitcher and others to share the code between the switcher and the key navigation.

To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote :

The patch works as described in the manual test. Code looks ok too. But again the wording of the manual-test can be improved...

1.) State that the launcher should be filled with enough sticky (bamf/launcher) icons so the icons collapse in the folding layout and they are forced to expand when in keyboard-navigation.

2.) Note the term "sticky" meaning stickyness within the scope of bamf/launcher and not window workspace-stickyness. That way testers are not confused when reading through and reproducing the manual tests.

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

Manual test fixed as requested, so: approving the branch for merging.

Revision history for this message
Unity Merger (unity-merger) wrote :

Attempt to merge into lp:unity failed due to conflicts:

text conflict in plugins/unityshell/src/unityshell.cpp

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'manual-tests/SuperTab.txt'
2--- manual-tests/SuperTab.txt 1970-01-01 00:00:00 +0000
3+++ manual-tests/SuperTab.txt 2012-01-14 13:17:25 +0000
4@@ -0,0 +1,22 @@
5+Super Tab Launcher Switcher
6+---------------------------
7+This test shows how the Super+Tab launcher switcher works
8+
9+#. Open some applications pinned to the launcher
10+#. Press Super+Tab
11+#. Release and Press again Tab some times
12+#. Press also the Shift key and press again Tab
13+#. Release all the keys
14+
15+Outcome:
16+ The first launcher item should be highlighted.
17+ Pressing Tab multiple times makes the next launcher icon to be highlighted.
18+ If clicking on the launcher while the Super+Tab switcher is active, the switcher
19+ should terminate and the standard click action should be done.
20+ When also the Shift modifier is pressed, pressing Tab highlights the previous
21+ icon.
22+ When releasing Super the highlighted launcher icon should be activated, and
23+ the default launcher icon action should be performed.
24+ If in the launcher there are many icons and they are shown as collapsed,
25+ when the Super+Tab is activated and the icons should be expanded when
26+ neeeded.
27
28=== modified file 'plugins/unityshell/src/Launcher.cpp'
29--- plugins/unityshell/src/Launcher.cpp 2012-01-07 17:15:49 +0000
30+++ plugins/unityshell/src/Launcher.cpp 2012-01-14 13:17:25 +0000
31@@ -247,6 +247,7 @@
32 _render_drag_window = false;
33 _drag_edge_touching = false;
34 _keynav_activated = false;
35+ _key_switcher_activated = false;
36 _backlight_mode = BACKLIGHT_NORMAL;
37 _last_button_press = 0;
38 _selection_atom = 0;
39@@ -1459,10 +1460,13 @@
40 {
41 Launcher* self = (Launcher*) data;
42
43- self->_shortcuts_shown = true;
44- self->_hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, true);
45+ if (!self->_key_switcher_activated)
46+ {
47+ self->_shortcuts_shown = true;
48+ self->_hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, true);
49
50- self->QueueDraw();
51+ self->QueueDraw();
52+ }
53
54 self->_super_show_shortcuts_handle = 0;
55 return false;
56@@ -1920,7 +1924,8 @@
57 Launcher* self = (Launcher*) data;
58 nux::Geometry geo = self->GetGeometry();
59
60- if (self->_keynav_activated || !self->_hovered || self->GetActionState() == ACTION_DRAG_LAUNCHER)
61+ if (self->_keynav_activated || self->_key_switcher_activated || !self->_hovered ||
62+ self->GetActionState() == ACTION_DRAG_LAUNCHER)
63 return TRUE;
64
65 if (self->MouseOverTopScrollArea())
66@@ -2597,6 +2602,122 @@
67 _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
68 }
69
70+void Launcher::SelectPreviousIcon()
71+{
72+ if (_current_icon_index > 0)
73+ {
74+ LauncherModel::iterator it;
75+ int temp_current_icon_index = _current_icon_index;
76+ do
77+ {
78+ temp_current_icon_index --;
79+ it = _model->at(temp_current_icon_index);
80+ }
81+ while (it != (LauncherModel::iterator)NULL && !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE));
82+
83+ if (it != (LauncherModel::iterator)NULL)
84+ {
85+ _current_icon_index = temp_current_icon_index;
86+
87+ if ((*it)->GetCenter().y + - _icon_size/ 2 < GetGeometry().y)
88+ _launcher_drag_delta += (_icon_size + _space_between_icons);
89+ }
90+ EnsureAnimation();
91+ selection_change.emit();
92+ }
93+}
94+
95+void Launcher::SelectNextIcon()
96+{
97+ if (_current_icon_index < _model->Size() - 1)
98+ {
99+ LauncherModel::iterator it;
100+ int temp_current_icon_index = _current_icon_index;
101+
102+ do
103+ {
104+ temp_current_icon_index ++;
105+ it = _model->at(temp_current_icon_index);
106+ }
107+ while (it != (LauncherModel::iterator)nullptr &&
108+ !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE));
109+
110+ if (it != (LauncherModel::iterator)nullptr)
111+ {
112+ _current_icon_index = temp_current_icon_index;
113+
114+ if ((*it)->GetCenter().y + _icon_size / 2 > GetGeometry().height)
115+ _launcher_drag_delta -= (_icon_size + _space_between_icons);
116+ }
117+
118+ EnsureAnimation();
119+ selection_change.emit();
120+ }
121+}
122+
123+void Launcher::KeySwitcherActivate()
124+{
125+ if (_key_switcher_activated)
126+ return;
127+
128+ _hide_machine->SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true);
129+ _hover_machine->SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true);
130+
131+ _key_switcher_activated = true;
132+
133+ ubus_server_send_message(ubus_server_get_default(),
134+ UBUS_LAUNCHER_START_KEY_SWTICHER,
135+ g_variant_new_boolean(true));
136+
137+ KeySwitcherNext();
138+}
139+
140+void Launcher::KeySwitcherTerminate()
141+{
142+ if (!_key_switcher_activated)
143+ return;
144+
145+ LauncherModel::iterator it = _model->at(_current_icon_index);
146+
147+ if (it != (LauncherModel::iterator)NULL)
148+ (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0));
149+
150+ _hide_machine->SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false);
151+ _hover_machine->SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false);
152+
153+ ubus_server_send_message(ubus_server_get_default(),
154+ UBUS_LAUNCHER_END_KEY_SWTICHER,
155+ g_variant_new_boolean(true));
156+
157+ _key_switcher_activated = false;
158+ _current_icon_index = -1;
159+ _last_icon_index = -1;
160+ QueueDraw();
161+
162+ selection_change.emit();
163+}
164+
165+bool Launcher::KeySwitcherIsActive()
166+{
167+ return _key_switcher_activated;
168+}
169+
170+void Launcher::KeySwitcherNext()
171+{
172+ if (!_key_switcher_activated)
173+ return;
174+
175+ SelectNextIcon();
176+}
177+
178+void Launcher::KeySwitcherPrevious()
179+{
180+ if (!_key_switcher_activated)
181+ return;
182+
183+ SelectPreviousIcon();
184+}
185+
186 void
187 Launcher::RecvKeyPressed(unsigned long eventType,
188 unsigned long key_sym,
189@@ -2619,53 +2740,13 @@
190 // up (move selection up or go to global-menu if at top-most icon)
191 case NUX_VK_UP:
192 case NUX_KP_UP:
193- if (_current_icon_index > 0)
194- {
195- int temp_current_icon_index = _current_icon_index;
196- do
197- {
198- temp_current_icon_index --;
199- it = _model->at(temp_current_icon_index);
200- }
201- while (it != (LauncherModel::iterator)NULL && !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE));
202-
203- if (it != (LauncherModel::iterator)NULL)
204- {
205- _current_icon_index = temp_current_icon_index;
206-
207- if ((*it)->GetCenter().y + - _icon_size/ 2 < GetGeometry().y)
208- _launcher_drag_delta += (_icon_size + _space_between_icons);
209- }
210- EnsureAnimation();
211- selection_change.emit();
212- }
213+ SelectPreviousIcon();
214 break;
215
216 // down (move selection down and unfold launcher if needed)
217 case NUX_VK_DOWN:
218 case NUX_KP_DOWN:
219- if (_current_icon_index < _model->Size() - 1)
220- {
221- int temp_current_icon_index = _current_icon_index;
222-
223- do
224- {
225- temp_current_icon_index ++;
226- it = _model->at(temp_current_icon_index);
227- }
228- while (it != (LauncherModel::iterator)NULL && !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE));
229-
230- if (it != (LauncherModel::iterator)NULL)
231- {
232- _current_icon_index = temp_current_icon_index;
233-
234- if ((*it)->GetCenter().y + _icon_size / 2 > GetGeometry().height)
235- _launcher_drag_delta -= (_icon_size + _space_between_icons);
236- }
237-
238- EnsureAnimation();
239- selection_change.emit();
240- }
241+ SelectNextIcon();
242 break;
243
244 // esc/left (close quicklist or exit laucher key-focus)
245@@ -2793,6 +2874,12 @@
246 _start_dragicon_handle = g_timeout_add(START_DRAGICON_DURATION, &Launcher::StartIconDragTimeout, this);
247
248 launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags));
249+
250+ if (_key_switcher_activated)
251+ {
252+ _current_icon_index = -1;
253+ KeySwitcherTerminate();
254+ }
255 }
256 }
257
258
259=== modified file 'plugins/unityshell/src/Launcher.h'
260--- plugins/unityshell/src/Launcher.h 2011-12-08 01:23:11 +0000
261+++ plugins/unityshell/src/Launcher.h 2012-01-14 13:17:25 +0000
262@@ -199,12 +199,20 @@
263 sigc::signal<void> selection_change;
264 sigc::signal<void> hidden_changed;
265
266-
267 // Key navigation
268 virtual bool InspectKeyEvent(unsigned int eventType,
269 unsigned int keysym,
270 const char* character);
271
272+ void SelectPreviousIcon();
273+ void SelectNextIcon();
274+
275+ void KeySwitcherActivate();
276+ void KeySwitcherTerminate();
277+ bool KeySwitcherIsActive();
278+ void KeySwitcherNext();
279+ void KeySwitcherPrevious();
280+
281 protected:
282 // Introspectable methods
283 std::string GetName() const;
284@@ -403,6 +411,7 @@
285
286 bool _shortcuts_shown;
287 bool _keynav_activated;
288+ bool _key_switcher_activated;
289 guint64 _latest_shortcut;
290
291 BacklightMode _backlight_mode;
292
293=== modified file 'plugins/unityshell/src/UBusMessages.h'
294--- plugins/unityshell/src/UBusMessages.h 2012-01-08 14:02:45 +0000
295+++ plugins/unityshell/src/UBusMessages.h 2012-01-14 13:17:25 +0000
296@@ -44,6 +44,8 @@
297 // get rid of keyboard-input-focus
298 #define UBUS_LAUNCHER_START_KEY_NAV "LAUNCHER_START_KEY_NAV"
299 #define UBUS_LAUNCHER_END_KEY_NAV "LAUNCHER_END_KEY_NAV"
300+#define UBUS_LAUNCHER_START_KEY_SWTICHER "LAUNCHER_START_KEY_SWITCHER"
301+#define UBUS_LAUNCHER_END_KEY_SWTICHER "LAUNCHER_END_KEY_SWITCHER"
302 #define UBUS_LAUNCHER_ICON_URGENT_CHANGED "LAUNCHER_ICON_URGENT_CHANGED"
303 #define UBUS_QUICKLIST_START_KEY_NAV "QUICKLIST_START_KEY_NAV"
304 #define UBUS_QUICKLIST_END_KEY_NAV "QUICKLIST_END_KEY_NAV"
305
306=== modified file 'plugins/unityshell/src/unity-root-accessible.cpp'
307--- plugins/unityshell/src/unity-root-accessible.cpp 2011-09-22 13:08:52 +0000
308+++ plugins/unityshell/src/unity-root-accessible.cpp 2012-01-14 13:17:25 +0000
309@@ -352,8 +352,8 @@
310 }
311
312 static void
313-ubus_launcher_start_key_nav_cb(GVariant* variant,
314- UnityRootAccessible* self)
315+ubus_launcher_register_interest_cb(GVariant* variant,
316+ UnityRootAccessible* self)
317 {
318 //launcher window is the same during all the life of Unity
319 if (self->priv->launcher_window == NULL)
320@@ -392,7 +392,12 @@
321 static unity::UBusManager ubus_manager;
322
323 ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_NAV,
324- sigc::bind(sigc::ptr_fun(ubus_launcher_start_key_nav_cb), self));
325+ sigc::bind(sigc::ptr_fun(ubus_launcher_register_interest_cb),
326+ self));
327+
328+ ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWTICHER,
329+ sigc::bind(sigc::ptr_fun(ubus_launcher_register_interest_cb),
330+ self));
331
332 nux::GetWindowCompositor().sigVisibleViewWindow.
333 connect(sigc::bind(sigc::ptr_fun(wc_change_visibility_window_cb), self, TRUE));
334
335=== modified file 'plugins/unityshell/src/unityshell.cpp'
336--- plugins/unityshell/src/unityshell.cpp 2012-01-13 15:35:44 +0000
337+++ plugins/unityshell/src/unityshell.cpp 2012-01-14 13:17:25 +0000
338@@ -287,8 +287,13 @@
339
340 optionSetAltTabPrevWindowInitiate(boost::bind(&UnityScreen::altTabPrevWindowInitiate, this, _1, _2, _3));
341
342- optionSetAltTabLeftInitiate (boost::bind (&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
343- optionSetAltTabRightInitiate (boost::bind (&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
344+ optionSetAltTabLeftInitiate(boost::bind (&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
345+ optionSetAltTabRightInitiate(boost::bind (&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
346+
347+ optionSetLauncherSwitcherForwardInitiate(boost::bind(&UnityScreen::launcherSwitcherForwardInitiate, this, _1, _2, _3));
348+ optionSetLauncherSwitcherPrevInitiate(boost::bind(&UnityScreen::launcherSwitcherPrevInitiate, this, _1, _2, _3));
349+ optionSetLauncherSwitcherForwardTerminate(boost::bind(&UnityScreen::launcherSwitcherTerminate, this, _1, _2, _3));
350+
351 optionSetShowMinimizedWindowsNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
352
353 for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); i++)
354@@ -1121,10 +1126,12 @@
355 // we should just say "key_string[1] = 0" because that is the only
356 // thing that could possibly make sense here.
357 key_string[result] = 0;
358- if (super_keypressed_) {
359+ if (super_keypressed_)
360+ {
361 shortcut_controller_->Hide();
362 skip_other_plugins = launcher.CheckSuperShortcutPressed(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string);
363- if (!skip_other_plugins) {
364+ if (!skip_other_plugins)
365+ {
366 skip_other_plugins = dash_controller_->CheckShortcutActivation(key_string);
367 if (skip_other_plugins)
368 launcher.SetLatestShortcut(key_string[0]);
369@@ -1273,6 +1280,7 @@
370 {
371 super_keypressed_ = false;
372 launcher_controller_->launcher().EndKeyShowLauncher();
373+ launcher_controller_->launcher().KeySwitcherTerminate();
374 shortcut_controller_->Hide();
375 return false;
376 }
377@@ -1530,6 +1538,30 @@
378 return false;
379 }
380
381+bool UnityScreen::launcherSwitcherForwardInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
382+{
383+ Launcher& launcher = launcher_controller_->launcher();
384+
385+ if (!launcher.KeySwitcherIsActive())
386+ launcher.KeySwitcherActivate();
387+ else
388+ launcher.KeySwitcherNext();
389+
390+ return false;
391+}
392+bool UnityScreen::launcherSwitcherPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
393+{
394+ launcher_controller_->launcher().KeySwitcherPrevious();
395+
396+ return false;
397+}
398+bool UnityScreen::launcherSwitcherTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
399+{
400+ launcher_controller_->launcher().KeySwitcherTerminate();
401+
402+ return false;
403+}
404+
405 void UnityScreen::OnLauncherStartKeyNav(GVariant* data, void* value)
406 {
407 UnityScreen* self = reinterpret_cast<UnityScreen*>(value);
408
409=== modified file 'plugins/unityshell/src/unityshell.h'
410--- plugins/unityshell/src/unityshell.h 2012-01-13 15:35:44 +0000
411+++ plugins/unityshell/src/unityshell.h 2012-01-14 13:17:25 +0000
412@@ -192,6 +192,10 @@
413 bool altTabNextWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
414 bool altTabPrevWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
415
416+ bool launcherSwitcherForwardInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
417+ bool launcherSwitcherPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
418+ bool launcherSwitcherTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options);
419+
420 /* handle option changes and change settings inside of the
421 * panel and dock views */
422 void optionChanged(CompOption*, Options num);
423
424=== modified file 'plugins/unityshell/unityshell.xml.in'
425--- plugins/unityshell/unityshell.xml.in 2011-12-19 22:18:53 +0000
426+++ plugins/unityshell/unityshell.xml.in 2012-01-14 13:17:25 +0000
427@@ -97,6 +97,16 @@
428 <_long>Open the first menu on the panel, allowing keyboard navigation thereafter.</_long>
429 <default>F10</default>
430 </option>
431+ <option name="launcher_switcher_forward" type="key">
432+ <_short>Key to start the launcher application switcher</_short>
433+ <_long>Switch the applications using the launcher</_long>
434+ <default>&lt;Super&gt;Tab</default>
435+ </option>
436+ <option name="launcher_switcher_prev" type="key">
437+ <_short>Key to start the launcher application switcher in reverse</_short>
438+ <_long>Switch the applications using the launcher, in reverse order</_long>
439+ <default>&lt;Super&gt;&lt;Shift&gt;Tab</default>
440+ </option>
441 </group>
442 <group>
443 <_short>Switcher</_short>