Merge lp:~3v1n0/unity/icon-activation-overlay-focus-fix 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: 3552
Proposed branch: lp:~3v1n0/unity/icon-activation-overlay-focus-fix
Merge into: lp:unity
Diff against target: 358 lines (+79/-57)
9 files modified
dash/DashController.cpp (+8/-20)
dash/DashController.h (+2/-2)
dash/DashView.cpp (+1/-1)
hud/HudController.cpp (+12/-28)
hud/HudController.h (+1/-1)
launcher/SimpleLauncherIcon.cpp (+1/-1)
plugins/unityshell/src/unityshell.cpp (+2/-2)
tests/autopilot/unity/tests/launcher/test_icon_behavior.py (+32/-2)
tests/test_application_launcher_icon.cpp (+20/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/icon-activation-overlay-focus-fix
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+189080@code.launchpad.net

Commit message

SimpleLauncherIcon: we need to restore the focus when closing the Overlay for activation

Description of the change

Always make the Dash/Hud restore the input focus when hidden, also don't
save it when showing it, giving the focus back to the default window
is just enough.

This fixes a focus issue we had when clicking on a launcher icon when
an overlay was opened.

Added both unit and AP tests.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dash/DashController.cpp'
2--- dash/DashController.cpp 2013-09-19 00:03:28 +0000
3+++ dash/DashController.cpp 2013-10-03 13:43:44 +0000
4@@ -105,8 +105,7 @@
5 }
6 });
7
8- auto spread_cb = sigc::bind(sigc::mem_fun(this, &Controller::HideDash), true);
9- WindowManager::Default().initiate_spread.connect(spread_cb);
10+ WindowManager::Default().initiate_spread.connect(sigc::mem_fun(this, &Controller::HideDash));
11
12 dbus_server_.AddObjects(dbus::INTROSPECTION, dbus::PATH);
13 dbus_server_.GetObjects().front()->SetMethodsCallsHandler([this] (std::string const& method, GVariant*) {
14@@ -174,7 +173,7 @@
15 // hide if something else is coming up
16 if (overlay_identity.Str() != "dash")
17 {
18- HideDash(true);
19+ HideDash();
20 }
21 });
22
23@@ -276,16 +275,7 @@
24
25 void Controller::OnExternalHideDash(GVariant* variant)
26 {
27- EnsureDash();
28-
29- if (variant)
30- {
31- HideDash(g_variant_get_boolean(variant));
32- }
33- else
34- {
35- HideDash();
36- }
37+ HideDash();
38 }
39
40 void Controller::ShowDash()
41@@ -340,14 +330,14 @@
42 nux::GetWindowCompositor().SetKeyFocusArea(view_->default_focus());
43 }
44
45-void Controller::QuicklyHideDash(bool restore)
46+void Controller::QuicklyHideDash()
47 {
48- HideDash(restore);
49+ HideDash();
50 timeline_animator_.Stop();
51 window_->ShowWindow(false);
52 }
53
54-void Controller::HideDash(bool restore)
55+void Controller::HideDash()
56 {
57 if (!visible_)
58 return;
59@@ -362,10 +352,8 @@
60 window_->EnableInputWindow(false, dash::window_title, true, false);
61 visible_ = false;
62
63- nux::GetWindowCompositor().SetKeyFocusArea(NULL,nux::KEY_NAV_NONE);
64-
65- if (restore)
66- WindowManager::Default().RestoreInputFocus();
67+ nux::GetWindowCompositor().SetKeyFocusArea(NULL, nux::KEY_NAV_NONE);
68+ WindowManager::Default().RestoreInputFocus();
69
70 StartShowHideTimeline();
71
72
73=== modified file 'dash/DashController.h'
74--- dash/DashController.h 2013-09-16 17:40:56 +0000
75+++ dash/DashController.h 2013-10-03 13:43:44 +0000
76@@ -59,8 +59,8 @@
77
78 sigc::signal<void> on_realize;
79
80- void HideDash(bool restore_focus = true);
81- void QuicklyHideDash(bool restore_focus = true);
82+ void HideDash();
83+ void QuicklyHideDash();
84 void ShowDash();
85
86 void ReFocusKeyInput();
87
88=== modified file 'dash/DashView.cpp'
89--- dash/DashView.cpp 2013-09-24 20:18:42 +0000
90+++ dash/DashView.cpp 2013-10-03 13:43:44 +0000
91@@ -1401,7 +1401,7 @@
92 {
93 if (preview_displaying_)
94 ClosePreview();
95- else if (search_bar_->search_string != "")
96+ else if (!search_bar_->search_string().empty())
97 search_bar_->search_string = "";
98 else
99 ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
100
101=== modified file 'hud/HudController.cpp'
102--- hud/HudController.cpp 2013-09-13 01:36:20 +0000
103+++ hud/HudController.cpp 2013-10-03 13:43:44 +0000
104@@ -65,7 +65,7 @@
105 // As a default. the create_window_ function should just create a base window.
106 if (create_window_ == nullptr)
107 {
108- create_window_ = [&]() {
109+ create_window_ = [this]() {
110 return new ResizingBaseWindow("Hud",
111 [this](nux::Geometry const& geo) {
112 if (view_)
113@@ -76,14 +76,14 @@
114 }
115
116 SetupWindow();
117- UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(true); });
118+ UScreen::GetDefault()->changed.connect([this] (int, std::vector<nux::Geometry>&) { Relayout(true); });
119
120 ubus.RegisterInterest(UBUS_HUD_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));
121
122 //!!FIXME!! - just hijacks the dash close request so we get some more requests than normal,
123 ubus.RegisterInterest(UBUS_OVERLAY_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));
124
125- ubus.RegisterInterest(UBUS_OVERLAY_SHOWN, [&] (GVariant *data) {
126+ ubus.RegisterInterest(UBUS_OVERLAY_SHOWN, [this] (GVariant *data) {
127 unity::glib::String overlay_identity;
128 gboolean can_maximise = FALSE;
129 gint32 overlay_monitor = 0;
130@@ -92,15 +92,15 @@
131
132 if (overlay_identity.Str() != "hud")
133 {
134- HideHud(true);
135+ HideHud();
136 }
137 });
138
139- launcher_width.changed.connect([&] (int new_width) { Relayout(); });
140+ launcher_width.changed.connect([this] (int) { Relayout(); });
141
142 WindowManager& wm = WindowManager::Default();
143 wm.screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
144- wm.initiate_spread.connect(sigc::bind(sigc::mem_fun(this, &Controller::HideHud), true));
145+ wm.initiate_spread.connect(sigc::mem_fun(this, &Controller::HideHud));
146
147 hud_service_.queries_updated.connect(sigc::mem_fun(this, &Controller::OnQueriesFinished));
148 timeline_animator_.updated.connect(sigc::mem_fun(this, &Controller::OnViewShowHideFrame));
149@@ -289,22 +289,13 @@
150 void Controller::OnExternalHideHud(GVariant* variant)
151 {
152 LOG_DEBUG(logger) << "External Hiding the hud";
153- EnsureHud();
154-
155- if (variant)
156- {
157- HideHud(g_variant_get_boolean(variant));
158- }
159- else
160- {
161- HideHud();
162- }
163+ HideHud();
164 }
165
166 void Controller::ShowHideHud()
167 {
168 EnsureHud();
169- visible_ ? HideHud(true) : ShowHud();
170+ visible_ ? HideHud() : ShowHud();
171 }
172
173 void Controller::ReFocusKeyInput()
174@@ -364,8 +355,6 @@
175
176 LOG_DEBUG(logger) << "Taking application icon: " << focused_app_icon_;
177 SetIcon(focused_app_icon_);
178-
179- WindowManager::Default().SaveInputFocus();
180 FocusWindow();
181
182 view_->ResetToDefault();
183@@ -402,10 +391,10 @@
184 window_->QueueDraw();
185 }
186
187-void Controller::HideHud(bool restore)
188+void Controller::HideHud()
189 {
190 LOG_DEBUG (logger) << "hiding the hud";
191- if (visible_ == false)
192+ if (!visible_)
193 return;
194
195 need_show_ = false;
196@@ -415,14 +404,9 @@
197 window_->EnableInputWindow(false, "Hud", true, false);
198 visible_ = false;
199
200- nux::GetWindowCompositor().SetKeyFocusArea(NULL,nux::KEY_NAV_NONE);
201-
202+ WindowManager::Default().RestoreInputFocus();
203+ nux::GetWindowCompositor().SetKeyFocusArea(NULL, nux::KEY_NAV_NONE);
204 StartShowHideTimeline();
205-
206- restore = true;
207- if (restore)
208- WindowManager::Default().RestoreInputFocus();
209-
210 hud_service_.CloseQuery();
211
212 //unhide the launcher
213
214=== modified file 'hud/HudController.h'
215--- hud/HudController.h 2012-12-13 03:17:19 +0000
216+++ hud/HudController.h 2013-10-03 13:43:44 +0000
217@@ -60,7 +60,7 @@
218
219 void ShowHideHud();
220 void ShowHud();
221- void HideHud(bool restore_focus = true);
222+ void HideHud();
223 void ReFocusKeyInput();
224 bool IsVisible();
225
226
227=== modified file 'launcher/SimpleLauncherIcon.cpp'
228--- launcher/SimpleLauncherIcon.cpp 2013-07-29 16:35:54 +0000
229+++ launcher/SimpleLauncherIcon.cpp 2013-10-03 13:43:44 +0000
230@@ -49,7 +49,7 @@
231
232 void SimpleLauncherIcon::ActivateLauncherIcon(ActionArg arg)
233 {
234- UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST, g_variant_new_boolean(FALSE));
235+ UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
236 }
237
238 nux::BaseTexture* SimpleLauncherIcon::GetTextureForSize(int size)
239
240=== modified file 'plugins/unityshell/src/unityshell.cpp'
241--- plugins/unityshell/src/unityshell.cpp 2013-10-01 02:17:09 +0000
242+++ plugins/unityshell/src/unityshell.cpp 2013-10-03 13:43:44 +0000
243@@ -1514,7 +1514,7 @@
244 }
245 else
246 {
247- dash_controller_->HideDash(false);
248+ dash_controller_->HideDash();
249 }
250 }
251 }
252@@ -1529,7 +1529,7 @@
253
254 if (!hud_geo.IsInside(pt) && !DoesPointIntersectUnityGeos(pt) && !on_top_geo.IsInside(pt))
255 {
256- hud_controller_->HideHud(false);
257+ hud_controller_->HideHud();
258 }
259 }
260 else if (switcher_controller_->Visible())
261
262=== modified file 'tests/autopilot/unity/tests/launcher/test_icon_behavior.py'
263--- tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2013-05-02 15:51:41 +0000
264+++ tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2013-10-03 13:43:44 +0000
265@@ -90,11 +90,10 @@
266 """Shift+Clicking MUST open a new instance of an already-running application."""
267 app = self.process_manager.start_app("Calculator")
268 icon = self.unity.launcher.model.get_icon(desktop_id=app.desktop_file)
269- launcher_instance = self.unity.launcher.get_launcher_for_monitor(0)
270
271 self.keyboard.press("Shift")
272 self.addCleanup(self.keyboard.release, "Shift")
273- launcher_instance.click_launcher_icon(icon)
274+ self.launcher_instance.click_launcher_icon(icon)
275
276 self.assertNumberWinsIsEventually(app, 2)
277
278@@ -326,6 +325,37 @@
279 self.launcher_instance.click_launcher_icon(icon)
280 self.assertThat(lambda: window.x_win.get_wm_state()['state'], Eventually(Equals(Xutil.NormalState)))
281
282+ def test_icon_focuses_application_window_when_dash_is_open(self):
283+ """Clicking on an icon when dash is shown must focus it."""
284+ win = self.process_manager.start_app_window("Calculator")
285+ self.assertThat(lambda: win.is_focused, Eventually(Equals(True)))
286+
287+ self.addCleanup(self.unity.dash.ensure_hidden)
288+ self.unity.dash.ensure_visible()
289+ self.assertThat(lambda: win.is_focused, Eventually(Equals(False)))
290+
291+ icon = self.unity.launcher.model.get_icon(desktop_id=win.application.desktop_file)
292+ self.launcher_instance.click_launcher_icon(icon)
293+
294+ self.assertThat(self.unity.dash.visible, Eventually(Equals(False)))
295+ self.assertThat(lambda: win.is_focused, Eventually(Equals(True)))
296+
297+ def test_icon_focuses_application_window_when_hud_is_open(self):
298+ """Clicking on an icon when hud is shown must focus it."""
299+ win = self.process_manager.start_app_window("Calculator")
300+ self.assertThat(lambda: win.is_focused, Eventually(Equals(True)))
301+
302+ self.addCleanup(self.unity.hud.ensure_hidden)
303+ self.unity.hud.ensure_visible()
304+ self.assertThat(lambda: win.is_focused, Eventually(Equals(False)))
305+
306+ icon = self.unity.launcher.model.get_icon(desktop_id=win.application.desktop_file)
307+ self.launcher_instance.click_launcher_icon(icon)
308+
309+ self.assertThat(self.unity.hud.visible, Eventually(Equals(False)))
310+ self.assertThat(lambda: win.is_focused, Eventually(Equals(True)))
311+
312+
313 class LauncherDragIconsBehavior(LauncherTestCase):
314 """Tests dragging icons around the Launcher."""
315
316
317=== modified file 'tests/test_application_launcher_icon.cpp'
318--- tests/test_application_launcher_icon.cpp 2013-09-11 10:45:10 +0000
319+++ tests/test_application_launcher_icon.cpp 2013-10-03 13:43:44 +0000
320@@ -27,6 +27,8 @@
321 #include "ApplicationLauncherIcon.h"
322 #include "FavoriteStore.h"
323 #include "StandaloneWindowManager.h"
324+#include "UBusWrapper.h"
325+#include "UBusMessages.h"
326 #include "ZeitgeistUtils.h"
327 #include "mock-application.h"
328 #include "test_utils.h"
329@@ -63,6 +65,7 @@
330 MOCK_CONST_METHOD0(GetRemoteMenus, glib::Object<DbusmenuMenuitem>());
331
332 bool LauncherIconIsSticky() const { return LauncherIcon::IsSticky(); }
333+ void LocalActivate(ActionArg a) { ApplicationLauncherIcon::ActivateLauncherIcon(a); }
334
335 using ApplicationLauncherIcon::IsFileManager;
336 using ApplicationLauncherIcon::LogUnityEvent;
337@@ -1109,4 +1112,21 @@
338 usc_icon->Remove();
339 }
340
341+TEST_F(TestApplicationLauncherIcon, ClosesOverlayOnActivation)
342+{
343+ bool closes_overlay = false;
344+ UBusManager manager;
345+ manager.RegisterInterest(UBUS_OVERLAY_CLOSE_REQUEST, [&closes_overlay] (GVariant* v) {
346+ ASSERT_THAT(v, IsNull());
347+ closes_overlay = true;
348+ });
349+
350+ // XXX: we should abstract the application activation into application::Manager
351+ ON_CALL(*mock_icon, ActivateLauncherIcon(_)).WillByDefault(Invoke([this] (ActionArg a) { mock_icon->LocalActivate(a); }));
352+ mock_icon->Activate(ActionArg());
353+ Utils::WaitUntil(closes_overlay);
354+
355+ EXPECT_TRUE(closes_overlay);
356 }
357+
358+} // anonymous namespace