blob: 92f1532fa173e8eae4a0cef696f9161016ba61a4 [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "unix/ibus/key_translator.h"
#include <memory>
#include <set>
#include "session/commands.pb.h"
#include "testing/base/public/gunit.h"
namespace mozc {
namespace ibus {
struct {
guint ibus_key;
commands::KeyEvent::SpecialKey mozc_key;
} kSpecialKeys[] = {
{IBUS_space, commands::KeyEvent::SPACE},
{IBUS_Return, commands::KeyEvent::ENTER},
{IBUS_Left, commands::KeyEvent::LEFT},
{IBUS_Right, commands::KeyEvent::RIGHT},
{IBUS_Up, commands::KeyEvent::UP},
{IBUS_Down, commands::KeyEvent::DOWN},
{IBUS_Escape, commands::KeyEvent::ESCAPE},
{IBUS_Delete, commands::KeyEvent::DEL},
{IBUS_BackSpace, commands::KeyEvent::BACKSPACE},
{IBUS_Insert, commands::KeyEvent::INSERT},
{IBUS_Henkan, commands::KeyEvent::HENKAN},
{IBUS_Muhenkan, commands::KeyEvent::MUHENKAN},
{IBUS_Hiragana, commands::KeyEvent::KANA},
{IBUS_Katakana, commands::KeyEvent::KATAKANA},
{IBUS_Hiragana_Katakana, commands::KeyEvent::KANA},
{IBUS_Eisu_toggle, commands::KeyEvent::EISU},
{IBUS_Home, commands::KeyEvent::HOME},
{IBUS_End, commands::KeyEvent::END},
{IBUS_Tab, commands::KeyEvent::TAB},
{IBUS_F1, commands::KeyEvent::F1},
{IBUS_F2, commands::KeyEvent::F2},
{IBUS_F3, commands::KeyEvent::F3},
{IBUS_F4, commands::KeyEvent::F4},
{IBUS_F5, commands::KeyEvent::F5},
{IBUS_F6, commands::KeyEvent::F6},
{IBUS_F7, commands::KeyEvent::F7},
{IBUS_F8, commands::KeyEvent::F8},
{IBUS_F9, commands::KeyEvent::F9},
{IBUS_F10, commands::KeyEvent::F10},
{IBUS_F11, commands::KeyEvent::F11},
{IBUS_F12, commands::KeyEvent::F12},
{IBUS_F13, commands::KeyEvent::F13},
{IBUS_F14, commands::KeyEvent::F14},
{IBUS_F15, commands::KeyEvent::F15},
{IBUS_F16, commands::KeyEvent::F16},
{IBUS_F17, commands::KeyEvent::F17},
{IBUS_F18, commands::KeyEvent::F18},
{IBUS_F19, commands::KeyEvent::F19},
{IBUS_F20, commands::KeyEvent::F20},
{IBUS_F21, commands::KeyEvent::F21},
{IBUS_F22, commands::KeyEvent::F22},
{IBUS_F23, commands::KeyEvent::F23},
{IBUS_F24, commands::KeyEvent::F24},
{IBUS_Page_Up, commands::KeyEvent::PAGE_UP},
{IBUS_Page_Down, commands::KeyEvent::PAGE_DOWN},
{IBUS_KP_0, commands::KeyEvent::NUMPAD0},
{IBUS_KP_1, commands::KeyEvent::NUMPAD1},
{IBUS_KP_2, commands::KeyEvent::NUMPAD2},
{IBUS_KP_3, commands::KeyEvent::NUMPAD3},
{IBUS_KP_4, commands::KeyEvent::NUMPAD4},
{IBUS_KP_5, commands::KeyEvent::NUMPAD5},
{IBUS_KP_6, commands::KeyEvent::NUMPAD6},
{IBUS_KP_7, commands::KeyEvent::NUMPAD7},
{IBUS_KP_8, commands::KeyEvent::NUMPAD8},
{IBUS_KP_9, commands::KeyEvent::NUMPAD9},
{IBUS_KP_Equal, commands::KeyEvent::EQUALS},
{IBUS_KP_Multiply, commands::KeyEvent::MULTIPLY},
{IBUS_KP_Add, commands::KeyEvent::ADD},
{IBUS_KP_Separator, commands::KeyEvent::SEPARATOR},
{IBUS_KP_Subtract, commands::KeyEvent::SUBTRACT},
{IBUS_KP_Decimal, commands::KeyEvent::DECIMAL},
{IBUS_KP_Divide, commands::KeyEvent::DIVIDE},
{IBUS_KP_Space, commands::KeyEvent::SPACE},
{IBUS_KP_Tab, commands::KeyEvent::TAB},
{IBUS_KP_Enter, commands::KeyEvent::ENTER},
{IBUS_KP_Home, commands::KeyEvent::HOME},
{IBUS_KP_Left, commands::KeyEvent::LEFT},
{IBUS_KP_Up, commands::KeyEvent::UP},
{IBUS_KP_Right, commands::KeyEvent::RIGHT},
{IBUS_KP_Down, commands::KeyEvent::DOWN},
{IBUS_KP_Page_Up, commands::KeyEvent::PAGE_UP},
{IBUS_KP_Page_Down, commands::KeyEvent::PAGE_DOWN},
{IBUS_KP_End, commands::KeyEvent::END},
{IBUS_KP_Delete, commands::KeyEvent::DEL},
{IBUS_KP_Insert, commands::KeyEvent::INSERT},
{IBUS_Caps_Lock, commands::KeyEvent::CAPS_LOCK},
{IBUS_ISO_Left_Tab, commands::KeyEvent::TAB},
};
// Checks "container" contains "key" value or not
bool IsContained(commands::KeyEvent_ModifierKey key,
const ::google::protobuf::RepeatedField<int>& container) {
for (int i = 0; i< container.size(); ++i) {
if (container.Get(i) == key) {
return true;
}
}
return false;
}
class KeyTranslatorTest : public testing::Test {
protected:
KeyTranslatorTest() {}
~KeyTranslatorTest() {}
virtual void SetUp() {
translator_.reset(new KeyTranslator);
}
std::unique_ptr<KeyTranslator> translator_;
};
TEST_F(KeyTranslatorTest, TranslateAscii) {
commands::KeyEvent out;
// ' ' (0x20) is treated as a special key by Mozc.
EXPECT_TRUE(translator_->Translate(0x20, 0, 0, config::Config::ROMAN, true,
&out));
EXPECT_FALSE(out.has_key_code());
EXPECT_TRUE(out.has_special_key());
EXPECT_EQ(0, out.modifier_keys_size());
for (char c = 0x21; c < 0x7f; ++c) {
EXPECT_TRUE(translator_->Translate(c, 0, 0, config::Config::ROMAN, true,
&out));
EXPECT_TRUE(out.has_key_code());
EXPECT_FALSE(out.has_special_key());
EXPECT_EQ(c, out.key_code());
EXPECT_EQ(0, out.modifier_keys_size());
}
}
TEST_F(KeyTranslatorTest, TranslateSpecial) {
commands::KeyEvent out;
for (int i = 0; i < arraysize(kSpecialKeys); ++i) {
EXPECT_TRUE(translator_->Translate(kSpecialKeys[i].ibus_key, 0, 0,
config::Config::ROMAN, true, &out));
EXPECT_FALSE(out.has_key_code());
EXPECT_TRUE(out.has_special_key());
EXPECT_EQ(kSpecialKeys[i].mozc_key, out.special_key());
EXPECT_EQ(0, out.modifier_keys_size());
}
// Check Hiragana_Katakana local hack. The detail is described in
// key_translator.cc file.
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, 0,
config::Config::ROMAN, true, &out));
EXPECT_FALSE(out.has_key_code());
ASSERT_TRUE(out.has_special_key());
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
EXPECT_EQ(0, out.modifier_keys_size());
}
TEST_F(KeyTranslatorTest, TranslateSingleModifierMasks) {
commands::KeyEvent out;
// CTRL modifier
// C-F1
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, IBUS_CONTROL_MASK,
config::Config::ROMAN, true, &out));
ASSERT_EQ(1, out.modifier_keys_size());
// C-a
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', IBUS_CONTROL_MASK,
config::Config::ROMAN, true, &out));
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::CTRL, out.modifier_keys(0));
// SHIFT modifier
// S-F1
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, IBUS_SHIFT_MASK,
config::Config::ROMAN, true, &out));
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::SHIFT, out.modifier_keys(0));
// S-a
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', IBUS_SHIFT_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(0, out.modifier_keys_size());
// S-0
// TODO(nona): Resolve Shift-0 problem (b/4338394)
// We have to check the behavior of Shift-0, because most of japanese
// keyboard are not assigned Shift-0 character. So that, we expect the client
// send keycode='0'(\x30) with shift modifier, but currently only send
// keycode='0'. There are few difficulties because the mapping of Shift-0 are
// controled xkb in X11, but the way to get the mapping is unclear.
// ALT modifier
// M-F1
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, IBUS_MOD1_MASK,
config::Config::ROMAN, true, &out));
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::ALT, out.modifier_keys(0));
// M-a
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', IBUS_MOD1_MASK,
config::Config::ROMAN, true, &out));
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::ALT, out.modifier_keys(0));
}
TEST_F(KeyTranslatorTest, TranslateMultipleModifierMasks) {
commands::KeyEvent out;
guint modifier;
// CTRL + SHIFT modifier
// C-S-F1 (CTRL + SHIFT + SpecialKey)
modifier = IBUS_CONTROL_MASK | IBUS_SHIFT_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
// C-S-a (CTRL + SHIFT + OtherKey)
modifier = IBUS_CONTROL_MASK | IBUS_SHIFT_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
// CTRL + ALT modifier
// C-M-F1 (CTRL + ALT + SpecialKey)
modifier = IBUS_CONTROL_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
// C-M-a (CTRL + ALT + OtherKey)
modifier = IBUS_CONTROL_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
// SHIFT + ALT modifier
// S-M-F1 (CTRL + ALT + SpecialKey)
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
// S-M-a (CTRL + ALT + OtherKey)
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
// CTRL + SHIFT + ALT modifier
// C-S-M-F1 (CTRL + SHIFT + ALT + SpecialKey)
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_F1, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(3, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
// C-S-M-a (CTRL + SHFIT + ALT + OtherKey)
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_A, 'a', modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(3, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
}
TEST_F(KeyTranslatorTest, HiraganaKatakanaHandlingWithSingleModifierTest) {
// Check Hiragana_Katakana local hack. The detail is described in
// key_translator.cc file.
commands::KeyEvent out;
// S-Hiragana_Katakana
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, IBUS_SHIFT_MASK,
config::Config::ROMAN, true, &out));
EXPECT_FALSE(out.has_key_code());
ASSERT_TRUE(out.has_special_key());
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
EXPECT_EQ(0, out.modifier_keys_size());
// C-Hiragana_Katakana
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0,
IBUS_CONTROL_MASK, config::Config::ROMAN,
true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::CTRL, out.modifier_keys(0));
// M-Hiragana_Katakana
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, IBUS_MOD1_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::ALT, out.modifier_keys(0));
// Hiragana_Katakana handling should have no effect into Hiragana key or
// Katakana key.
// S-Hiragana
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, IBUS_SHIFT_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::SHIFT, out.modifier_keys(0));
// C-Hiragana
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, IBUS_CONTROL_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::CTRL, out.modifier_keys(0));
// M-Hiragana
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, IBUS_MOD1_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::ALT, out.modifier_keys(0));
// S-Katakana
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, IBUS_SHIFT_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::SHIFT, out.modifier_keys(0));
// C-Katakana
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, IBUS_CONTROL_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::CTRL, out.modifier_keys(0));
// M-Katakana
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, IBUS_MOD1_MASK,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::ALT, out.modifier_keys(0));
}
TEST_F(KeyTranslatorTest, HiraganaKatakanaHandlingWithMultipleModifiersTest) {
// Check Hiragana_Katakana local hack. The detail is described in
// key_translator.cc file.
commands::KeyEvent out;
guint modifier;
// C-S-Hiragana_Katakana
modifier = IBUS_SHIFT_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::CTRL, out.modifier_keys(0));
// M-S-Hiragana_Katakana
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::ALT, out.modifier_keys(0));
// C-M-Hiragana_Katakana
modifier = IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
// C-S-M-Hiragana_Katakana
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
EXPECT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
// Hiragana_Katakana handling should have no effect into Hiragana key or
// Katakana key.
// C-S-Hiragana
modifier = IBUS_SHIFT_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
// M-S-Hiragana
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
// C-M-Hiragana
modifier = IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
// C-S-M-Hiragana
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Hiragana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KANA, out.special_key());
EXPECT_EQ(3, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
// C-S-Katakana
modifier = IBUS_SHIFT_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
// M-S-Katakana
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
// C-M-Katakana
modifier = IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
ASSERT_EQ(2, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
// C-S-M-Katakana
modifier = IBUS_SHIFT_MASK | IBUS_MOD1_MASK | IBUS_CONTROL_MASK;
EXPECT_TRUE(translator_->Translate(IBUS_Katakana, 0, modifier,
config::Config::ROMAN, true, &out));
EXPECT_EQ(commands::KeyEvent::KATAKANA, out.special_key());
EXPECT_EQ(3, out.modifier_keys_size());
IsContained(commands::KeyEvent::CTRL, out.modifier_keys());
IsContained(commands::KeyEvent::SHIFT, out.modifier_keys());
IsContained(commands::KeyEvent::ALT, out.modifier_keys());
}
TEST_F(KeyTranslatorTest, TranslateUnknow) {
commands::KeyEvent out;
EXPECT_FALSE(translator_->Translate(IBUS_VoidSymbol, 0, 0,
config::Config::ROMAN, true, &out));
// Mozc does not support F25 - F35.
EXPECT_FALSE(translator_->Translate(IBUS_F25, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F26, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F27, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F28, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F29, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F30, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F31, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F32, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F33, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F34, 0, 0, config::Config::ROMAN,
true, &out));
EXPECT_FALSE(translator_->Translate(IBUS_F35, 0, 0, config::Config::ROMAN,
true, &out));
}
TEST_F(KeyTranslatorTest, TranslateModiferOnly) {
commands::KeyEvent out;
// Just tap left_shift key
EXPECT_TRUE(translator_->Translate(
IBUS_Shift_L, 0, 0, config::Config::ROMAN, true, &out));
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::LEFT_SHIFT, out.modifier_keys(0));
// Just tap right_shift key
out.Clear();
EXPECT_TRUE(translator_->Translate(
IBUS_Shift_R, 0, 0, config::Config::ROMAN, true, &out));
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::RIGHT_SHIFT, out.modifier_keys(0));
// Just tap left_ctrl key
out.Clear();
EXPECT_TRUE(translator_->Translate(
IBUS_Control_L, 0, 0, config::Config::ROMAN, true, &out));
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::LEFT_CTRL, out.modifier_keys(0));
// Just tap right_ctrl key
out.Clear();
EXPECT_TRUE(translator_->Translate(
IBUS_Control_R, 0, 0, config::Config::ROMAN, true, &out));
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::RIGHT_CTRL, out.modifier_keys(0));
// Just tap left_alt key
out.Clear();
EXPECT_TRUE(translator_->Translate(
IBUS_Alt_L, 0, 0, config::Config::ROMAN, true, &out));
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::LEFT_ALT, out.modifier_keys(0));
// Just tap right_alt key
out.Clear();
EXPECT_TRUE(translator_->Translate(
IBUS_Alt_R, 0, 0, config::Config::ROMAN, true, &out));
EXPECT_EQ(1, out.modifier_keys_size());
EXPECT_EQ(commands::KeyEvent::RIGHT_ALT, out.modifier_keys(0));
}
} // namespace ibus
} // namespace mozc