1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/base/ime/chromeos/character_composer.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/gtk+/gdk/gdkkeysyms.h"
10 #include "ui/base/glib/glib_integers.h"
11 #include "ui/events/event_constants.h"
12
13 namespace ui {
14
15 class CharacterComposerTest : public testing::Test {
16 protected:
FilterKeyPress(CharacterComposer * character_composer,uint key,uint keycode,int flags)17 bool FilterKeyPress(CharacterComposer* character_composer,
18 uint key,
19 uint keycode,
20 int flags) {
21 return character_composer->FilterKeyPressInternal(key, keycode, flags);
22 }
23
24 // Expects key is not filtered and no character is composed.
ExpectKeyNotFilteredWithKeyCode(CharacterComposer * character_composer,uint key,uint keycode,int flags)25 void ExpectKeyNotFilteredWithKeyCode(CharacterComposer* character_composer,
26 uint key,
27 uint keycode,
28 int flags) {
29 EXPECT_FALSE(character_composer->FilterKeyPressInternal(key, keycode,
30 flags));
31 EXPECT_TRUE(character_composer->composed_character().empty());
32 }
33
34 // Expects key is filtered and no character is composed.
ExpectKeyFilteredWithKeycode(CharacterComposer * character_composer,uint key,uint keycode,int flags)35 void ExpectKeyFilteredWithKeycode(CharacterComposer* character_composer,
36 uint key,
37 uint keycode,
38 int flags) {
39 EXPECT_TRUE(character_composer->FilterKeyPressInternal(key, keycode,
40 flags));
41 EXPECT_TRUE(character_composer->composed_character().empty());
42 }
43
44 // Expects key is not filtered and no character is composed.
ExpectKeyNotFiltered(CharacterComposer * character_composer,uint key,int flags)45 void ExpectKeyNotFiltered(CharacterComposer* character_composer,
46 uint key,
47 int flags) {
48 ExpectKeyNotFilteredWithKeyCode(character_composer, key, 0, flags);
49 }
50
51 // Expects key is filtered and no character is composed.
ExpectKeyFiltered(CharacterComposer * character_composer,uint key,int flags)52 void ExpectKeyFiltered(CharacterComposer* character_composer,
53 uint key,
54 int flags) {
55 ExpectKeyFilteredWithKeycode(character_composer, key, 0, flags);
56 }
57
58 // Expects |expected_character| is composed after sequence [key1, key2].
ExpectCharacterComposed(CharacterComposer * character_composer,uint key1,uint key2,int flags,const string16 & expected_character)59 void ExpectCharacterComposed(CharacterComposer* character_composer,
60 uint key1,
61 uint key2,
62 int flags,
63 const string16& expected_character) {
64 ExpectKeyFiltered(character_composer, key1, flags);
65 EXPECT_TRUE(character_composer->FilterKeyPressInternal(key2, 0, flags));
66 EXPECT_EQ(expected_character, character_composer->composed_character());
67 }
68
69 // Expects |expected_character| is composed after sequence [key1, key2, key3].
ExpectCharacterComposed(CharacterComposer * character_composer,uint key1,uint key2,uint key3,int flags,const string16 & expected_character)70 void ExpectCharacterComposed(CharacterComposer* character_composer,
71 uint key1,
72 uint key2,
73 uint key3,
74 int flags,
75 const string16& expected_character) {
76 ExpectKeyFiltered(character_composer, key1, flags);
77 ExpectCharacterComposed(character_composer, key2, key3, flags,
78 expected_character);
79 }
80
81 // Expects |expected_character| is composed after sequence [key1, key2, key3,
82 // key 4].
ExpectCharacterComposed(CharacterComposer * character_composer,uint key1,uint key2,uint key3,uint key4,int flags,const string16 & expected_character)83 void ExpectCharacterComposed(CharacterComposer* character_composer,
84 uint key1,
85 uint key2,
86 uint key3,
87 uint key4,
88 int flags,
89 const string16& expected_character) {
90 ExpectKeyFiltered(character_composer, key1, flags);
91 ExpectCharacterComposed(character_composer, key2, key3, key4, flags,
92 expected_character);
93 }
94
95 // Expects |expected_character| is composed after sequence [key1, key2, key3,
96 // key 4, key5].
ExpectCharacterComposed(CharacterComposer * character_composer,uint key1,uint key2,uint key3,uint key4,uint key5,int flags,const string16 & expected_character)97 void ExpectCharacterComposed(CharacterComposer* character_composer,
98 uint key1,
99 uint key2,
100 uint key3,
101 uint key4,
102 uint key5,
103 int flags,
104 const string16& expected_character) {
105 ExpectKeyFiltered(character_composer, key1, flags);
106 ExpectCharacterComposed(character_composer, key2, key3, key4, key5, flags,
107 expected_character);
108 }
109
110 // Expects |expected_character| is composed after sequence [key1, key2, key3,
111 // key 4, key5, key6].
ExpectCharacterComposed(CharacterComposer * character_composer,uint key1,uint key2,uint key3,uint key4,uint key5,uint key6,int flags,const string16 & expected_character)112 void ExpectCharacterComposed(CharacterComposer* character_composer,
113 uint key1,
114 uint key2,
115 uint key3,
116 uint key4,
117 uint key5,
118 uint key6,
119 int flags,
120 const string16& expected_character) {
121 ExpectKeyFiltered(character_composer, key1, flags);
122 ExpectCharacterComposed(character_composer, key2, key3, key4, key5, key6,
123 flags, expected_character);
124 }
125
126 // Expects |expected_character| is composed after sequence [{key1, keycode1}].
ExpectCharacterComposedWithKeyCode(CharacterComposer * character_composer,uint key1,uint keycode1,int flags,const string16 & expected_character)127 void ExpectCharacterComposedWithKeyCode(CharacterComposer* character_composer,
128 uint key1, uint keycode1,
129 int flags,
130 const string16& expected_character) {
131 EXPECT_TRUE(character_composer->FilterKeyPressInternal(key1, keycode1,
132 flags));
133 EXPECT_EQ(expected_character, character_composer->composed_character());
134 }
135 };
136
TEST_F(CharacterComposerTest,InitialState)137 TEST_F(CharacterComposerTest, InitialState) {
138 CharacterComposer character_composer;
139 EXPECT_TRUE(character_composer.composed_character().empty());
140 }
141
TEST_F(CharacterComposerTest,NormalKeyIsNotFiltered)142 TEST_F(CharacterComposerTest, NormalKeyIsNotFiltered) {
143 CharacterComposer character_composer;
144 ExpectKeyNotFiltered(&character_composer, GDK_KEY_B, 0);
145 ExpectKeyNotFiltered(&character_composer, GDK_KEY_Z, 0);
146 ExpectKeyNotFiltered(&character_composer, GDK_KEY_c, 0);
147 ExpectKeyNotFiltered(&character_composer, GDK_KEY_m, 0);
148 ExpectKeyNotFiltered(&character_composer, GDK_KEY_0, 0);
149 ExpectKeyNotFiltered(&character_composer, GDK_KEY_1, 0);
150 ExpectKeyNotFiltered(&character_composer, GDK_KEY_8, 0);
151 }
152
TEST_F(CharacterComposerTest,PartiallyMatchingSequence)153 TEST_F(CharacterComposerTest, PartiallyMatchingSequence) {
154 CharacterComposer character_composer;
155
156 // Composition with sequence ['dead acute', '1'] will fail.
157 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
158 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
159
160 // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
161 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
162 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex, 0);
163 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
164 }
165
TEST_F(CharacterComposerTest,FullyMatchingSequences)166 TEST_F(CharacterComposerTest, FullyMatchingSequences) {
167 CharacterComposer character_composer;
168 // LATIN SMALL LETTER A WITH ACUTE
169 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0,
170 string16(1, 0x00E1));
171 // LATIN CAPITAL LETTER A WITH ACUTE
172 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_A, 0,
173 string16(1, 0x00C1));
174 // GRAVE ACCENT
175 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_grave,
176 GDK_KEY_dead_grave, 0, string16(1, 0x0060));
177 // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
178 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute,
179 GDK_KEY_dead_circumflex, GDK_KEY_a, 0,
180 string16(1, 0x1EA5));
181 // LATIN CAPITAL LETTER U WITH HORN AND GRAVE
182 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_grave,
183 GDK_KEY_dead_horn, GDK_KEY_U, 0, string16(1, 0x1EEA));
184 // LATIN CAPITAL LETTER C WITH CEDILLA
185 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_C, 0,
186 string16(1, 0x00C7));
187 // LATIN SMALL LETTER C WITH CEDILLA
188 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_c, 0,
189 string16(1, 0x00E7));
190 }
191
TEST_F(CharacterComposerTest,FullyMatchingSequencesAfterMatchingFailure)192 TEST_F(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) {
193 CharacterComposer character_composer;
194 // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
195 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
196 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex, 0);
197 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
198 // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
199 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute,
200 GDK_KEY_dead_circumflex, GDK_KEY_a, 0,
201 string16(1, 0x1EA5));
202 }
203
TEST_F(CharacterComposerTest,ComposedCharacterIsClearedAfterReset)204 TEST_F(CharacterComposerTest, ComposedCharacterIsClearedAfterReset) {
205 CharacterComposer character_composer;
206 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0,
207 string16(1, 0x00E1));
208 character_composer.Reset();
209 EXPECT_TRUE(character_composer.composed_character().empty());
210 }
211
TEST_F(CharacterComposerTest,CompositionStateIsClearedAfterReset)212 TEST_F(CharacterComposerTest, CompositionStateIsClearedAfterReset) {
213 CharacterComposer character_composer;
214 // Even though sequence ['dead acute', 'a'] will compose 'a with acute',
215 // no character is composed here because of reset.
216 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
217 character_composer.Reset();
218 ExpectKeyNotFiltered(&character_composer, GDK_KEY_a, 0);
219 }
220
TEST_F(CharacterComposerTest,KeySequenceCompositionPreedit)221 TEST_F(CharacterComposerTest, KeySequenceCompositionPreedit) {
222 CharacterComposer character_composer;
223 // LATIN SMALL LETTER A WITH ACUTE
224 // preedit_string() is always empty in key sequence composition mode.
225 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
226 EXPECT_TRUE(character_composer.preedit_string().empty());
227 EXPECT_TRUE(FilterKeyPress(&character_composer, GDK_KEY_a, 0, 0));
228 EXPECT_EQ(string16(1, 0x00E1), character_composer.composed_character());
229 EXPECT_TRUE(character_composer.preedit_string().empty());
230 }
231
232 // ComposeCheckerWithCompactTable in character_composer.cc is depending on the
233 // assumption that the data in gtkimcontextsimpleseqs.h is correctly ordered.
TEST_F(CharacterComposerTest,MainTableIsCorrectlyOrdered)234 TEST_F(CharacterComposerTest, MainTableIsCorrectlyOrdered) {
235 // This file is included here intentionally, instead of the top of the file,
236 // because including this file at the top of the file will define a
237 // global constant and contaminate the global namespace.
238 #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h"
239 const int index_size = 26;
240 const int index_stride = 6;
241
242 // Verify that the index is correctly ordered
243 for (int i = 1; i < index_size; ++i) {
244 const int index_key_prev = gtk_compose_seqs_compact[(i - 1)*index_stride];
245 const int index_key = gtk_compose_seqs_compact[i*index_stride];
246 EXPECT_TRUE(index_key > index_key_prev);
247 }
248
249 // Verify that the sequenes are correctly ordered
250 struct {
251 int operator()(const uint16* l, const uint16* r, int length) const{
252 for (int i = 0; i < length; ++i) {
253 if (l[i] > r[i])
254 return 1;
255 if (l[i] < r[i])
256 return -1;
257 }
258 return 0;
259 }
260 } compare_sequence;
261
262 for (int i = 0; i < index_size; ++i) {
263 for (int length = 1; length < index_stride - 1; ++length) {
264 const int index_begin = gtk_compose_seqs_compact[i*index_stride + length];
265 const int index_end =
266 gtk_compose_seqs_compact[i*index_stride + length + 1];
267 const int stride = length + 1;
268 for (int index = index_begin + stride; index < index_end;
269 index += stride) {
270 const uint16* sequence = >k_compose_seqs_compact[index];
271 const uint16* sequence_prev = sequence - stride;
272 EXPECT_EQ(1, compare_sequence(sequence, sequence_prev, length));
273 }
274 }
275 }
276 }
277
TEST_F(CharacterComposerTest,HexadecimalComposition)278 TEST_F(CharacterComposerTest, HexadecimalComposition) {
279 CharacterComposer character_composer;
280 // HIRAGANA LETTER A (U+3042)
281 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
282 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
283 ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4,
284 GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042));
285 // MUSICAL KEYBOARD (U+1F3B9)
286 const char16 kMusicalKeyboard[] = {0xd83c, 0xdfb9};
287 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
288 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
289 ExpectCharacterComposed(&character_composer, GDK_KEY_1, GDK_KEY_f, GDK_KEY_3,
290 GDK_KEY_b, GDK_KEY_9, GDK_KEY_Return, 0,
291 string16(kMusicalKeyboard,
292 kMusicalKeyboard +
293 arraysize(kMusicalKeyboard)));
294 }
295
TEST_F(CharacterComposerTest,HexadecimalCompositionPreedit)296 TEST_F(CharacterComposerTest, HexadecimalCompositionPreedit) {
297 CharacterComposer character_composer;
298 // HIRAGANA LETTER A (U+3042)
299 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
300 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
301 EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
302 ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
303 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
304 ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
305 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
306 ExpectKeyFiltered(&character_composer, GDK_KEY_4, 0);
307 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
308 ExpectKeyFiltered(&character_composer, GDK_KEY_a, 0);
309 EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer.preedit_string());
310 ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
311 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
312 ExpectCharacterComposed(&character_composer, GDK_KEY_2, GDK_KEY_Return, 0,
313 string16(1, 0x3042));
314 EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
315
316 // Sequence with an ignored character ('x') and Escape.
317 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
318 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
319 EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
320 ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
321 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
322 ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
323 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
324 ExpectKeyFiltered(&character_composer, GDK_KEY_x, 0);
325 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
326 ExpectKeyFiltered(&character_composer, GDK_KEY_4, 0);
327 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
328 ExpectKeyFiltered(&character_composer, GDK_KEY_2, 0);
329 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string());
330 ExpectKeyFiltered(&character_composer, GDK_KEY_Escape, 0);
331 EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
332 }
333
TEST_F(CharacterComposerTest,HexadecimalCompositionWithNonHexKey)334 TEST_F(CharacterComposerTest, HexadecimalCompositionWithNonHexKey) {
335 CharacterComposer character_composer;
336
337 // Sequence [Ctrl+Shift+U, x, space] does not compose a character.
338 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
339 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
340 ExpectKeyFiltered(&character_composer, GDK_KEY_x, 0);
341 ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0);
342 EXPECT_TRUE(character_composer.composed_character().empty());
343
344 // HIRAGANA LETTER A (U+3042) with a sequence [3, 0, x, 4, 2].
345 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
346 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
347 ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_x,
348 GDK_KEY_4, GDK_KEY_2, GDK_KEY_space, 0,
349 string16(1, 0x3042));
350 }
351
TEST_F(CharacterComposerTest,HexadecimalCompositionWithAdditionalModifiers)352 TEST_F(CharacterComposerTest, HexadecimalCompositionWithAdditionalModifiers) {
353 CharacterComposer character_composer;
354
355 // Ctrl+Shift+Alt+U
356 // HIRAGANA LETTER A (U+3042)
357 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
358 EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN);
359 ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4,
360 GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042));
361
362 // Ctrl+Shift+u (CapsLock enabled)
363 ExpectKeyNotFiltered(&character_composer, GDK_KEY_u,
364 EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_CAPS_LOCK_DOWN);
365 }
366
TEST_F(CharacterComposerTest,CancelHexadecimalComposition)367 TEST_F(CharacterComposerTest, CancelHexadecimalComposition) {
368 CharacterComposer character_composer;
369 // Cancel composition with ESC.
370 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
371 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
372 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
373 ExpectKeyFiltered(&character_composer, GDK_KEY_Escape, 0);
374
375 // Now we can start composition again since the last composition was
376 // cancelled.
377 // HIRAGANA LETTER A (U+3042)
378 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
379 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
380 ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4,
381 GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042));
382 }
383
TEST_F(CharacterComposerTest,HexadecimalCompositionWithBackspace)384 TEST_F(CharacterComposerTest, HexadecimalCompositionWithBackspace) {
385 CharacterComposer character_composer;
386 // HIRAGANA LETTER A (U+3042)
387 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
388 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
389 ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
390 ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
391 ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0);
392 ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
393 ExpectCharacterComposed(&character_composer, GDK_KEY_4, GDK_KEY_2,
394 GDK_KEY_space, 0, string16(1, 0x3042));
395 }
396
TEST_F(CharacterComposerTest,CancelHexadecimalCompositionWithBackspace)397 TEST_F(CharacterComposerTest, CancelHexadecimalCompositionWithBackspace) {
398 CharacterComposer character_composer;
399
400 // Backspace just after Ctrl+Shift+U.
401 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
402 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
403 ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
404 ExpectKeyNotFiltered(&character_composer, GDK_KEY_3, 0);
405
406 // Backspace twice after Ctrl+Shift+U and 3.
407 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
408 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
409 ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
410 ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
411 ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
412 ExpectKeyNotFiltered(&character_composer, GDK_KEY_3, 0);
413 }
414
TEST_F(CharacterComposerTest,HexadecimalCompositionPreeditWithModifierPressed)415 TEST_F(CharacterComposerTest, HexadecimalCompositionPreeditWithModifierPressed)
416 {
417 // This test case supposes X Window System uses 101 keyboard layout.
418 CharacterComposer character_composer;
419 const int control_shift = EF_CONTROL_DOWN | EF_SHIFT_DOWN;
420 // HIRAGANA LETTER A (U+3042)
421 ExpectKeyFilteredWithKeycode(&character_composer,
422 GDK_KEY_U, 30, control_shift);
423 EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
424 ExpectKeyFilteredWithKeycode(&character_composer,
425 GDK_KEY_numbersign, 12, control_shift);
426 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
427 ExpectKeyFilteredWithKeycode(&character_composer,
428 GDK_KEY_parenright, 19, control_shift);
429 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
430 ExpectKeyFilteredWithKeycode(&character_composer,
431 GDK_KEY_dollar, 13, control_shift);
432 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
433 ExpectKeyFilteredWithKeycode(&character_composer,
434 GDK_KEY_A, 38, control_shift);
435 EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer.preedit_string());
436 ExpectKeyFilteredWithKeycode(&character_composer,
437 GDK_KEY_BackSpace, 22, control_shift);
438 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
439 ExpectKeyFilteredWithKeycode(&character_composer,
440 GDK_KEY_at, 11, control_shift);
441 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string());
442 ExpectCharacterComposedWithKeyCode(&character_composer,
443 GDK_KEY_Return, 36,
444 control_shift,
445 string16(1, 0x3042));
446 EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
447
448 // Sequence with an ignored character (control + shift + 'x') and Escape.
449 ExpectKeyFilteredWithKeycode(&character_composer,
450 GDK_KEY_U, 30, control_shift);
451 EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
452 ExpectKeyFilteredWithKeycode(&character_composer,
453 GDK_KEY_numbersign, 12, control_shift);
454 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
455 ExpectKeyFilteredWithKeycode(&character_composer,
456 GDK_KEY_parenright, 19, control_shift);
457 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
458 ExpectKeyFilteredWithKeycode(&character_composer,
459 GDK_KEY_X, 53, control_shift);
460 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
461 ExpectKeyFilteredWithKeycode(&character_composer,
462 GDK_KEY_dollar, 13, control_shift);
463 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
464 ExpectKeyFilteredWithKeycode(&character_composer,
465 GDK_KEY_at, 11, control_shift);
466 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string());
467 ExpectKeyFilteredWithKeycode(&character_composer,
468 GDK_KEY_Escape, 9, control_shift);
469 EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
470 }
471
TEST_F(CharacterComposerTest,InvalidHexadecimalSequence)472 TEST_F(CharacterComposerTest, InvalidHexadecimalSequence) {
473 CharacterComposer character_composer;
474 // U+FFFFFFFF
475 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
476 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
477 for (int i = 0; i < 8; ++i)
478 ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0);
479 ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0);
480
481 // U+0000 (Actually, this is a valid unicode character, but we don't
482 // compose a string with a character '\0')
483 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
484 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
485 for (int i = 0; i < 4; ++i)
486 ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
487 ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0);
488
489 // U+10FFFF
490 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
491 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
492 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
493 ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
494 for (int i = 0; i < 4; ++i)
495 ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0);
496 ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0);
497
498 // U+110000
499 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
500 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
501 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
502 ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
503 for (int i = 0; i < 4; ++i)
504 ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
505 ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0);
506 }
507
TEST_F(CharacterComposerTest,HexadecimalSequenceAndDeadKey)508 TEST_F(CharacterComposerTest, HexadecimalSequenceAndDeadKey) {
509 CharacterComposer character_composer;
510 // LATIN SMALL LETTER A WITH ACUTE
511 ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0,
512 string16(1, 0x00E1));
513 // HIRAGANA LETTER A (U+3042) with dead_acute ignored.
514 ExpectKeyFiltered(&character_composer, GDK_KEY_U,
515 EF_SHIFT_DOWN | EF_CONTROL_DOWN);
516 ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0,
517 GDK_KEY_dead_acute, GDK_KEY_4, GDK_KEY_2,
518 GDK_KEY_space, 0, string16(1, 0x3042));
519 // LATIN CAPITAL LETTER U WITH ACUTE while 'U' is pressed with Ctrl+Shift.
520 ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
521 EXPECT_TRUE(FilterKeyPress(&character_composer, GDK_KEY_U, 0,
522 EF_SHIFT_DOWN | EF_CONTROL_DOWN));
523 EXPECT_EQ(string16(1, 0x00DA), character_composer.composed_character());
524 }
525
TEST_F(CharacterComposerTest,BlacklistedKeyeventsTest)526 TEST_F(CharacterComposerTest, BlacklistedKeyeventsTest) {
527 CharacterComposer character_composer;
528 EXPECT_TRUE(FilterKeyPress(&character_composer, GDK_KEY_dead_acute, 0, 0));
529 EXPECT_FALSE(FilterKeyPress(&character_composer, GDK_KEY_s, 0, 0));
530 ASSERT_EQ(1U, character_composer.composed_character().size());
531 EXPECT_EQ(GDK_KEY_apostrophe, character_composer.composed_character().at(0));
532 }
533
534 } // namespace ui
535