| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/base/ime/character_composer.h" |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/gtk+/gdk/gdkkeysyms.h" |
| #include "ui/base/glib/glib_integers.h" |
| #include "ui/events/event_constants.h" |
| |
| namespace ui { |
| |
| namespace { |
| |
| // Expects key is not filtered and no character is composed. |
| void ExpectKeyNotFiltered(CharacterComposer* character_composer, |
| uint key, |
| int flags) { |
| EXPECT_FALSE(character_composer->FilterKeyPress(key, 0, flags)); |
| EXPECT_TRUE(character_composer->composed_character().empty()); |
| } |
| |
| // Expects key is filtered and no character is composed. |
| void ExpectKeyFiltered(CharacterComposer* character_composer, |
| uint key, |
| int flags) { |
| EXPECT_TRUE(character_composer->FilterKeyPress(key, 0, flags)); |
| EXPECT_TRUE(character_composer->composed_character().empty()); |
| } |
| |
| // Expects key is filtered and no character is composed. |
| void ExpectKeyFilteredWithKeycode(CharacterComposer* character_composer, |
| uint key, |
| uint keycode, |
| int flags) { |
| EXPECT_TRUE(character_composer->FilterKeyPress(key, keycode, flags)); |
| EXPECT_TRUE(character_composer->composed_character().empty()); |
| } |
| |
| // Expects |expected_character| is composed after sequence [key1, key2]. |
| void ExpectCharacterComposed(CharacterComposer* character_composer, |
| uint key1, |
| uint key2, |
| int flags, |
| const string16& expected_character) { |
| ExpectKeyFiltered(character_composer, key1, flags); |
| EXPECT_TRUE(character_composer->FilterKeyPress(key2, 0, flags)); |
| EXPECT_EQ(expected_character, character_composer->composed_character()); |
| } |
| |
| // Expects |expected_character| is composed after sequence [key1, key2, key3]. |
| void ExpectCharacterComposed(CharacterComposer* character_composer, |
| uint key1, |
| uint key2, |
| uint key3, |
| int flags, |
| const string16& expected_character) { |
| ExpectKeyFiltered(character_composer, key1, flags); |
| ExpectCharacterComposed(character_composer, key2, key3, flags, |
| expected_character); |
| } |
| |
| // Expects |expected_character| is composed after sequence [key1, key2, key3, |
| // key 4]. |
| void ExpectCharacterComposed(CharacterComposer* character_composer, |
| uint key1, |
| uint key2, |
| uint key3, |
| uint key4, |
| int flags, |
| const string16& expected_character) { |
| ExpectKeyFiltered(character_composer, key1, flags); |
| ExpectCharacterComposed(character_composer, key2, key3, key4, flags, |
| expected_character); |
| } |
| |
| // Expects |expected_character| is composed after sequence [key1, key2, key3, |
| // key 4, key5]. |
| void ExpectCharacterComposed(CharacterComposer* character_composer, |
| uint key1, |
| uint key2, |
| uint key3, |
| uint key4, |
| uint key5, |
| int flags, |
| const string16& expected_character) { |
| ExpectKeyFiltered(character_composer, key1, flags); |
| ExpectCharacterComposed(character_composer, key2, key3, key4, key5, flags, |
| expected_character); |
| } |
| |
| // Expects |expected_character| is composed after sequence [key1, key2, key3, |
| // key 4, key5, key6]. |
| void ExpectCharacterComposed(CharacterComposer* character_composer, |
| uint key1, |
| uint key2, |
| uint key3, |
| uint key4, |
| uint key5, |
| uint key6, |
| int flags, |
| const string16& expected_character) { |
| ExpectKeyFiltered(character_composer, key1, flags); |
| ExpectCharacterComposed(character_composer, key2, key3, key4, key5, key6, |
| flags, expected_character); |
| } |
| |
| // Expects |expected_character| is composed after sequence [{key1, keycode1}]. |
| void ExpectCharacterComposedWithKeyCode(CharacterComposer* character_composer, |
| uint key1, uint keycode1, |
| int flags, |
| const string16& expected_character) { |
| EXPECT_TRUE(character_composer->FilterKeyPress(key1, keycode1, flags)); |
| EXPECT_EQ(expected_character, character_composer->composed_character()); |
| } |
| |
| } // namespace |
| |
| TEST(CharacterComposerTest, InitialState) { |
| CharacterComposer character_composer; |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| } |
| |
| TEST(CharacterComposerTest, NormalKeyIsNotFiltered) { |
| CharacterComposer character_composer; |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_B, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_Z, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_c, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_m, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_0, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_1, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_8, 0); |
| } |
| |
| TEST(CharacterComposerTest, PartiallyMatchingSequence) { |
| CharacterComposer character_composer; |
| |
| // Composition with sequence ['dead acute', '1'] will fail. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| |
| // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| } |
| |
| TEST(CharacterComposerTest, FullyMatchingSequences) { |
| CharacterComposer character_composer; |
| // LATIN SMALL LETTER A WITH ACUTE |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0, |
| string16(1, 0x00E1)); |
| // LATIN CAPITAL LETTER A WITH ACUTE |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_A, 0, |
| string16(1, 0x00C1)); |
| // GRAVE ACCENT |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_grave, |
| GDK_KEY_dead_grave, 0, string16(1, 0x0060)); |
| // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, |
| GDK_KEY_dead_circumflex, GDK_KEY_a, 0, |
| string16(1, 0x1EA5)); |
| // LATIN CAPITAL LETTER U WITH HORN AND GRAVE |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_grave, |
| GDK_KEY_dead_horn, GDK_KEY_U, 0, string16(1, 0x1EEA)); |
| // LATIN CAPITAL LETTER C WITH CEDILLA |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_C, 0, |
| string16(1, 0x00C7)); |
| // LATIN SMALL LETTER C WITH CEDILLA |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_c, 0, |
| string16(1, 0x00E7)); |
| } |
| |
| TEST(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) { |
| CharacterComposer character_composer; |
| // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, |
| GDK_KEY_dead_circumflex, GDK_KEY_a, 0, |
| string16(1, 0x1EA5)); |
| } |
| |
| TEST(CharacterComposerTest, ComposedCharacterIsClearedAfterReset) { |
| CharacterComposer character_composer; |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0, |
| string16(1, 0x00E1)); |
| character_composer.Reset(); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| } |
| |
| TEST(CharacterComposerTest, CompositionStateIsClearedAfterReset) { |
| CharacterComposer character_composer; |
| // Even though sequence ['dead acute', 'a'] will compose 'a with acute', |
| // no character is composed here because of reset. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0); |
| character_composer.Reset(); |
| EXPECT_FALSE(character_composer.FilterKeyPress(GDK_KEY_a, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| } |
| |
| TEST(CharacterComposerTest, KeySequenceCompositionPreedit) { |
| CharacterComposer character_composer; |
| // LATIN SMALL LETTER A WITH ACUTE |
| // preedit_string() is always empty in key sequence composition mode. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0); |
| EXPECT_TRUE(character_composer.preedit_string().empty()); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_a, 0, 0)); |
| EXPECT_EQ(string16(1, 0x00E1), character_composer.composed_character()); |
| EXPECT_TRUE(character_composer.preedit_string().empty()); |
| } |
| |
| // ComposeCheckerWithCompactTable in character_composer.cc is depending on the |
| // assumption that the data in gtkimcontextsimpleseqs.h is correctly ordered. |
| TEST(CharacterComposerTest, MainTableIsCorrectlyOrdered) { |
| // This file is included here intentionally, instead of the top of the file, |
| // because including this file at the top of the file will define a |
| // global constant and contaminate the global namespace. |
| #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h" |
| const int index_size = 26; |
| const int index_stride = 6; |
| |
| // Verify that the index is correctly ordered |
| for (int i = 1; i < index_size; ++i) { |
| const int index_key_prev = gtk_compose_seqs_compact[(i - 1)*index_stride]; |
| const int index_key = gtk_compose_seqs_compact[i*index_stride]; |
| EXPECT_TRUE(index_key > index_key_prev); |
| } |
| |
| // Verify that the sequenes are correctly ordered |
| struct { |
| int operator()(const uint16* l, const uint16* r, int length) const{ |
| for (int i = 0; i < length; ++i) { |
| if (l[i] > r[i]) |
| return 1; |
| if (l[i] < r[i]) |
| return -1; |
| } |
| return 0; |
| } |
| } compare_sequence; |
| |
| for (int i = 0; i < index_size; ++i) { |
| for (int length = 1; length < index_stride - 1; ++length) { |
| const int index_begin = gtk_compose_seqs_compact[i*index_stride + length]; |
| const int index_end = |
| gtk_compose_seqs_compact[i*index_stride + length + 1]; |
| const int stride = length + 1; |
| for (int index = index_begin + stride; index < index_end; |
| index += stride) { |
| const uint16* sequence = >k_compose_seqs_compact[index]; |
| const uint16* sequence_prev = sequence - stride; |
| EXPECT_EQ(1, compare_sequence(sequence, sequence_prev, length)); |
| } |
| } |
| } |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalComposition) { |
| CharacterComposer character_composer; |
| // HIRAGANA LETTER A (U+3042) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4, |
| GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042)); |
| // MUSICAL KEYBOARD (U+1F3B9) |
| const char16 kMusicalKeyboard[] = {0xd83c, 0xdfb9}; |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_1, GDK_KEY_f, GDK_KEY_3, |
| GDK_KEY_b, GDK_KEY_9, GDK_KEY_Return, 0, |
| string16(kMusicalKeyboard, |
| kMusicalKeyboard + |
| arraysize(kMusicalKeyboard))); |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalCompositionPreedit) { |
| CharacterComposer character_composer; |
| // HIRAGANA LETTER A (U+3042) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0); |
| EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0); |
| EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_4, 0); |
| EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_a, 0); |
| EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0); |
| EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string()); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_2, GDK_KEY_Return, 0, |
| string16(1, 0x3042)); |
| EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string()); |
| |
| // Sequence with an ignored character ('x') and Escape. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0); |
| EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0); |
| EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_x, 0); |
| EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_4, 0); |
| EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_2, 0); |
| EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string()); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_Escape, 0); |
| EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string()); |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalCompositionWithNonHexKey) { |
| CharacterComposer character_composer; |
| |
| // Sequence [Ctrl+Shift+U, x, space] does not compose a character. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_x, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| |
| // HIRAGANA LETTER A (U+3042) with a sequence [3, 0, x, 4, 2]. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_x, |
| GDK_KEY_4, GDK_KEY_2, GDK_KEY_space, 0, |
| string16(1, 0x3042)); |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalCompositionWithAdditionalModifiers) { |
| CharacterComposer character_composer; |
| |
| // Ctrl+Shift+Alt+U |
| // HIRAGANA LETTER A (U+3042) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4, |
| GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042)); |
| |
| // Ctrl+Shift+u (CapsLock enabled) |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_u, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_CAPS_LOCK_DOWN); |
| } |
| |
| TEST(CharacterComposerTest, CancelHexadecimalComposition) { |
| CharacterComposer character_composer; |
| // Cancel composition with ESC. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_Escape, 0); |
| |
| // Now we can start composition again since the last composition was |
| // cancelled. |
| // HIRAGANA LETTER A (U+3042) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4, |
| GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042)); |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalCompositionWithBackspace) { |
| CharacterComposer character_composer; |
| // HIRAGANA LETTER A (U+3042) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_4, GDK_KEY_2, |
| GDK_KEY_space, 0, string16(1, 0x3042)); |
| } |
| |
| TEST(CharacterComposerTest, CancelHexadecimalCompositionWithBackspace) { |
| CharacterComposer character_composer; |
| |
| // Backspace just after Ctrl+Shift+U. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_3, 0); |
| |
| // Backspace twice after Ctrl+Shift+U and 3. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0); |
| ExpectKeyNotFiltered(&character_composer, GDK_KEY_3, 0); |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalCompositionPreeditWithModifierPressed) { |
| // This test case supposes X Window System uses 101 keyboard layout. |
| CharacterComposer character_composer; |
| const int control_shift = EF_CONTROL_DOWN | EF_SHIFT_DOWN; |
| // HIRAGANA LETTER A (U+3042) |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_U, 30, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_numbersign, 12, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_parenright, 19, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_dollar, 13, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_A, 38, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_BackSpace, 22, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_at, 11, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string()); |
| ExpectCharacterComposedWithKeyCode(&character_composer, |
| GDK_KEY_Return, 36, |
| control_shift, |
| string16(1, 0x3042)); |
| EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string()); |
| |
| // Sequence with an ignored character (control + shift + 'x') and Escape. |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_U, 30, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_numbersign, 12, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_parenright, 19, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_X, 53, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_dollar, 13, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_at, 11, control_shift); |
| EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string()); |
| ExpectKeyFilteredWithKeycode(&character_composer, |
| GDK_KEY_Escape, 9, control_shift); |
| EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string()); |
| } |
| |
| TEST(CharacterComposerTest, InvalidHexadecimalSequence) { |
| CharacterComposer character_composer; |
| // U+FFFFFFFF |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| for (int i = 0; i < 8; ++i) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| |
| // U+0000 (Actually, this is a valid unicode character, but we don't |
| // compose a string with a character '\0') |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| for (int i = 0; i < 4; ++i) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| |
| // U+10FFFF |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0); |
| for (int i = 0; i < 4; ++i) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| |
| // U+110000 |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0); |
| ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0); |
| for (int i = 0; i < 4; ++i) |
| ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0)); |
| EXPECT_TRUE(character_composer.composed_character().empty()); |
| } |
| |
| TEST(CharacterComposerTest, HexadecimalSequenceAndDeadKey) { |
| CharacterComposer character_composer; |
| // LATIN SMALL LETTER A WITH ACUTE |
| ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0, |
| string16(1, 0x00E1)); |
| // HIRAGANA LETTER A (U+3042) with dead_acute ignored. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_U, |
| EF_SHIFT_DOWN | EF_CONTROL_DOWN); |
| ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, |
| GDK_KEY_dead_acute, GDK_KEY_4, GDK_KEY_2, |
| GDK_KEY_space, 0, string16(1, 0x3042)); |
| // LATIN CAPITAL LETTER U WITH ACUTE while 'U' is pressed with Ctrl+Shift. |
| ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0); |
| EXPECT_TRUE(character_composer.FilterKeyPress( |
| GDK_KEY_U, 0, EF_SHIFT_DOWN | EF_CONTROL_DOWN)); |
| EXPECT_EQ(string16(1, 0x00DA), character_composer.composed_character()); |
| } |
| |
| TEST(CharacterComposerTest, BlacklistedKeyeventsTest) { |
| CharacterComposer character_composer; |
| EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_dead_acute, 0, 0)); |
| EXPECT_FALSE(character_composer.FilterKeyPress(GDK_KEY_s, 0, 0)); |
| ASSERT_EQ(1U, character_composer.composed_character().size()); |
| EXPECT_EQ(GDK_KEY_apostrophe, character_composer.composed_character().at(0)); |
| } |
| |
| } // namespace ui |