Merge lp:~3v1n0/unity/search-bar-modifiers-filter 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: 2428
Proposed branch: lp:~3v1n0/unity/search-bar-modifiers-filter
Merge into: lp:unity
Prerequisite: lp:~3v1n0/unity/close-overlays-on-spread
Diff against target: 345 lines (+244/-32)
4 files modified
tests/CMakeLists.txt (+1/-0)
tests/test_im_text_entry.cpp (+202/-0)
unity-shared/IMTextEntry.cpp (+34/-26)
unity-shared/IMTextEntry.h (+7/-6)
To merge this branch: bzr merge lp:~3v1n0/unity/search-bar-modifiers-filter
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
Review via email: mp+111059@code.launchpad.net

Commit message

IMTextEntry: ignore invalid keypress when using modifiers keys.

All the key pressure when pressing the Alt or Super key should be ignored.
When pressing Ctrl key we should only allow: A key, arrow keys, Backspace or Delete keys and Home or Delete keys.

Description of the change

Adding proper filters to prevent invalid Ctrl+<key> pressure and all the Super+<key> and Alt+<key> presses, to be consistent with Gtk text entries and to avoid that using a compiz keybinding (such as Super+W) would cause the key to be written into the Dash or Hud search bars.

Unit tests included.

To post a comment you must log in.
Revision history for this message
Andrea Azzarone (azzar1) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/CMakeLists.txt'
2--- tests/CMakeLists.txt 2012-06-15 02:03:31 +0000
3+++ tests/CMakeLists.txt 2012-06-19 16:37:24 +0000
4@@ -207,6 +207,7 @@
5 test_main.cpp
6 test_lensview_impl.cpp
7 test_icon_loader.cpp
8+ test_im_text_entry.cpp
9 test_hud_view.cpp
10 test_resultviewgrid.cpp
11 test_single_monitor_launcher_icon.cpp
12
13=== added file 'tests/test_im_text_entry.cpp'
14--- tests/test_im_text_entry.cpp 1970-01-01 00:00:00 +0000
15+++ tests/test_im_text_entry.cpp 2012-06-19 16:37:24 +0000
16@@ -0,0 +1,202 @@
17+/*
18+ * Copyright 2012 Canonical Ltd.
19+ *
20+ * This program is free software: you can redistribute it and/or modify it
21+ * under the terms of the GNU Lesser General Public License version 3, as
22+ * published by the Free Software Foundation.
23+ *
24+ * This program is distributed in the hope that it will be useful, but
25+ * WITHOUT ANY WARRANTY; without even the implied warranties of
26+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
27+ * PURPOSE. See the applicable version of the GNU Lesser General Public
28+ * License for more details.
29+ *
30+ * You should have received a copy of both the GNU Lesser General Public
31+ * License version 3 along with this program. If not, see
32+ * <http://www.gnu.org/licenses/>
33+ *
34+ * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
35+ *
36+ */
37+
38+#include <gmock/gmock.h>
39+#include "unity-shared/IMTextEntry.h"
40+
41+using namespace testing;
42+using namespace unity;
43+
44+namespace
45+{
46+
47+class TestEvent : public nux::Event
48+{
49+public:
50+ TestEvent(nux::KeyModifier keymod, unsigned long keysym)
51+ {
52+ type = NUX_KEYDOWN;
53+ key_modifiers = keymod;
54+ x11_keysym = keysym;
55+ }
56+
57+ TestEvent(unsigned long keysym)
58+ {
59+ type = NUX_KEYDOWN;
60+ x11_keysym = keysym;
61+ }
62+};
63+
64+class MockTextEntry : public IMTextEntry
65+{
66+public:
67+ MOCK_METHOD1(InsertText, void(std::string const&));
68+ MOCK_METHOD0(Cut, void());
69+ MOCK_METHOD0(Copy, void());
70+ MOCK_METHOD1(Paste, void(bool));
71+
72+ bool TryHandleSpecial(nux::Event const& event)
73+ {
74+ return IMTextEntry::TryHandleSpecial(event);
75+ }
76+};
77+
78+
79+TEST(TestIMTextEntry, CopyCtrlC)
80+{
81+ MockTextEntry text_entry;
82+
83+ TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_c);
84+
85+ EXPECT_CALL(text_entry, Copy());
86+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
87+}
88+
89+TEST(TestIMTextEntry, CopyCtrlIns)
90+{
91+ MockTextEntry text_entry;
92+
93+ TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_INSERT);
94+
95+ EXPECT_CALL(text_entry, Copy());
96+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
97+}
98+
99+TEST(TestIMTextEntry, PasteCtrlV)
100+{
101+ MockTextEntry text_entry;
102+
103+ TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_v);
104+
105+ EXPECT_CALL(text_entry, Paste(false));
106+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
107+}
108+
109+TEST(TestIMTextEntry, PasteShiftIns)
110+{
111+ MockTextEntry text_entry;
112+
113+ TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_INSERT);
114+
115+ EXPECT_CALL(text_entry, Paste(false));
116+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
117+}
118+
119+TEST(TestIMTextEntry, CutCtrlX)
120+{
121+ MockTextEntry text_entry;
122+
123+ TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_x);
124+
125+ EXPECT_CALL(text_entry, Cut());
126+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
127+}
128+
129+TEST(TestIMTextEntry, CutShiftDel)
130+{
131+ MockTextEntry text_entry;
132+
133+ TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_DELETE);
134+
135+ EXPECT_CALL(text_entry, Cut());
136+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
137+}
138+
139+TEST(TestIMTextEntry, CtrlMoveKeys)
140+{
141+ MockTextEntry text_entry;
142+
143+ TestEvent left(KEY_MODIFIER_CTRL, NUX_VK_LEFT);
144+ EXPECT_TRUE(text_entry.TryHandleSpecial(left));
145+
146+ TestEvent right(KEY_MODIFIER_CTRL, NUX_VK_RIGHT);
147+ EXPECT_TRUE(text_entry.TryHandleSpecial(right));
148+
149+ TestEvent home(KEY_MODIFIER_CTRL, NUX_VK_HOME);
150+ EXPECT_TRUE(text_entry.TryHandleSpecial(home));
151+
152+ TestEvent end(KEY_MODIFIER_CTRL, NUX_VK_END);
153+ EXPECT_TRUE(text_entry.TryHandleSpecial(end));
154+}
155+
156+TEST(TestIMTextEntry, CtrlDeleteKeys)
157+{
158+ MockTextEntry text_entry;
159+
160+ TestEvent del(KEY_MODIFIER_CTRL, NUX_VK_DELETE);
161+ EXPECT_TRUE(text_entry.TryHandleSpecial(del));
162+
163+ TestEvent backspace(KEY_MODIFIER_CTRL, NUX_VK_BACKSPACE);
164+ EXPECT_TRUE(text_entry.TryHandleSpecial(backspace));
165+}
166+
167+TEST(TestIMTextEntry, CtrlA)
168+{
169+ MockTextEntry text_entry;
170+
171+ TestEvent selectall(KEY_MODIFIER_CTRL, NUX_VK_a);
172+ EXPECT_TRUE(text_entry.TryHandleSpecial(selectall));
173+}
174+
175+TEST(TestIMTextEntry, CtrlKeybindings)
176+{
177+ MockTextEntry text_entry;
178+
179+ std::vector<unsigned long> allowed_keys { NUX_VK_a, NUX_VK_BACKSPACE,
180+ NUX_VK_LEFT, NUX_VK_RIGHT,
181+ NUX_VK_HOME, NUX_VK_END,
182+ NUX_VK_BACKSPACE, NUX_VK_DELETE };
183+
184+ for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym)
185+ {
186+ bool should_be_handled = false;
187+
188+ if (std::find(allowed_keys.begin(), allowed_keys.end(), keysym) != allowed_keys.end())
189+ should_be_handled = true;
190+
191+ TestEvent event(KEY_MODIFIER_CTRL, keysym);
192+ EXPECT_EQ(text_entry.TryHandleSpecial(event), should_be_handled);
193+ }
194+}
195+
196+TEST(TestIMTextEntry, AltKeybindings)
197+{
198+ MockTextEntry text_entry;
199+
200+ for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym)
201+ {
202+ TestEvent event(KEY_MODIFIER_ALT, keysym);
203+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
204+ }
205+}
206+
207+TEST(TestIMTextEntry, SuperKeybindings)
208+{
209+ MockTextEntry text_entry;
210+
211+ for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym)
212+ {
213+ TestEvent event(KEY_MODIFIER_SUPER, keysym);
214+ EXPECT_FALSE(text_entry.TryHandleSpecial(event));
215+ }
216+}
217+
218+}
219
220=== modified file 'unity-shared/IMTextEntry.cpp'
221--- unity-shared/IMTextEntry.cpp 2012-05-06 23:48:38 +0000
222+++ unity-shared/IMTextEntry.cpp 2012-06-19 16:37:24 +0000
223@@ -44,52 +44,60 @@
224 unsigned int keysym,
225 const char* character)
226 {
227- bool need_to_filter_event = TryHandleSpecial(event_type, keysym, character);
228-
229+ nux::Event const& event = nux::GetGraphicsDisplay()->GetCurrentEvent();
230+ bool need_to_filter_event = TryHandleSpecial(event);
231+
232 if (need_to_filter_event)
233 need_to_filter_event = TextEntry::InspectKeyEvent(event_type, keysym, character);
234-
235+
236 return need_to_filter_event;
237 }
238
239-bool IMTextEntry::TryHandleSpecial(unsigned int eventType, unsigned int keysym, const char* character)
240+bool IMTextEntry::TryHandleSpecial(nux::Event const& event)
241 {
242- nux::Event event = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent();
243- unsigned int keyval = keysym;
244- bool shift = (event.GetKeyState() & NUX_STATE_SHIFT);
245- bool ctrl = (event.GetKeyState() & NUX_STATE_CTRL);
246-
247 /* If there is preedit, handle the event else where, but we
248 want to be able to copy/paste while ibus is active */
249 if (!preedit_.empty())
250 return true;
251
252- if (eventType != NUX_KEYDOWN)
253+ if (event.type != NUX_KEYDOWN)
254 return false;
255
256- if (((keyval == NUX_VK_x) && ctrl && !shift) ||
257- ((keyval == NUX_VK_DELETE) && shift && !ctrl))
258+ unsigned int keyval = event.GetKeySym();
259+ bool shift = event.GetKeyModifierState(KEY_MODIFIER_SHIFT);
260+ bool ctrl = event.GetKeyModifierState(KEY_MODIFIER_CTRL);
261+ bool super = event.GetKeyModifierState(KEY_MODIFIER_SUPER);
262+ bool alt = event.GetKeyModifierState(KEY_MODIFIER_ALT);
263+
264+ if ((ctrl && !shift && keyval == NUX_VK_x) || // Ctrl + X
265+ (shift && !ctrl && keyval == NUX_VK_DELETE)) // Shift + Del
266 {
267 Cut();
268 }
269- else if (((keyval == NUX_VK_c) && ctrl && (!shift)) ||
270- ((keyval == NUX_VK_INSERT) && ctrl && (!shift)))
271+ else if (ctrl && !shift && (keyval == NUX_VK_c || keyval == NUX_VK_INSERT)) // Ctrl + C / Ins
272 {
273 Copy();
274 }
275- else if (((keyval == NUX_VK_v) && ctrl && (!shift)) ||
276- ((keyval == NUX_VK_INSERT) && shift && (!ctrl)))
277+ else if ((ctrl && !shift && keyval == NUX_VK_v) || // Ctrl + V
278+ (shift && !ctrl && keyval == NUX_VK_INSERT)) // Shift + Ins
279 {
280 Paste();
281 }
282- else if (keyval == NUX_VK_TAB || keyval == NUX_VK_LEFT_TAB)
283- {
284- return true;
285- }
286- else
287- {
288- return true;
289- }
290+ else if (ctrl)
291+ {
292+ if (keyval == NUX_VK_LEFT || keyval == NUX_VK_RIGHT || // Ctrl + Move keys
293+ keyval == NUX_VK_HOME || keyval == NUX_VK_END || // Ctrl + Home / End
294+ keyval == NUX_VK_BACKSPACE || keyval == NUX_VK_DELETE || // Ctrl + Backspace / Delete
295+ keyval == NUX_VK_a) // Ctrl + A
296+ {
297+ return true;
298+ }
299+ }
300+ else if (!alt && !super)
301+ {
302+ return true;
303+ }
304+
305 return false;
306 }
307
308@@ -146,10 +154,10 @@
309 int button = nux::GetEventButton(bflags);
310
311 if (button == 2)
312- {
313+ {
314 SetCursor(XYToTextIndex(x,y));
315 Paste(true);
316- }
317+ }
318 }
319
320 bool IMTextEntry::im_preedit()
321
322=== modified file 'unity-shared/IMTextEntry.h'
323--- unity-shared/IMTextEntry.h 2012-05-06 23:48:38 +0000
324+++ unity-shared/IMTextEntry.h 2012-06-19 16:37:24 +0000
325@@ -43,13 +43,14 @@
326
327 private:
328 bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character);
329- bool TryHandleSpecial(unsigned int eventType, unsigned int keysym, const char* character);
330- void InsertText(std::string const& text);
331- void Cut();
332- void Copy();
333- void Paste(bool primary = false);
334-
335 void OnMouseButtonUp(int x, int y, unsigned long bflags, unsigned long kflags);
336+
337+protected:
338+ bool TryHandleSpecial(nux::Event const& event);
339+ virtual void InsertText(std::string const& text);
340+ virtual void Cut();
341+ virtual void Copy();
342+ virtual void Paste(bool primary = false);
343 };
344
345 }