Merge lp:~brandontschaefer/unity/mouse-move-hud-buttons-focus into lp:unity

Proposed by Brandon Schaefer
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 2663
Proposed branch: lp:~brandontschaefer/unity/mouse-move-hud-buttons-focus
Merge into: lp:unity
Diff against target: 322 lines (+140/-22)
4 files modified
hud/HudButton.cpp (+17/-1)
hud/HudView.cpp (+62/-1)
hud/HudView.h (+6/-0)
tests/autopilot/unity/tests/test_hud.py (+55/-20)
To merge this branch: bzr merge lp:~brandontschaefer/unity/mouse-move-hud-buttons-focus
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Gord Allott (community) Approve
jenkins continuous-integration Pending
Review via email: mp+121966@code.launchpad.net

Commit message

The mouse will now cause the HUD buttons to change selection.

Description of the change

=== Problem ===
Moving the mouse over a Hud button does not change its visual focus.

=== Fix ===
Using mouse_enter/leave/move to change the visual focus of the Hud button to follow the mouse.

=== Tests ===
AP tests

To post a comment you must log in.
Revision history for this message
Gord Allott (gordallott) wrote :

seems okay to me, +1

review: Approve
Revision history for this message
Tim Penhey (thumper) wrote :

Approving dead code removal.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hud/HudButton.cpp'
2--- hud/HudButton.cpp 2012-08-06 15:39:20 +0000
3+++ hud/HudButton.cpp 2012-09-04 18:17:20 +0000
4@@ -75,6 +75,22 @@
5 {
6 QueueDraw();
7 });
8+
9+ mouse_move.connect([&](int x, int y, int dx, int dy, unsigned int button, unsigned int key)
10+ {
11+ if (!fake_focused)
12+ fake_focused = true;
13+ });
14+
15+ mouse_enter.connect([&](int x, int y, unsigned int button, unsigned int key)
16+ {
17+ fake_focused = true;
18+ });
19+
20+ mouse_leave.connect([&](int x, int y, unsigned int button, unsigned int key)
21+ {
22+ fake_focused = false;
23+ });
24 }
25
26 void HudButton::InitTheme()
27@@ -113,7 +129,6 @@
28 return false;
29 }
30
31-
32 long HudButton::ComputeContentSize()
33 {
34 long ret = nux::Button::ComputeContentSize();
35@@ -207,6 +222,7 @@
36 nux::StaticCairoText* text = new nux::StaticCairoText(item.first);
37 text->SetTextColor(nux::Color(1.0f, 1.0f, 1.0f, item.second ? 1.0f : 0.5f));
38 text->SetFont(button_font);
39+ text->SetInputEventSensitivity(false);
40 hlayout_->AddView(text, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
41 }
42 }
43
44=== modified file 'hud/HudView.cpp'
45--- hud/HudView.cpp 2012-08-20 14:26:14 +0000
46+++ hud/HudView.cpp 2012-09-04 18:17:20 +0000
47@@ -66,6 +66,7 @@
48 , timeline_need_more_draw_(false)
49 , selected_button_(0)
50 , show_embedded_icon_(true)
51+ , keyboard_stole_focus_(false)
52 {
53 renderer_.SetOwner(this);
54 renderer_.need_redraw.connect([this] () {
55@@ -251,6 +252,22 @@
56 query_activated.emit(dynamic_cast<HudButton*>(view)->GetQuery());
57 });
58
59+ button->mouse_move.connect([&](int x, int y, int dx, int dy, unsigned long mouse_button, unsigned long special_key) {
60+ if (keyboard_stole_focus_)
61+ {
62+ MouseStealsHudButtonFocus();
63+ keyboard_stole_focus_ = false;
64+ }
65+ });
66+
67+ button->mouse_enter.connect([&](int x, int y, unsigned long mouse_button, unsigned long special_key) {
68+ MouseStealsHudButtonFocus();
69+ });
70+
71+ button->mouse_leave.connect([&](int x, int y, unsigned long mouse_button, unsigned long special_key) {
72+ SelectLastFocusedButton();
73+ });
74+
75 button->key_nav_focus_activate.connect([&](nux::Area* area) {
76 query_activated.emit(dynamic_cast<HudButton*>(area)->GetQuery());
77 });
78@@ -484,6 +501,49 @@
79 }
80 }
81
82+void View::MouseStealsHudButtonFocus()
83+{
84+ LoseSelectedButtonFocus();
85+ FindNewSelectedButton();
86+}
87+
88+void View::LoseSelectedButtonFocus()
89+{
90+ int button_index = 1;
91+ for (auto it = buttons_.rbegin(); it != buttons_.rend(); ++it)
92+ {
93+ if (selected_button_ == button_index)
94+ (*it)->fake_focused = false;
95+ ++button_index;
96+ }
97+}
98+
99+void View::FindNewSelectedButton()
100+{
101+ int button_index = 1;
102+ for (auto it = buttons_.rbegin(); it != buttons_.rend(); ++it)
103+ {
104+ if ((*it)->fake_focused)
105+ {
106+ query_selected.emit((*it)->GetQuery());
107+ selected_button_ = button_index;
108+ return;
109+ }
110+ ++button_index;
111+ }
112+}
113+
114+void View::SelectLastFocusedButton()
115+{
116+ int button_index = 1;
117+ for (auto it = buttons_.rbegin(); it != buttons_.rend(); ++it)
118+ {
119+ if (button_index == selected_button_)
120+ (*it)->fake_focused = true;
121+ ++button_index;
122+ }
123+}
124+
125 // Keyboard navigation
126 bool View::AcceptKeyNavFocus()
127 {
128@@ -656,12 +716,12 @@
129 (*next)->fake_focused = true;
130 query_selected.emit((*next)->GetQuery());
131 --selected_button_;
132+ keyboard_stole_focus_ = true;
133 }
134 break;
135 }
136 }
137 }
138-
139 if (event_type == nux::NUX_KEYDOWN && direction == nux::KEY_NAV_DOWN)
140 {
141 std::list<HudButton::Ptr>::reverse_iterator rit;
142@@ -679,6 +739,7 @@
143 (*next)->fake_focused = true;
144 query_selected.emit((*next)->GetQuery());
145 ++selected_button_;
146+ keyboard_stole_focus_ = true;
147 }
148 break;
149 }
150
151=== modified file 'hud/HudView.h'
152--- hud/HudView.h 2012-07-04 02:37:23 +0000
153+++ hud/HudView.h 2012-09-04 18:17:20 +0000
154@@ -85,6 +85,11 @@
155
156 void ProcessGrowShrink();
157
158+ void MouseStealsHudButtonFocus();
159+ void LoseSelectedButtonFocus();
160+ void FindNewSelectedButton();
161+ void SelectLastFocusedButton();
162+
163 std::string GetName() const;
164 void AddProperties(GVariantBuilder* builder);
165 IntrospectableList GetIntrospectableChildren();
166@@ -116,6 +121,7 @@
167 int selected_button_;
168 bool show_embedded_icon_;
169 bool activated_signal_sent_;
170+ bool keyboard_stole_focus_;
171 };
172
173
174
175=== modified file 'tests/autopilot/unity/tests/test_hud.py'
176--- tests/autopilot/unity/tests/test_hud.py 2012-08-27 14:45:44 +0000
177+++ tests/autopilot/unity/tests/test_hud.py 2012-09-04 18:17:20 +0000
178@@ -247,11 +247,11 @@
179 self.mouse.click()
180
181 self.assertThat(self.hud.visible, Eventually(Equals(False)))
182-
183+
184 def test_hud_closes_click_after_text_removed(self):
185 """Clicking outside of the hud after a search text has been entered and
186 then removed from the searchbox will make it close."""
187-
188+
189 self.hud.ensure_visible()
190 self.keyboard.type("Test")
191 self.keyboard.press_and_release("Escape")
192@@ -259,7 +259,7 @@
193 (x,y,w,h) = self.hud.view.geometry
194 self.mouse.move(w/2, h+50)
195 self.mouse.click()
196-
197+
198 self.assertThat(self.hud.visible, Eventually(Equals(False)))
199
200 def test_alt_f4_close_hud(self):
201@@ -276,49 +276,49 @@
202 self.hud.ensure_visible()
203 self.keyboard.press_and_release("Alt+F4")
204 self.assertThat(self.hud.visible, Eventually(Equals(False)))
205-
206+
207 def test_app_activate_on_enter(self):
208 """Hud must close after activating a search item with Enter."""
209- self.hud.ensure_visible()
210-
211+ self.hud.ensure_visible()
212+
213 self.keyboard.type("Device > System Settings")
214 self.assertThat(self.hud.search_string, Eventually(Equals("Device > System Settings")))
215-
216+
217 self.keyboard.press_and_release("Enter")
218-
219+
220 app_found = self.bamf.wait_until_application_is_running("gnome-control-center.desktop", 5)
221 self.assertTrue(app_found)
222 self.addCleanup(self.close_all_app, "System Settings")
223-
224+
225 self.assertThat(self.hud.visible, Eventually(Equals(False)))
226-
227+
228 def test_hud_closes_on_escape(self):
229 """Hud must close on escape after searchbox is cleared"""
230 self.hud.ensure_visible()
231-
232+
233 self.keyboard.type("ThisText")
234 self.keyboard.press_and_release("Escape")
235 self.keyboard.press_and_release("Escape")
236-
237+
238 self.assertThat(self.hud.visible, Eventually(Equals(False)))
239-
240+
241 def test_hud_closes_on_escape_shrunk(self):
242 """Hud must close when escape key is pressed"""
243 self.hud.ensure_visible()
244 self.keyboard.press_and_release("Escape")
245-
246+
247 self.assertThat(self.hud.visible, Eventually(Equals(False)))
248
249 def test_alt_arrow_keys_not_eaten(self):
250 """Tests that Alt+ArrowKey events are correctly passed to the
251 active window when Unity is not responding to them."""
252-
253+
254 self.start_app_window("Terminal")
255-
256+
257 #There's no easy way to read text from terminal, writing input
258 #to a text file and then reading from there works.
259 self.keyboard.type('echo "')
260-
261+
262 #Terminal is receiving input with Alt+Arrowkeys
263 self.keyboard.press("Alt")
264 self.keyboard.press_and_release("Up")
265@@ -326,13 +326,13 @@
266 self.keyboard.press_and_release("Right")
267 self.keyboard.press_and_release("Left")
268 self.keyboard.release("Alt")
269-
270+
271 self.keyboard.type('" > /tmp/ap_test_alt_keys')
272 self.addCleanup(remove, '/tmp/ap_test_alt_keys')
273 self.keyboard.press_and_release("Enter")
274-
275+
276 file_contents = open('/tmp/ap_test_alt_keys', 'r').read().strip()
277-
278+
279 self.assertThat(file_contents, Equals('ABCD'))
280
281 def test_hud_closes_on_item_activated(self):
282@@ -357,6 +357,41 @@
283
284 self.assertThat(self.hud.visible, Eventually(Equals(False)))
285
286+ def test_mouse_changes_selected_hud_button(self):
287+ """This tests moves the mouse from the top of the screen to the bottom, this must
288+ change the selected button from 1 to 5.
289+ """
290+
291+ self.hud.ensure_visible()
292+
293+ self.keyboard.type("a")
294+ (x,y,w,h) = self.hud.view.geometry
295+
296+ self.mouse.move(w/2, 0)
297+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(1)))
298+
299+ self.mouse.move(w/2, h)
300+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(5)))
301+
302+ def test_keyboard_steals_focus_from_mouse(self):
303+ """This tests moves the mouse from the top of the screen to the bottom,
304+ then it presses the keyboard up 5 times, this must change the selected button from 5 to 1.
305+ """
306+
307+ self.hud.ensure_visible()
308+
309+ self.keyboard.type("a")
310+ (x,y,w,h) = self.hud.view.geometry
311+
312+ self.mouse.move(w/2, 0)
313+ self.mouse.move(w/2, h)
314+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(5)))
315+
316+ for i in range(5):
317+ self.keyboard.press_and_release('Up')
318+
319+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(1)))
320+
321
322 class HudLauncherInteractionsTests(HudTestsBase):
323