Nux

Merge lp:~3v1n0/nux/text-entry-double-deadkeys-fix into lp:nux

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: 665
Merged at revision: 630
Proposed branch: lp:~3v1n0/nux/text-entry-double-deadkeys-fix
Merge into: lp:nux
Prerequisite: lp:~3v1n0/nux/text-entry-compose-ignore-modifiers
Diff against target: 275 lines (+144/-32)
3 files modified
Nux/TextEntry.cpp (+35/-31)
Nux/TextEntry.h (+1/-1)
tests/gtest-nux-textentry.cpp (+108/-0)
To merge this branch: bzr merge lp:~3v1n0/nux/text-entry-double-deadkeys-fix
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Review via email: mp+113479@code.launchpad.net

Commit message

TextEntry: correctly handle a "double-deadkey" pressure

Correctly reset the dead_key mode when terminated.

Description of the change

When a deadkey was pressed twice it worked correctly only once, since we were not handling correctly this case.
Now if we're in dead_key_mode and the user types another dead_key we check if the one that has been pressed is equal to the first one, in that case we accept it and we exit from the dead_key mode.

Added gtests.

To post a comment you must log in.
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Looks good, and all tests pass.

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-05 03:04:23 +0000
3+++ Nux/TextEntry.cpp 2012-07-05 03:04:23 +0000
4@@ -326,6 +326,7 @@
5 if (dead_key_mode_ && keysym == XK_space)
6 {
7 dead_key_mode_ = false;
8+ composition_mode_ = false;
9 EnterText(dead_key_string_.c_str());
10 QueueRefresh(false, true);
11 return;
12@@ -649,18 +650,21 @@
13 {
14 #if defined(NUX_OS_LINUX)
15 /* Checks if the keysym between the first and last dead key */
16- if (character && (keysym >= XK_dead_grave) && (keysym <= XK_dead_stroke) && !dead_key_mode_)
17+ if (character && (keysym >= XK_dead_grave) && (keysym <= XK_dead_stroke))
18 {
19 int key = keysym - XK_dead_grave;
20- dead_key_mode_ = true;
21
22 if (dead_keys_map[key])
23 {
24 composition_mode_ = true;
25- composition_string_.clear();
26-
27- dead_key_string_ = character;
28-
29+
30+ if (!dead_key_mode_)
31+ {
32+ composition_string_.clear();
33+ dead_key_string_ = character;
34+ }
35+
36+ dead_key_mode_ = true;
37 std::string dead_key;
38 dead_key = dead_keys_map[key];
39 HandledComposition(keysym, dead_key.c_str());
40@@ -668,14 +672,8 @@
41 return true;
42 }
43 }
44- else if (dead_key_mode_ && (state & IBUS_IGNORED_MASK))
45- {
46- dead_key_mode_ = false;
47- }
48- return false;
49-#else
50- return false;
51 #endif
52+ return false;
53 }
54
55 bool TextEntry::HandledComposition(int keysym, const char* character)
56@@ -714,11 +712,9 @@
57 return true;
58 }
59
60+ std::string composition_match;
61 composition_string_ += character;
62-
63- std::string composition_match;
64-
65- int match = LookForMatch(composition_match);
66+ SearchState match = GetCompositionForString(composition_string_, composition_match);
67
68 if (match == PARTIAL)
69 {
70@@ -726,6 +722,7 @@
71 }
72 else if (match == NO_MATCH)
73 {
74+ dead_key_mode_ = false;
75 composition_mode_ = false;
76 composition_string_.clear();
77 }
78@@ -733,12 +730,10 @@
79 {
80 EnterText(composition_match.c_str());
81 composition_mode_ = false;
82+ dead_key_mode_ = false;
83 composition_string_.clear();
84 QueueRefresh(false, true);
85
86- if (dead_key_mode_)
87- dead_key_mode_ = false;
88-
89 return true;
90 }
91 }
92@@ -1299,25 +1294,34 @@
93 return cached_layout_;
94 }
95
96- int TextEntry::LookForMatch(std::string& str)
97+ TextEntry::SearchState TextEntry::GetCompositionForString(std::string const& input, std::string& composition)
98 {
99- str.clear();
100- int search_state = NO_MATCH;
101-
102- // Check if the string we have is a match,partial match or doesnt match
103+ composition.clear();
104+ SearchState search_state = NO_MATCH;
105+
106+ /* If we have two dead keys concatenated, then we should just write one */
107+ if (dead_key_mode_ && input.length() == 2)
108+ {
109+ if (input[0] == input[1])
110+ {
111+ composition = input[0];
112+ return MATCH;
113+ }
114+ }
115+
116+ /* Check if the string we have is a match, partial match or doesn't match */
117 for (int i = 0; nux_compose_seqs_compact[i] != "\0"; i++)
118 {
119- if (nux_compose_seqs_compact[i].compare(composition_string_) == 0)
120+ if (nux_compose_seqs_compact[i] == input)
121 {
122 // advance to the next sequence after ::
123- while (nux_compose_seqs_compact[++i].compare("::") != 0)
124- {
125- }
126+ while (nux_compose_seqs_compact[++i] != "::")
127+ {}
128
129- str = nux_compose_seqs_compact[++i];
130+ composition = nux_compose_seqs_compact[++i];
131 return MATCH;
132 }
133- else if (nux_compose_seqs_compact[i].find(composition_string_) != std::string::npos)
134+ else if (nux_compose_seqs_compact[i].find(input) == 0)
135 {
136 search_state = PARTIAL;
137 }
138
139=== modified file 'Nux/TextEntry.h'
140--- Nux/TextEntry.h 2012-07-03 23:24:53 +0000
141+++ Nux/TextEntry.h 2012-07-05 03:04:23 +0000
142@@ -352,7 +352,7 @@
143 void GetCursorLocationInLayout(int* strong_x, int* strong_y, int* strong_height,
144 int* weak_x, int* weak_y, int* weak_height);
145
146- int LookForMatch(std::string& str);
147+ SearchState GetCompositionForString(std::string const& input, std::string& composition);
148
149 /** The CairoCanvas which hold cairo_t inside */
150 CairoGraphics* canvas_;
151
152=== modified file 'tests/gtest-nux-textentry.cpp'
153--- tests/gtest-nux-textentry.cpp 2012-07-05 03:04:23 +0000
154+++ tests/gtest-nux-textentry.cpp 2012-07-05 03:04:23 +0000
155@@ -66,6 +66,23 @@
156 return composition_mode_;
157 }
158
159+ bool InDeadKeyMode() const
160+ {
161+ return dead_key_mode_;
162+ }
163+
164+ enum class CompositionResult
165+ {
166+ NO_MATCH,
167+ PARTIAL,
168+ MATCH
169+ };
170+
171+ CompositionResult GetCompositionForString(std::string const& input, std::string& composition)
172+ {
173+ return static_cast<CompositionResult>(TextEntry::GetCompositionForString(input, composition));
174+ }
175+
176 nux::IBusIMEContext* ime() const
177 {
178 #if defined(NUX_OS_LINUX)
179@@ -436,5 +453,96 @@
180
181 EXPECT_EQ(text_entry->GetText(), "ñ");
182 }
183+
184+TEST_F(TestTextEntry, CompositionDeadKey)
185+{
186+ ASSERT_FALSE(text_entry->InCompositionMode());
187+ TestEvent dead_key(XK_dead_circumflex);
188+ SendEvent(dead_key);
189+ EXPECT_TRUE(text_entry->InDeadKeyMode());
190+ EXPECT_TRUE(text_entry->InCompositionMode());
191+
192+ TestEvent a(XK_a);
193+ SendEvent(a);
194+ EXPECT_FALSE(text_entry->InCompositionMode());
195+ EXPECT_FALSE(text_entry->InDeadKeyMode());
196+
197+ EXPECT_EQ(text_entry->GetText(), "â");
198+}
199+
200+TEST_F(TestTextEntry, CompositionDeadKeyRepeat)
201+{
202+ ASSERT_FALSE(text_entry->InCompositionMode());
203+ TestEvent dead_key(XK_dead_grave);
204+ SendEvent(dead_key);
205+ EXPECT_TRUE(text_entry->InDeadKeyMode());
206+ EXPECT_TRUE(text_entry->InCompositionMode());
207+
208+ SendEvent(dead_key);
209+ EXPECT_FALSE(text_entry->InCompositionMode());
210+ EXPECT_FALSE(text_entry->InDeadKeyMode());
211+
212+ EXPECT_EQ(text_entry->GetText(), "`");
213+}
214+
215+TEST_F(TestTextEntry, CompositionDeadKeyComplex)
216+{
217+ ASSERT_FALSE(text_entry->InCompositionMode());
218+ TestEvent dead_key(XK_dead_circumflex);
219+ SendEvent(dead_key);
220+ EXPECT_TRUE(text_entry->InDeadKeyMode());
221+ EXPECT_TRUE(text_entry->InCompositionMode());
222+
223+ SendEvent(dead_key);
224+ EXPECT_FALSE(text_entry->InCompositionMode());
225+ EXPECT_FALSE(text_entry->InDeadKeyMode());
226+ EXPECT_EQ(text_entry->GetText(), "^");
227+
228+ SendEvent(dead_key);
229+ TestEvent o(XK_o);
230+ SendEvent(o);
231+ EXPECT_FALSE(text_entry->InCompositionMode());
232+ EXPECT_FALSE(text_entry->InDeadKeyMode());
233+
234+ EXPECT_EQ(text_entry->GetText(), "^ô");
235+}
236+
237+TEST_F(TestTextEntry, CompositionDeadKeysMix)
238+{
239+ ASSERT_FALSE(text_entry->InCompositionMode());
240+ TestEvent dead_key1(XK_dead_grave);
241+ SendEvent(dead_key1);
242+ EXPECT_TRUE(text_entry->InDeadKeyMode());
243+ EXPECT_TRUE(text_entry->InCompositionMode());
244+
245+ TestEvent dead_key2(XK_dead_circumflex);
246+ SendEvent(dead_key2);
247+ EXPECT_FALSE(text_entry->InCompositionMode());
248+ EXPECT_FALSE(text_entry->InDeadKeyMode());
249+
250+ EXPECT_EQ(text_entry->GetText(), "");
251+}
252+
253+TEST_F(TestTextEntry, CompositionResultValid)
254+{
255+ std::string composed;
256+ auto result = text_entry->GetCompositionForString("o", composed);
257+
258+ EXPECT_EQ(result, MockTextEntry::CompositionResult::PARTIAL);
259+ EXPECT_TRUE(composed.empty());
260+
261+ result = text_entry->GetCompositionForString("ox", composed);
262+ EXPECT_EQ(result, MockTextEntry::CompositionResult::MATCH);
263+ EXPECT_EQ(composed, "¤");
264+}
265+
266+TEST_F(TestTextEntry, CompositionResultInValid)
267+{
268+ std::string composed;
269+ auto result = text_entry->GetCompositionForString("nux", composed);
270+
271+ EXPECT_EQ(result, MockTextEntry::CompositionResult::NO_MATCH);
272+ EXPECT_TRUE(composed.empty());
273+}
274 #endif
275 }

Subscribers

People subscribed via source and target branches