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