| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/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: | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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]. | |
| 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]. | |
| 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]. | |
| 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]. | |
| 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]. | |
| 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}]. | |
| 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 | |
| 137 TEST_F(CharacterComposerTest, InitialState) { | |
| 138 CharacterComposer character_composer; | |
| 139 EXPECT_TRUE(character_composer.composed_character().empty()); | |
| 140 } | |
| 141 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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. | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| OLD | NEW |