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.
5 #include "ui/base/ime/chromeos/character_composer.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/events/event.h"
11 #include "ui/events/event_constants.h"
12 #include "ui/events/event_utils.h"
13 #include "ui/events/keycodes/dom/dom_code.h"
14 #include "ui/events/keycodes/dom/dom_key.h"
15 #include "ui/events/keycodes/keyboard_code_conversion.h"
16 #include "ui/events/keycodes/keyboard_codes.h"
18 using base::ASCIIToUTF16
;
24 const base::char16 kCombiningGrave
= 0x0300;
25 const base::char16 kCombiningAcute
= 0x0301;
26 const base::char16 kCombiningCircumflex
= 0x0302;
27 const base::char16 kCombiningHorn
= 0x031B;
31 class CharacterComposerTest
: public testing::Test
{
33 // Returns a |KeyEvent| for a dead key press.
34 KeyEvent
* DeadKeyPress(base::char16 combining_character
) const {
36 new KeyEvent(ET_KEY_PRESSED
, VKEY_UNKNOWN
, DomCode::NONE
, EF_NONE
,
37 DomKey::DEAD
, combining_character
, EventTimeForNow());
41 // Expects key is filtered and no character is composed.
42 void ExpectDeadKeyFiltered(base::char16 combining_character
) {
43 scoped_ptr
<KeyEvent
> event(DeadKeyPress(combining_character
));
44 EXPECT_TRUE(character_composer_
.FilterKeyPress(*event
));
45 EXPECT_TRUE(character_composer_
.composed_character().empty());
48 // Expects key is filtered and the given character is composed.
49 void ExpectDeadKeyComposed(base::char16 combining_character
,
50 const base::string16
& expected_character
) {
51 scoped_ptr
<KeyEvent
> event(DeadKeyPress(combining_character
));
52 EXPECT_TRUE(character_composer_
.FilterKeyPress(*event
));
53 EXPECT_EQ(expected_character
, character_composer_
.composed_character());
56 // Returns a |KeyEvent| for a character key press.
57 KeyEvent
* UnicodeKeyPress(KeyboardCode vkey
,
60 base::char16 character
) const {
61 KeyEvent
* event
= new KeyEvent(ET_KEY_PRESSED
, vkey
, code
, flags
,
62 CharacterToDomKey(character
), character
,
67 // Expects key is not filtered and no character is composed.
68 void ExpectUnicodeKeyNotFiltered(KeyboardCode vkey
,
71 base::char16 character
) {
72 scoped_ptr
<KeyEvent
> event(UnicodeKeyPress(vkey
, code
, flags
, character
));
73 EXPECT_FALSE(character_composer_
.FilterKeyPress(*event
));
74 EXPECT_TRUE(character_composer_
.composed_character().empty());
77 // Expects key is filtered and no character is composed.
78 void ExpectUnicodeKeyFiltered(KeyboardCode vkey
,
81 base::char16 character
) {
82 scoped_ptr
<KeyEvent
> event(UnicodeKeyPress(vkey
, code
, flags
, character
));
83 EXPECT_TRUE(character_composer_
.FilterKeyPress(*event
));
84 EXPECT_TRUE(character_composer_
.composed_character().empty());
87 // Expects key is filtered and the given character is composed.
88 void ExpectUnicodeKeyComposed(KeyboardCode vkey
,
91 base::char16 character
,
92 const base::string16
& expected_character
) {
93 scoped_ptr
<KeyEvent
> event(UnicodeKeyPress(vkey
, code
, flags
, character
));
94 EXPECT_TRUE(character_composer_
.FilterKeyPress(*event
));
95 EXPECT_EQ(expected_character
, character_composer_
.composed_character());
98 CharacterComposer character_composer_
;
101 TEST_F(CharacterComposerTest
, InitialState
) {
102 EXPECT_TRUE(character_composer_
.composed_character().empty());
105 TEST_F(CharacterComposerTest
, NormalKeyIsNotFiltered
) {
106 ExpectUnicodeKeyNotFiltered(VKEY_B
, DomCode::KEY_B
, EF_NONE
, 'B');
107 ExpectUnicodeKeyNotFiltered(VKEY_Z
, DomCode::KEY_Z
, EF_NONE
, 'Z');
108 ExpectUnicodeKeyNotFiltered(VKEY_C
, DomCode::KEY_C
, EF_NONE
, 'c');
109 ExpectUnicodeKeyNotFiltered(VKEY_M
, DomCode::KEY_M
, EF_NONE
, 'm');
110 ExpectUnicodeKeyNotFiltered(VKEY_0
, DomCode::DIGIT0
, EF_NONE
, '0');
111 ExpectUnicodeKeyNotFiltered(VKEY_1
, DomCode::DIGIT1
, EF_NONE
, '1');
112 ExpectUnicodeKeyNotFiltered(VKEY_8
, DomCode::DIGIT8
, EF_NONE
, '8');
115 TEST_F(CharacterComposerTest
, PartiallyMatchingSequence
) {
116 // Composition with sequence ['dead acute', '1'] will fail.
117 ExpectDeadKeyFiltered(kCombiningAcute
);
118 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
120 // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
121 ExpectDeadKeyFiltered(kCombiningAcute
);
122 ExpectDeadKeyFiltered(kCombiningCircumflex
);
123 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
126 TEST_F(CharacterComposerTest
, FullyMatchingSequences
) {
127 // LATIN SMALL LETTER A WITH ACUTE
128 ExpectDeadKeyFiltered(kCombiningAcute
);
129 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a',
130 base::string16(1, 0x00E1));
131 // LATIN CAPITAL LETTER A WITH ACUTE
132 ExpectDeadKeyFiltered(kCombiningAcute
);
133 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'A',
134 base::string16(1, 0x00C1));
136 ExpectDeadKeyFiltered(kCombiningGrave
);
137 ExpectDeadKeyComposed(kCombiningGrave
, base::string16(1, 0x0060));
138 // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
139 ExpectDeadKeyFiltered(kCombiningAcute
);
140 ExpectDeadKeyFiltered(kCombiningCircumflex
);
141 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a',
142 base::string16(1, 0x1EA5));
143 // LATIN CAPITAL LETTER U WITH HORN AND GRAVE
144 ExpectDeadKeyFiltered(kCombiningGrave
);
145 ExpectDeadKeyFiltered(kCombiningHorn
);
146 ExpectUnicodeKeyComposed(VKEY_U
, DomCode::KEY_U
, EF_NONE
, 'U',
147 base::string16(1, 0x1EEA));
148 // LATIN CAPITAL LETTER C WITH CEDILLA
149 ExpectDeadKeyFiltered(kCombiningAcute
);
150 ExpectUnicodeKeyComposed(VKEY_C
, DomCode::KEY_C
, EF_NONE
, 'C',
151 base::string16(1, 0x00C7));
152 // LATIN SMALL LETTER C WITH CEDILLA
153 ExpectDeadKeyFiltered(kCombiningAcute
);
154 ExpectUnicodeKeyComposed(VKEY_C
, DomCode::KEY_C
, EF_NONE
, 'c',
155 base::string16(1, 0x00E7));
158 TEST_F(CharacterComposerTest
, FullyMatchingSequencesAfterMatchingFailure
) {
159 // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
160 ExpectDeadKeyFiltered(kCombiningAcute
);
161 ExpectDeadKeyFiltered(kCombiningCircumflex
);
162 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
163 // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
164 ExpectDeadKeyFiltered(kCombiningAcute
);
165 ExpectDeadKeyFiltered(kCombiningCircumflex
);
166 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a',
167 base::string16(1, 0x1EA5));
170 TEST_F(CharacterComposerTest
, ComposedCharacterIsClearedAfterReset
) {
171 ExpectDeadKeyFiltered(kCombiningAcute
);
172 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a',
173 base::string16(1, 0x00E1));
174 character_composer_
.Reset();
175 EXPECT_TRUE(character_composer_
.composed_character().empty());
178 TEST_F(CharacterComposerTest
, CompositionStateIsClearedAfterReset
) {
179 // Even though sequence ['dead acute', 'a'] will compose 'a with acute',
180 // no character is composed here because of reset.
181 ExpectDeadKeyFiltered(kCombiningAcute
);
182 character_composer_
.Reset();
183 ExpectUnicodeKeyNotFiltered(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a');
186 TEST_F(CharacterComposerTest
, KeySequenceCompositionPreedit
) {
187 // LATIN SMALL LETTER A WITH ACUTE
188 // preedit_string() is always empty in key sequence composition mode.
189 ExpectDeadKeyFiltered(kCombiningAcute
);
190 EXPECT_TRUE(character_composer_
.preedit_string().empty());
191 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a',
192 base::string16(1, 0x00E1));
193 EXPECT_TRUE(character_composer_
.preedit_string().empty());
196 // Verify the structure of the primary |TreeComposeChecker| table.
197 TEST_F(CharacterComposerTest
, MainTableIsCorrectlyOrdered
) {
198 // This file is included here intentionally, instead of the top of the file,
199 // because including this file at the top of the file will define a
200 // global constant and contaminate the global namespace.
201 #include "ui/base/ime/chromeos/character_composer_data.h"
202 const int kTypes
= 2;
204 // Record the subtree locations and check subtable sizes.
205 std::vector
<uint16_t> subtrees
;
207 while (index
< kCompositions
.tree_entries
) {
208 // Record the start of the subtree.
210 subtrees
.push_back(index
);
211 for (int t
= 0; t
< kTypes
; ++t
) {
212 // Skip the internal table and verify the next index is within the data.
213 index
+= 1 + 2 * kCompositions
.tree
[index
];
214 EXPECT_GT(kCompositions
.tree_entries
, index
);
215 // Skip the leaf table and verify that the next index is not past the
217 index
+= 1 + 2 * kCompositions
.tree
[index
];
218 EXPECT_GE(kCompositions
.tree_entries
, index
);
221 // We should end up at the end of the data.
222 EXPECT_EQ(kCompositions
.tree_entries
, index
);
224 // Check subtable structure.
226 while (index
< kCompositions
.tree_entries
) {
228 for (int t
= 0; t
< kTypes
; ++t
) {
229 // Check the internal subtable.
230 uint16_t previous_key
= 0;
231 uint16_t size
= kCompositions
.tree
[index
++];
232 for (uint16_t i
= 0; i
< size
; ++i
) {
233 // Verify that the subtable is sorted.
234 uint16_t key
= kCompositions
.tree
[index
];
235 uint16_t value
= kCompositions
.tree
[index
+ 1];
237 EXPECT_LT(previous_key
, key
) << index
;
239 // Verify that the internal link is valid.
240 const auto it
= std::find(subtrees
.begin(), subtrees
.end(), value
);
241 EXPECT_FALSE(subtrees
.end() == it
) << index
;
244 // Check the leaf subtable.
246 size
= kCompositions
.tree
[index
++];
247 for (uint16_t i
= 0; i
< size
; ++i
) {
248 // Verify that the subtable is sorted.
249 uint16_t key
= kCompositions
.tree
[index
];
251 EXPECT_LT(previous_key
, key
) << index
;
259 TEST_F(CharacterComposerTest
, HexadecimalComposition
) {
260 // HIRAGANA LETTER A (U+3042)
261 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
262 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 'U');
263 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
264 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, EF_NONE
, '0');
265 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, EF_NONE
, '4');
266 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
267 ExpectUnicodeKeyComposed(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ',
268 base::string16(1, 0x3042));
269 // MUSICAL KEYBOARD (U+1F3B9)
270 const base::char16 kMusicalKeyboard
[] = {0xd83c, 0xdfb9};
271 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
272 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 'U');
273 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, EF_NONE
, '1');
274 ExpectUnicodeKeyFiltered(VKEY_F
, DomCode::KEY_F
, EF_NONE
, 'f');
275 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
276 ExpectUnicodeKeyFiltered(VKEY_B
, DomCode::KEY_B
, EF_NONE
, 'b');
277 ExpectUnicodeKeyFiltered(VKEY_9
, DomCode::DIGIT9
, EF_NONE
, '9');
278 ExpectUnicodeKeyComposed(
279 VKEY_RETURN
, DomCode::ENTER
, EF_NONE
, '\r',
280 base::string16(kMusicalKeyboard
,
281 kMusicalKeyboard
+ arraysize(kMusicalKeyboard
)));
284 TEST_F(CharacterComposerTest
, HexadecimalCompositionPreedit
) {
285 // HIRAGANA LETTER A (U+3042)
286 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
287 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 'U');
288 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_
.preedit_string());
289 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, 0, '3');
290 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_
.preedit_string());
291 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, 0, '0');
292 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_
.preedit_string());
293 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, 0, '4');
294 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_
.preedit_string());
295 ExpectUnicodeKeyFiltered(VKEY_A
, DomCode::KEY_A
, 0, 'a');
296 EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer_
.preedit_string());
297 ExpectUnicodeKeyFiltered(VKEY_BACK
, DomCode::BACKSPACE
, EF_NONE
, '\b');
298 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_
.preedit_string());
299 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
300 ExpectUnicodeKeyComposed(VKEY_RETURN
, DomCode::ENTER
, EF_NONE
,
302 base::string16(1, 0x3042));
303 EXPECT_EQ(ASCIIToUTF16(""), character_composer_
.preedit_string());
305 // Sequence with an ignored character ('x') and Escape.
306 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
307 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 'U');
308 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_
.preedit_string());
309 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, 0, '3');
310 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_
.preedit_string());
311 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, 0, '0');
312 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_
.preedit_string());
313 ExpectUnicodeKeyFiltered(VKEY_X
, DomCode::KEY_X
, 0, 'x');
314 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_
.preedit_string());
315 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, 0, '4');
316 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_
.preedit_string());
317 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, 0, '2');
318 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_
.preedit_string());
319 ExpectUnicodeKeyFiltered(VKEY_ESCAPE
, DomCode::ESCAPE
, EF_NONE
, 0x1B);
320 EXPECT_EQ(ASCIIToUTF16(""), character_composer_
.preedit_string());
323 TEST_F(CharacterComposerTest
, HexadecimalCompositionWithNonHexKey
) {
324 // Sequence [Ctrl+Shift+U, x, space] does not compose a character.
325 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
326 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
327 ExpectUnicodeKeyFiltered(VKEY_X
, DomCode::KEY_X
, 0, 'x');
328 ExpectUnicodeKeyFiltered(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ');
329 EXPECT_TRUE(character_composer_
.composed_character().empty());
331 // HIRAGANA LETTER A (U+3042) with a sequence [3, 0, x, 4, 2].
332 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
333 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
334 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
335 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, EF_NONE
, '0');
336 ExpectUnicodeKeyFiltered(VKEY_X
, DomCode::KEY_X
, EF_NONE
, 'x');
337 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, EF_NONE
, '4');
338 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
339 ExpectUnicodeKeyComposed(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ',
340 base::string16(1, 0x3042));
343 TEST_F(CharacterComposerTest
, HexadecimalCompositionWithAdditionalModifiers
) {
345 // HIRAGANA LETTER A (U+3042)
346 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
347 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
| EF_ALT_DOWN
, 0x15);
348 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
349 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, EF_NONE
, '0');
350 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, EF_NONE
, '4');
351 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
352 ExpectUnicodeKeyComposed(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ',
353 base::string16(1, 0x3042));
355 // Ctrl+Shift+u (CapsLock enabled)
356 ExpectUnicodeKeyNotFiltered(
357 VKEY_U
, DomCode::KEY_U
,
358 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
| EF_CAPS_LOCK_DOWN
, 'u');
361 TEST_F(CharacterComposerTest
, CancelHexadecimalComposition
) {
362 // Cancel composition with ESC.
363 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
364 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
365 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
366 ExpectUnicodeKeyFiltered(VKEY_ESCAPE
, DomCode::ESCAPE
, EF_NONE
, 0x1B);
368 // Now we can start composition again since the last composition was
370 // HIRAGANA LETTER A (U+3042)
371 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
372 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
373 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
374 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, EF_NONE
, '0');
375 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, EF_NONE
, '4');
376 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
377 ExpectUnicodeKeyComposed(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ',
378 base::string16(1, 0x3042));
381 TEST_F(CharacterComposerTest
, HexadecimalCompositionWithBackspace
) {
382 // HIRAGANA LETTER A (U+3042)
383 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
384 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
385 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, 0, '3');
386 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, 0, '0');
387 ExpectUnicodeKeyFiltered(VKEY_F
, DomCode::KEY_F
, 0, 'f');
388 ExpectUnicodeKeyFiltered(VKEY_BACK
, DomCode::BACKSPACE
, EF_NONE
, '\b');
389 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, EF_NONE
, '4');
390 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
391 ExpectUnicodeKeyComposed(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ',
392 base::string16(1, 0x3042));
395 TEST_F(CharacterComposerTest
, CancelHexadecimalCompositionWithBackspace
) {
396 // Backspace just after Ctrl+Shift+U.
397 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
398 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
399 ExpectUnicodeKeyFiltered(VKEY_BACK
, DomCode::BACKSPACE
, EF_NONE
, '\b');
400 ExpectUnicodeKeyNotFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
402 // Backspace twice after Ctrl+Shift+U and 3.
403 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
404 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
405 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, 0, '3');
406 ExpectUnicodeKeyFiltered(VKEY_BACK
, DomCode::BACKSPACE
, EF_NONE
, '\b');
407 ExpectUnicodeKeyFiltered(VKEY_BACK
, DomCode::BACKSPACE
, EF_NONE
, '\b');
408 ExpectUnicodeKeyNotFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
411 TEST_F(CharacterComposerTest
,
412 HexadecimalCompositionPreeditWithModifierPressed
) {
413 // This test case supposes X Window System uses 101 keyboard layout.
414 const int kControlShift
= EF_CONTROL_DOWN
| EF_SHIFT_DOWN
;
415 // HIRAGANA LETTER A (U+3042)
416 ExpectUnicodeKeyFiltered(ui::VKEY_U
, DomCode::KEY_U
, kControlShift
, 0x15);
417 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_
.preedit_string());
418 ExpectUnicodeKeyFiltered(ui::VKEY_3
, DomCode::DIGIT3
, kControlShift
, '#');
419 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_
.preedit_string());
420 ExpectUnicodeKeyFiltered(ui::VKEY_0
, DomCode::DIGIT0
, kControlShift
, ')');
421 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_
.preedit_string());
422 ExpectUnicodeKeyFiltered(ui::VKEY_4
, DomCode::DIGIT4
, kControlShift
, '$');
423 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_
.preedit_string());
424 ExpectUnicodeKeyFiltered(ui::VKEY_A
, DomCode::KEY_A
, kControlShift
, 0x01);
425 EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer_
.preedit_string());
426 ExpectUnicodeKeyFiltered(ui::VKEY_BACK
, DomCode::BACKSPACE
, kControlShift
,
428 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_
.preedit_string());
429 ExpectUnicodeKeyFiltered(ui::VKEY_2
, DomCode::DIGIT2
, kControlShift
, 0);
430 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_
.preedit_string());
431 ExpectUnicodeKeyComposed(VKEY_RETURN
, DomCode::ENTER
, kControlShift
,
433 base::string16(1, 0x3042));
434 EXPECT_EQ(ASCIIToUTF16(""), character_composer_
.preedit_string());
436 // Sequence with an ignored character (control + shift + 'x') and Escape.
437 ExpectUnicodeKeyFiltered(ui::VKEY_U
, DomCode::KEY_U
, kControlShift
, 'U');
438 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_
.preedit_string());
439 ExpectUnicodeKeyFiltered(ui::VKEY_3
, DomCode::DIGIT3
, kControlShift
, '#');
440 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_
.preedit_string());
441 ExpectUnicodeKeyFiltered(ui::VKEY_0
, DomCode::DIGIT0
, kControlShift
, ')');
442 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_
.preedit_string());
443 ExpectUnicodeKeyFiltered(ui::VKEY_X
, DomCode::KEY_X
, kControlShift
, 'X');
444 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_
.preedit_string());
445 ExpectUnicodeKeyFiltered(ui::VKEY_4
, DomCode::DIGIT4
, kControlShift
, '$');
446 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_
.preedit_string());
447 ExpectUnicodeKeyFiltered(ui::VKEY_2
, DomCode::DIGIT2
, kControlShift
, 0);
448 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_
.preedit_string());
449 ExpectUnicodeKeyFiltered(ui::VKEY_ESCAPE
, DomCode::ESCAPE
, kControlShift
,
451 EXPECT_EQ(ASCIIToUTF16(""), character_composer_
.preedit_string());
454 TEST_F(CharacterComposerTest
, InvalidHexadecimalSequence
) {
456 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
457 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
458 for (int i
= 0; i
< 8; ++i
)
459 ExpectUnicodeKeyFiltered(VKEY_F
, DomCode::KEY_F
, 0, 'f');
460 ExpectUnicodeKeyFiltered(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ');
462 // U+0000 (Actually, this is a valid unicode character, but we don't
463 // compose a string with a character '\0')
464 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
465 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
466 for (int i
= 0; i
< 4; ++i
)
467 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, 0, '0');
468 ExpectUnicodeKeyFiltered(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ');
471 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
472 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
473 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
474 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, 0, '0');
475 for (int i
= 0; i
< 4; ++i
)
476 ExpectUnicodeKeyFiltered(VKEY_F
, DomCode::KEY_F
, 0, 'f');
477 ExpectUnicodeKeyFiltered(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ');
480 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
481 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
482 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
483 ExpectUnicodeKeyFiltered(VKEY_1
, DomCode::DIGIT1
, 0, '1');
484 for (int i
= 0; i
< 4; ++i
)
485 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, 0, '0');
486 ExpectUnicodeKeyFiltered(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ');
489 TEST_F(CharacterComposerTest
, HexadecimalSequenceAndDeadKey
) {
490 // LATIN SMALL LETTER A WITH ACUTE
491 ExpectDeadKeyFiltered(kCombiningAcute
);
492 ExpectUnicodeKeyComposed(VKEY_A
, DomCode::KEY_A
, EF_NONE
, 'a',
493 base::string16(1, 0x00E1));
494 // HIRAGANA LETTER A (U+3042) with dead_acute ignored.
495 ExpectUnicodeKeyFiltered(VKEY_U
, DomCode::KEY_U
,
496 EF_SHIFT_DOWN
| EF_CONTROL_DOWN
, 0x15);
497 ExpectUnicodeKeyFiltered(VKEY_3
, DomCode::DIGIT3
, EF_NONE
, '3');
498 ExpectUnicodeKeyFiltered(VKEY_0
, DomCode::DIGIT0
, EF_NONE
, '0');
499 ExpectDeadKeyFiltered(kCombiningAcute
);
500 ExpectUnicodeKeyFiltered(VKEY_4
, DomCode::DIGIT4
, EF_NONE
, '4');
501 ExpectUnicodeKeyFiltered(VKEY_2
, DomCode::DIGIT2
, EF_NONE
, '2');
502 ExpectUnicodeKeyComposed(VKEY_SPACE
, DomCode::SPACE
, EF_NONE
, ' ',
503 base::string16(1, 0x3042));