Nux

Merge lp:~3v1n0/nux/text-entry-compose-ignore-modifiers into lp:nux

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: 661
Merged at revision: 629
Proposed branch: lp:~3v1n0/nux/text-entry-compose-ignore-modifiers
Merge into: lp:nux
Diff against target: 458 lines (+144/-63)
2 files modified
Nux/TextEntry.cpp (+37/-4)
tests/gtest-nux-textentry.cpp (+107/-59)
To merge this branch: bzr merge lp:~3v1n0/nux/text-entry-compose-ignore-modifiers
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
Review via email: mp+113323@code.launchpad.net

Commit message

TextEntry: ignore meta keypresses when in composition mode

Description of the change

When in composition mode any pressure of a modifier key (such as AltGr) should be ignored, so that it's possible to continue to compose a correct char.

Tests covered by gtest.

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

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Nux/TextEntry.cpp'
2--- Nux/TextEntry.cpp 2012-07-03 23:24:53 +0000
3+++ Nux/TextEntry.cpp 2012-07-04 02:35:22 +0000
4@@ -371,6 +371,7 @@
5 unsigned int keyval = keysym;
6 bool shift = (state & NUX_STATE_SHIFT);
7 bool ctrl = (state & NUX_STATE_CTRL);
8+ bool handled = false;
9
10 // DLOG("TextEntry::key_down(%d, shift:%d ctrl:%d)", keyval, shift, ctrl);
11 if (event_type == NUX_KEYDOWN)
12@@ -381,6 +382,8 @@
13 MoveCursor(VISUALLY, -1, shift);
14 else
15 MoveCursor(WORDS, -1, shift);
16+
17+ handled = true;
18 }
19 else if (keyval == NUX_VK_RIGHT)
20 {
21@@ -388,16 +391,20 @@
22 MoveCursor(VISUALLY, 1, shift);
23 else
24 MoveCursor(WORDS, 1, shift);
25+
26+ handled = true;
27 }
28 else if (keyval == NUX_VK_UP)
29 {
30 // move cursor to start of line
31 MoveCursor(DISPLAY_LINES, -1, shift);
32+ handled = true;
33 }
34 else if (keyval == NUX_VK_DOWN)
35 {
36 // move cursor to end of line
37 MoveCursor(DISPLAY_LINES, 1, shift);
38+ handled = true;
39 }
40 else if (keyval == NUX_VK_HOME)
41 {
42@@ -405,6 +412,8 @@
43 MoveCursor(DISPLAY_LINE_ENDS, -1, shift);
44 else
45 MoveCursor(BUFFER, -1, shift);
46+
47+ handled = true;
48 }
49 else if (keyval == NUX_VK_END)
50 {
51@@ -412,6 +421,8 @@
52 MoveCursor(DISPLAY_LINE_ENDS, 1, shift);
53 else
54 MoveCursor(BUFFER, 1, shift);
55+
56+ handled = true;
57 }
58 else if (keyval == NUX_VK_PAGE_UP)
59 {
60@@ -419,6 +430,8 @@
61 MoveCursor(PAGES, -1, shift);
62 else
63 MoveCursor(BUFFER, -1, shift);
64+
65+ handled = true;
66 }
67 else if (keyval == NUX_VK_PAGE_DOWN)
68 {
69@@ -426,23 +439,28 @@
70 MoveCursor(PAGES, 1, shift);
71 else
72 MoveCursor(BUFFER, 1, shift);
73+
74+ handled = true;
75 }
76 else if (((keyval == NUX_VK_x) && ctrl && !shift) || ((keyval == NUX_VK_DELETE) && shift && !ctrl))
77 {
78 CutClipboard();
79+ handled = true;
80 }
81 else if (((keyval == NUX_VK_c) && ctrl && (!shift)) || ((keyval == NUX_VK_INSERT) && ctrl && (!shift)))
82 {
83 CopyClipboard();
84+ handled = true;
85 }
86 else if (((keyval == NUX_VK_v) && ctrl && (!shift)) || ((keyval == NUX_VK_INSERT) && shift && (!ctrl)))
87 {
88 PasteClipboard();
89+ handled = true;
90 }
91 else if ((keyval == NUX_VK_a) && ctrl)
92 {
93 SelectAll();
94- return;
95+ handled = true;
96 }
97 else if (keyval == NUX_VK_BACKSPACE)
98 {
99@@ -450,6 +468,8 @@
100 BackSpace(VISUALLY);
101 else
102 BackSpace(WORDS);
103+
104+ handled = true;
105 }
106 else if ((keyval == NUX_VK_DELETE) && (!shift))
107 {
108@@ -457,10 +477,13 @@
109 Delete(VISUALLY);
110 else
111 Delete(WORDS);
112+
113+ handled = true;
114 }
115 else if ((keyval == NUX_VK_INSERT) && (!shift) && (!ctrl))
116 {
117 ToggleOverwrite();
118+ handled = true;
119 }
120 // else
121 // {
122@@ -483,7 +506,7 @@
123 // }
124 }
125
126- if (character)
127+ if (!handled && character)
128 {
129 unsigned int utf_char = g_utf8_get_char(character);
130
131@@ -672,9 +695,19 @@
132 return true;
133 }
134
135- if (composition_mode_ && character)
136+ if (composition_mode_)
137 {
138- if (strncmp(character, "", 1) == 0 && keysym != NUX_VK_SHIFT)
139+ /* Excluding meta keys and shifts as composition cancellation */
140+ if ((keysym >= XK_Shift_L && keysym <= XK_Hyper_R) ||
141+ keysym == XK_ISO_Level3_Shift)
142+ {
143+ return true;
144+ }
145+
146+ if (!character)
147+ return true;
148+
149+ if (strncmp(character, "", 1) == 0)
150 {
151 composition_mode_ = false;
152 composition_string_.clear();
153
154=== modified file 'tests/gtest-nux-textentry.cpp'
155--- tests/gtest-nux-textentry.cpp 2012-07-03 16:32:17 +0000
156+++ tests/gtest-nux-textentry.cpp 2012-07-04 02:35:22 +0000
157@@ -61,6 +61,11 @@
158 TextEntry::SetCursor(cursor);
159 }
160
161+ bool InCompositionMode() const
162+ {
163+ return composition_mode_;
164+ }
165+
166 nux::IBusIMEContext* ime() const
167 {
168 #if defined(NUX_OS_LINUX)
169@@ -70,12 +75,6 @@
170 #endif
171 }
172
173- void WaitEvent()
174- {
175- if (im_running())
176- Utils::WaitForTimeoutMSec(100);
177- }
178-
179 MOCK_METHOD0(CutClipboard, void());
180 MOCK_METHOD0(CopyClipboard, void());
181 MOCK_METHOD0(PasteClipboard, void());
182@@ -87,22 +86,23 @@
183 class TestEvent : public Event
184 {
185 public:
186- TestEvent(KeyModifier keymod, unsigned long keysym)
187+ TestEvent(KeyModifier keymod, unsigned long keysym, EventType type = NUX_KEYDOWN)
188 {
189- type = NUX_KEYDOWN;
190+ Init(keysym, type);
191 key_modifiers = keymod;
192-#if defined(NUX_OS_LINUX)
193- x11_keysym = keysym;
194-#elif defined(NUX_OS_WINDOWS)
195- win32_keysym = keysym;
196-#endif
197- }
198-
199- TestEvent(unsigned long keysym)
200- {
201- type = NUX_KEYDOWN;
202-#if defined(NUX_OS_LINUX)
203- x11_keysym = keysym;
204+ }
205+
206+ TestEvent(unsigned long keysym, EventType type = NUX_KEYDOWN)
207+ {
208+ Init(keysym, type);
209+ }
210+
211+ void Init(unsigned long keysym, EventType etype)
212+ {
213+ type = etype;
214+#if defined(NUX_OS_LINUX)
215+ x11_keysym = keysym;
216+ g_unichar_to_utf8(x11_keysym, text);
217 #elif defined(NUX_OS_WINDOWS)
218 win32_keysym = keysym;
219 #endif
220@@ -126,6 +126,18 @@
221 GetWindowCompositor().SetKeyFocusArea(text_entry);
222 }
223
224+ void WaitEvent()
225+ {
226+ if (text_entry->im_running())
227+ Utils::WaitForTimeoutMSec(100);
228+ }
229+
230+ void SendEvent(Event& event)
231+ {
232+ GetWindowCompositor().ProcessEvent(event);
233+ WaitEvent();
234+ }
235+
236 std::unique_ptr<WindowThread> wnd_thread;
237 MockTextEntry* text_entry;
238 };
239@@ -212,7 +224,7 @@
240 unsigned int keysym = g_utf8_get_char(c.c_str());
241 text_entry->DeleteText(0, std::numeric_limits<int>::max());
242 text_entry->key_down.emit(NUX_KEYDOWN, keysym, 0, c.c_str(), 1);
243- text_entry->WaitEvent();
244+ WaitEvent();
245 EXPECT_EQ(text_entry->GetText(), "");
246 }
247 }
248@@ -221,32 +233,28 @@
249 {
250 EXPECT_CALL(*text_entry, CopyClipboard());
251 TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_c);
252- GetWindowCompositor().ProcessEvent(event);
253- text_entry->WaitEvent();
254+ SendEvent(event);
255 }
256
257 TEST_F(TestTextEntry, CopyCtrlIns)
258 {
259 EXPECT_CALL(*text_entry, CopyClipboard());
260 TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_INSERT);
261- GetWindowCompositor().ProcessEvent(event);
262- text_entry->WaitEvent();
263+ SendEvent(event);
264 }
265
266 TEST_F(TestTextEntry, PasteCtrlV)
267 {
268 EXPECT_CALL(*text_entry, PasteClipboard());
269 TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_v);
270- GetWindowCompositor().ProcessEvent(event);
271- text_entry->WaitEvent();
272+ SendEvent(event);
273 }
274
275 TEST_F(TestTextEntry, PasteShiftIns)
276 {
277 EXPECT_CALL(*text_entry, PasteClipboard());
278 TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_INSERT);
279- GetWindowCompositor().ProcessEvent(event);
280- text_entry->WaitEvent();
281+ SendEvent(event);
282 }
283
284 #if defined(NUX_OS_LINUX)
285@@ -267,16 +275,14 @@
286 {
287 EXPECT_CALL(*text_entry, CutClipboard());
288 TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_x);
289- GetWindowCompositor().ProcessEvent(event);
290- text_entry->WaitEvent();
291+ SendEvent(event);
292 }
293
294 TEST_F(TestTextEntry, CutShiftDel)
295 {
296 EXPECT_CALL(*text_entry, CutClipboard());
297 TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_DELETE);
298- GetWindowCompositor().ProcessEvent(event);
299- text_entry->WaitEvent();
300+ SendEvent(event);
301 }
302
303 TEST_F(TestTextEntry, CtrlA)
304@@ -289,8 +295,7 @@
305 ASSERT_EQ(start, end);
306 ASSERT_EQ(start, test_str.length());
307
308- GetWindowCompositor().ProcessEvent(selectall);
309- text_entry->WaitEvent();
310+ SendEvent(selectall);
311 EXPECT_TRUE(text_entry->GetSelectionBounds(&start, &end));
312 EXPECT_EQ(start, 0);
313 EXPECT_EQ(end, test_str.length());
314@@ -305,23 +310,19 @@
315 ASSERT_EQ(text_entry->GetCursor(), 0);
316
317 TestEvent right(NUX_VK_RIGHT);
318- GetWindowCompositor().ProcessEvent(right);
319- text_entry->WaitEvent();
320+ SendEvent(right);
321 EXPECT_EQ(text_entry->GetCursor(), 1);
322
323 TestEvent end(NUX_VK_END);
324- GetWindowCompositor().ProcessEvent(end);
325- text_entry->WaitEvent();
326+ SendEvent(end);
327 EXPECT_EQ(text_entry->GetCursor(), test_str.length());
328
329 TestEvent left(NUX_VK_LEFT);
330- GetWindowCompositor().ProcessEvent(left);
331- text_entry->WaitEvent();
332+ SendEvent(left);
333 EXPECT_EQ(text_entry->GetCursor(), 2);
334
335 TestEvent home(NUX_VK_HOME);
336- GetWindowCompositor().ProcessEvent(home);
337- text_entry->WaitEvent();
338+ SendEvent(home);
339 EXPECT_EQ(text_entry->GetCursor(), 0);
340 }
341
342@@ -334,23 +335,19 @@
343 ASSERT_EQ(text_entry->GetCursor(), 0);
344
345 TestEvent right(KEY_MODIFIER_CTRL, NUX_VK_RIGHT);
346- GetWindowCompositor().ProcessEvent(right);
347- text_entry->WaitEvent();
348+ SendEvent(right);
349 EXPECT_EQ(text_entry->GetCursor(), 3);
350
351 TestEvent left(KEY_MODIFIER_CTRL, NUX_VK_LEFT);
352- GetWindowCompositor().ProcessEvent(left);
353- text_entry->WaitEvent();
354+ SendEvent(left);
355 EXPECT_EQ(text_entry->GetCursor(), 0);
356
357 TestEvent end(KEY_MODIFIER_CTRL, NUX_VK_END);
358- GetWindowCompositor().ProcessEvent(end);
359- text_entry->WaitEvent();
360+ SendEvent(end);
361 EXPECT_EQ(text_entry->GetCursor(), test_str.length());
362
363 TestEvent home(KEY_MODIFIER_CTRL, NUX_VK_HOME);
364- GetWindowCompositor().ProcessEvent(home);
365- text_entry->WaitEvent();
366+ SendEvent(home);
367 EXPECT_EQ(text_entry->GetCursor(), 0);
368 }
369
370@@ -361,14 +358,12 @@
371 text_entry->SetCursor(0);
372
373 TestEvent del(NUX_VK_DELETE);
374- GetWindowCompositor().ProcessEvent(del);
375- text_entry->WaitEvent();
376+ SendEvent(del);
377 EXPECT_EQ(text_entry->GetText(), "ux");
378
379 text_entry->SetCursor(std::string(text_entry->GetText()).length());
380 TestEvent backspace(NUX_VK_BACKSPACE);
381- GetWindowCompositor().ProcessEvent(backspace);
382- text_entry->WaitEvent();
383+ SendEvent(backspace);
384 EXPECT_EQ(text_entry->GetText(), "u");
385 }
386
387@@ -379,14 +374,67 @@
388 text_entry->SetCursor(0);
389
390 TestEvent del(KEY_MODIFIER_CTRL, NUX_VK_DELETE);
391- GetWindowCompositor().ProcessEvent(del);
392- text_entry->WaitEvent();
393+ SendEvent(del);
394 EXPECT_EQ(text_entry->GetText(), " Text Entry");
395
396 text_entry->SetCursor(std::string(text_entry->GetText()).length());
397 TestEvent backspace(KEY_MODIFIER_CTRL, NUX_VK_BACKSPACE);
398- GetWindowCompositor().ProcessEvent(backspace);
399- text_entry->WaitEvent();
400+ SendEvent(backspace);
401 EXPECT_EQ(text_entry->GetText(), " Text ");
402 }
403+
404+#if defined(NUX_OS_LINUX)
405+TEST_F(TestTextEntry, CompositionStart)
406+{
407+ ASSERT_FALSE(text_entry->InCompositionMode());
408+ TestEvent compose(XK_Multi_key);
409+ SendEvent(compose);
410+ EXPECT_TRUE(text_entry->InCompositionMode());
411+}
412+
413+TEST_F(TestTextEntry, CompositionWrite)
414+{
415+ ASSERT_FALSE(text_entry->InCompositionMode());
416+ TestEvent compose(XK_Multi_key);
417+ SendEvent(compose);
418+
419+ TestEvent tilde(XK_asciitilde);
420+ SendEvent(tilde);
421+ EXPECT_TRUE(text_entry->InCompositionMode());
422+
423+ TestEvent n(TestEvent(XK_n));
424+ SendEvent(n);
425+ EXPECT_FALSE(text_entry->InCompositionMode());
426+
427+ EXPECT_EQ(text_entry->GetText(), "ñ");
428+}
429+
430+TEST_F(TestTextEntry, CompositionIgnoreModifiers)
431+{
432+ ASSERT_FALSE(text_entry->InCompositionMode());
433+ TestEvent compose(XK_Multi_key);
434+ SendEvent(compose);
435+
436+ TestEvent tilde(XK_asciitilde);
437+ SendEvent(tilde);
438+ EXPECT_TRUE(text_entry->InCompositionMode());
439+
440+ for (auto keysym = XK_Shift_L; keysym <= XK_Hyper_R; ++keysym)
441+ {
442+ TestEvent modifier(keysym);
443+ SendEvent(modifier);
444+ EXPECT_TRUE(text_entry->InCompositionMode());
445+ }
446+
447+ TestEvent AltGr(XK_ISO_Level3_Shift);
448+ SendEvent(AltGr);
449+ EXPECT_TRUE(text_entry->InCompositionMode());
450+
451+ TestEvent n(TestEvent(XK_n));
452+ SendEvent(n);
453+ EXPECT_FALSE(text_entry->InCompositionMode());
454+
455+ EXPECT_EQ(text_entry->GetText(), "ñ");
456+}
457+#endif
458 }

Subscribers

People subscribed via source and target branches