blob: b2406e23de39b88a95a504ef438fc846113a7ddd [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 <map>
#include <string>
#include "base/logging.h"
#include "base/port.h"
namespace {
const struct SpecialKeyMap {
guint from;
mozc::commands::KeyEvent::SpecialKey to;
} special_key_map[] = {
{IBUS_space, mozc::commands::KeyEvent::SPACE},
{IBUS_Return, mozc::commands::KeyEvent::ENTER},
{IBUS_Left, mozc::commands::KeyEvent::LEFT},
{IBUS_Right, mozc::commands::KeyEvent::RIGHT},
{IBUS_Up, mozc::commands::KeyEvent::UP},
{IBUS_Down, mozc::commands::KeyEvent::DOWN},
{IBUS_Escape, mozc::commands::KeyEvent::ESCAPE},
{IBUS_Delete, mozc::commands::KeyEvent::DEL},
{IBUS_BackSpace, mozc::commands::KeyEvent::BACKSPACE},
{IBUS_Insert, mozc::commands::KeyEvent::INSERT},
{IBUS_Henkan, mozc::commands::KeyEvent::HENKAN},
{IBUS_Muhenkan, mozc::commands::KeyEvent::MUHENKAN},
{IBUS_Hiragana, mozc::commands::KeyEvent::KANA},
{IBUS_Hiragana_Katakana, mozc::commands::KeyEvent::KANA},
{IBUS_Katakana, mozc::commands::KeyEvent::KATAKANA},
{IBUS_Zenkaku, mozc::commands::KeyEvent::HANKAKU},
{IBUS_Hankaku, mozc::commands::KeyEvent::HANKAKU},
{IBUS_Zenkaku_Hankaku, mozc::commands::KeyEvent::HANKAKU},
{IBUS_Eisu_toggle, mozc::commands::KeyEvent::EISU},
{IBUS_Home, mozc::commands::KeyEvent::HOME},
{IBUS_End, mozc::commands::KeyEvent::END},
{IBUS_Tab, mozc::commands::KeyEvent::TAB},
{IBUS_F1, mozc::commands::KeyEvent::F1},
{IBUS_F2, mozc::commands::KeyEvent::F2},
{IBUS_F3, mozc::commands::KeyEvent::F3},
{IBUS_F4, mozc::commands::KeyEvent::F4},
{IBUS_F5, mozc::commands::KeyEvent::F5},
{IBUS_F6, mozc::commands::KeyEvent::F6},
{IBUS_F7, mozc::commands::KeyEvent::F7},
{IBUS_F8, mozc::commands::KeyEvent::F8},
{IBUS_F9, mozc::commands::KeyEvent::F9},
{IBUS_F10, mozc::commands::KeyEvent::F10},
{IBUS_F11, mozc::commands::KeyEvent::F11},
{IBUS_F12, mozc::commands::KeyEvent::F12},
{IBUS_F13, mozc::commands::KeyEvent::F13},
{IBUS_F14, mozc::commands::KeyEvent::F14},
{IBUS_F15, mozc::commands::KeyEvent::F15},
{IBUS_F16, mozc::commands::KeyEvent::F16},
{IBUS_F17, mozc::commands::KeyEvent::F17},
{IBUS_F18, mozc::commands::KeyEvent::F18},
{IBUS_F19, mozc::commands::KeyEvent::F19},
{IBUS_F20, mozc::commands::KeyEvent::F20},
{IBUS_F21, mozc::commands::KeyEvent::F21},
{IBUS_F22, mozc::commands::KeyEvent::F22},
{IBUS_F23, mozc::commands::KeyEvent::F23},
{IBUS_F24, mozc::commands::KeyEvent::F24},
{IBUS_Page_Up, mozc::commands::KeyEvent::PAGE_UP},
{IBUS_Page_Down, mozc::commands::KeyEvent::PAGE_DOWN},
// Keypad (10-key).
{IBUS_KP_0, mozc::commands::KeyEvent::NUMPAD0},
{IBUS_KP_1, mozc::commands::KeyEvent::NUMPAD1},
{IBUS_KP_2, mozc::commands::KeyEvent::NUMPAD2},
{IBUS_KP_3, mozc::commands::KeyEvent::NUMPAD3},
{IBUS_KP_4, mozc::commands::KeyEvent::NUMPAD4},
{IBUS_KP_5, mozc::commands::KeyEvent::NUMPAD5},
{IBUS_KP_6, mozc::commands::KeyEvent::NUMPAD6},
{IBUS_KP_7, mozc::commands::KeyEvent::NUMPAD7},
{IBUS_KP_8, mozc::commands::KeyEvent::NUMPAD8},
{IBUS_KP_9, mozc::commands::KeyEvent::NUMPAD9},
{IBUS_KP_Equal, mozc::commands::KeyEvent::EQUALS}, // [=]
{IBUS_KP_Multiply, mozc::commands::KeyEvent::MULTIPLY}, // [*]
{IBUS_KP_Add, mozc::commands::KeyEvent::ADD}, // [+]
{IBUS_KP_Separator, mozc::commands::KeyEvent::SEPARATOR}, // enter
{IBUS_KP_Subtract, mozc::commands::KeyEvent::SUBTRACT}, // [-]
{IBUS_KP_Decimal, mozc::commands::KeyEvent::DECIMAL}, // [.]
{IBUS_KP_Divide, mozc::commands::KeyEvent::DIVIDE}, // [/]
{IBUS_KP_Space, mozc::commands::KeyEvent::SPACE},
{IBUS_KP_Tab, mozc::commands::KeyEvent::TAB},
{IBUS_KP_Enter, mozc::commands::KeyEvent::ENTER},
{IBUS_KP_Home, mozc::commands::KeyEvent::HOME},
{IBUS_KP_Left, mozc::commands::KeyEvent::LEFT},
{IBUS_KP_Up, mozc::commands::KeyEvent::UP},
{IBUS_KP_Right, mozc::commands::KeyEvent::RIGHT},
{IBUS_KP_Down, mozc::commands::KeyEvent::DOWN},
{IBUS_KP_Page_Up, mozc::commands::KeyEvent::PAGE_UP},
{IBUS_KP_Page_Down, mozc::commands::KeyEvent::PAGE_DOWN},
{IBUS_KP_End, mozc::commands::KeyEvent::END},
{IBUS_KP_Delete, mozc::commands::KeyEvent::DEL},
{IBUS_KP_Insert, mozc::commands::KeyEvent::INSERT},
{IBUS_Caps_Lock, mozc::commands::KeyEvent::CAPS_LOCK},
// Shift+TAB.
{IBUS_ISO_Left_Tab, mozc::commands::KeyEvent::TAB},
// TODO(mazda): Handle following keys?
// - IBUS_Kana_Lock? IBUS_KEY_Kana_Shift?
};
const struct ModifierKeyMap {
guint from;
mozc::commands::KeyEvent::ModifierKey to;
} modifier_key_map[] = {
{IBUS_Shift_L, mozc::commands::KeyEvent::LEFT_SHIFT},
{IBUS_Shift_R, mozc::commands::KeyEvent::RIGHT_SHIFT},
{IBUS_Control_L, mozc::commands::KeyEvent::LEFT_CTRL},
{IBUS_Control_R, mozc::commands::KeyEvent::RIGHT_CTRL},
{IBUS_Alt_L, mozc::commands::KeyEvent::LEFT_ALT},
{IBUS_Alt_R, mozc::commands::KeyEvent::RIGHT_ALT},
{IBUS_LOCK_MASK, mozc::commands::KeyEvent::CAPS},
};
const struct ModifierMaskMap {
guint from;
mozc::commands::KeyEvent::ModifierKey to;
} modifier_mask_map[] = {
{IBUS_SHIFT_MASK, mozc::commands::KeyEvent::SHIFT},
{IBUS_CONTROL_MASK, mozc::commands::KeyEvent::CTRL},
{IBUS_MOD1_MASK, mozc::commands::KeyEvent::ALT},
};
// TODO(team): Add kana_map_dv to support Dvoraklayout.
const struct KanaMap {
guint code;
const char *no_shift;
const char *shift;
} kana_map_jp[] = {
{ '1' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
{ '!' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
{ '2' , "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
{ '\"', "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
{ '3' , "\xe3\x81\x82", "\xe3\x81\x81" }, // "あ", "ぁ"
{ '#' , "\xe3\x81\x82", "\xe3\x81\x81" }, // "あ", "ぁ"
{ '4' , "\xe3\x81\x86", "\xe3\x81\x85" }, // "う", "ぅ"
{ '$' , "\xe3\x81\x86", "\xe3\x81\x85" }, // "う", "ぅ"
{ '5' , "\xe3\x81\x88", "\xe3\x81\x87" }, // "え", "ぇ"
{ '%' , "\xe3\x81\x88", "\xe3\x81\x87" }, // "え", "ぇ"
{ '6' , "\xe3\x81\x8a", "\xe3\x81\x89" }, // "お", "ぉ"
{ '&' , "\xe3\x81\x8a", "\xe3\x81\x89" }, // "お", "ぉ"
{ '7' , "\xe3\x82\x84", "\xe3\x82\x83" }, // "や", "ゃ"
{ '\'', "\xe3\x82\x84", "\xe3\x82\x83" }, // "や", "ゃ"
{ '8' , "\xe3\x82\x86", "\xe3\x82\x85" }, // "ゆ", "ゅ"
{ '(' , "\xe3\x82\x86", "\xe3\x82\x85" }, // "ゆ", "ゅ"
{ '9' , "\xe3\x82\x88", "\xe3\x82\x87" }, // "よ", "ょ"
{ ')' , "\xe3\x82\x88", "\xe3\x82\x87" }, // "よ", "ょ"
{ '0' , "\xe3\x82\x8f", "\xe3\x82\x92" }, // "わ", "を"
{ '-' , "\xe3\x81\xbb", "\xe3\x81\xbb" }, // "ほ", "ほ"
{ '=' , "\xe3\x81\xbb", "\xe3\x81\xbb" }, // "ほ", "ほ"
{ '^' , "\xe3\x81\xb8", "\xe3\x82\x92" }, // "へ", "を"
{ '~' , "\xe3\x81\xb8", "\xe3\x82\x92" }, // "へ", "を"
{ '|' , "\xe3\x83\xbc", "\xe3\x83\xbc" }, // "ー", "ー"
{ 'q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
{ 'Q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
{ 'w' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
{ 'W' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
{ 'e' , "\xe3\x81\x84", "\xe3\x81\x83" }, // "い", "ぃ"
{ 'E' , "\xe3\x81\x84", "\xe3\x81\x83" }, // "い", "ぃ"
{ 'r' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
{ 'R' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
{ 't' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
{ 'T' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
{ 'y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
{ 'Y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
{ 'u' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
{ 'U' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
{ 'i' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
{ 'I' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
{ 'o' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
{ 'O' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
{ 'p' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
{ 'P' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
{ '@' , "\xe3\x82\x9b", "\xe3\x82\x9b" }, // "゛", "゛"
{ '`' , "\xe3\x82\x9b", "\xe3\x82\x9b" }, // "゛", "゛"
{ '[' , "\xe3\x82\x9c", "\xe3\x80\x8c" }, // "゜", "「"
{ '{' , "\xe3\x82\x9c", "\xe3\x80\x8c" }, // "゜", "「"
{ 'a' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
{ 'A' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
{ 's' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
{ 'S' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
{ 'd' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
{ 'D' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
{ 'f' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
{ 'F' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
{ 'g' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
{ 'G' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
{ 'h' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
{ 'H' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
{ 'j' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
{ 'J' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
{ 'k' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
{ 'K' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
{ 'l' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
{ 'L' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
{ ';' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
{ '+' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
{ ':' , "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
{ '*' , "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
{ ']' , "\xe3\x82\x80", "\xe3\x80\x8d" }, // "む", "」"
{ '}' , "\xe3\x82\x80", "\xe3\x80\x8d" }, // "む", "」"
{ 'z' , "\xe3\x81\xa4", "\xe3\x81\xa3" }, // "つ", "っ"
{ 'Z' , "\xe3\x81\xa4", "\xe3\x81\xa3" }, // "つ", "っ"
{ 'x' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
{ 'X' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
{ 'c' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
{ 'C' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
{ 'v' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
{ 'V' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
{ 'b' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
{ 'B' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
{ 'n' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
{ 'N' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
{ 'm' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
{ 'M' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
{ ',' , "\xe3\x81\xad", "\xe3\x80\x81" }, // "ね", "、"
{ '<' , "\xe3\x81\xad", "\xe3\x80\x81" }, // "ね", "、"
{ '.' , "\xe3\x82\x8b", "\xe3\x80\x82" }, // "る", "。"
{ '>' , "\xe3\x82\x8b", "\xe3\x80\x82" }, // "る", "。"
{ '/' , "\xe3\x82\x81", "\xe3\x83\xbb" }, // "め", "・"
{ '?' , "\xe3\x82\x81", "\xe3\x83\xbb" }, // "め", "・"
{ '_' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
// A backslash is handled in a special way because it is input by
// two different keys (the one next to Backslash and the one next
// to Right Shift).
{ '\\', "", "" },
}, kana_map_us[] = {
{ '`' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
{ '~' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
{ '1' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
{ '!' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
{ '2' , "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
{ '@' , "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
{ '3' , "\xe3\x81\x82", "\xe3\x81\x81" }, // "あ", "ぁ"
{ '#' , "\xe3\x81\x82", "\xe3\x81\x81" }, // "あ", "ぁ"
{ '4' , "\xe3\x81\x86", "\xe3\x81\x85" }, // "う", "ぅ"
{ '$' , "\xe3\x81\x86", "\xe3\x81\x85" }, // "う", "ぅ"
{ '5' , "\xe3\x81\x88", "\xe3\x81\x87" }, // "え", "ぇ"
{ '%' , "\xe3\x81\x88", "\xe3\x81\x87" }, // "え", "ぇ"
{ '6' , "\xe3\x81\x8a", "\xe3\x81\x89" }, // "お", "ぉ"
{ '^' , "\xe3\x81\x8a", "\xe3\x81\x89" }, // "お", "ぉ"
{ '7' , "\xe3\x82\x84", "\xe3\x82\x83" }, // "や", "ゃ"
{ '&' , "\xe3\x82\x84", "\xe3\x82\x83" }, // "や", "ゃ"
{ '8' , "\xe3\x82\x86", "\xe3\x82\x85" }, // "ゆ", "ゅ"
{ '*' , "\xe3\x82\x86", "\xe3\x82\x85" }, // "ゆ", "ゅ"
{ '9' , "\xe3\x82\x88", "\xe3\x82\x87" }, // "よ", "ょ"
{ '(' , "\xe3\x82\x88", "\xe3\x82\x87" }, // "よ", "ょ"
{ '0' , "\xe3\x82\x8f", "\xe3\x82\x92" }, // "わ", "を"
{ ')' , "\xe3\x82\x8f", "\xe3\x82\x92" }, // "わ", "を"
{ '-' , "\xe3\x81\xbb", "\xe3\x83\xbc" }, // "ほ", "ー"
{ '_' , "\xe3\x81\xbb", "\xe3\x83\xbc" }, // "ほ", "ー"
{ '=' , "\xe3\x81\xb8", "\xe3\x81\xb8" }, // "へ", "へ"
{ '+' , "\xe3\x81\xb8", "\xe3\x81\xb8" }, // "へ", "へ"
{ 'q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
{ 'Q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
{ 'w' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
{ 'W' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
{ 'e' , "\xe3\x81\x84", "\xe3\x81\x83" }, // "い", "ぃ"
{ 'E' , "\xe3\x81\x84", "\xe3\x81\x83" }, // "い", "ぃ"
{ 'r' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
{ 'R' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
{ 't' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
{ 'T' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
{ 'y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
{ 'Y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
{ 'u' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
{ 'U' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
{ 'i' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
{ 'I' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
{ 'o' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
{ 'O' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
{ 'p' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
{ 'P' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
{ '[' , "\xe3\x82\x9b", "\xe3\x82\x9b" }, // "゛", "゛"
{ '{' , "\xe3\x82\x9b", "\xe3\x82\x9b" }, // "゛", "゛"
{ ']' , "\xe3\x82\x9c", "\xe3\x80\x8c" }, // "゜", "「"
{ '}' , "\xe3\x82\x9c", "\xe3\x80\x8c" }, // "゜", "「"
{ '\\', "\xe3\x82\x80", "\xe3\x80\x8d" }, // "む", "」"
{ '|' , "\xe3\x82\x80", "\xe3\x80\x8d" }, // "む", "」"
{ 'a' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
{ 'A' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
{ 's' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
{ 'S' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
{ 'd' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
{ 'D' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
{ 'f' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
{ 'F' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
{ 'g' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
{ 'G' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
{ 'h' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
{ 'H' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
{ 'j' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
{ 'J' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
{ 'k' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
{ 'K' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
{ 'l' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
{ 'L' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
{ ';' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
{ ':' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
{ '\'', "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
{ '\"', "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
{ 'z' , "\xe3\x81\xa4", "\xe3\x81\xa3" }, // "つ", "っ"
{ 'Z' , "\xe3\x81\xa4", "\xe3\x81\xa3" }, // "つ", "っ"
{ 'x' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
{ 'X' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
{ 'c' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
{ 'C' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
{ 'v' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
{ 'V' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
{ 'b' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
{ 'B' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
{ 'n' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
{ 'N' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
{ 'm' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
{ 'M' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
{ ',' , "\xe3\x81\xad", "\xe3\x80\x81" }, // "ね", "、"
{ '<' , "\xe3\x81\xad", "\xe3\x80\x81" }, // "ね", "、"
{ '.' , "\xe3\x82\x8b", "\xe3\x80\x82" }, // "る", "。"
{ '>' , "\xe3\x82\x8b", "\xe3\x80\x82" }, // "る", "。"
{ '/' , "\xe3\x82\x81", "\xe3\x83\xbb" }, // "め", "・"
{ '?' , "\xe3\x82\x81", "\xe3\x83\xbb" }, // "め", "・"
};
} // namespace
namespace mozc {
namespace ibus {
KeyTranslator::KeyTranslator() {
Init();
}
KeyTranslator::~KeyTranslator() {
}
// TODO(nona): Fix 'Shift-0' behavior b/4338394
bool KeyTranslator::Translate(guint keyval,
guint keycode,
guint modifiers,
config::Config::PreeditMethod method,
bool layout_is_jp,
commands::KeyEvent *out_event) const {
DCHECK(out_event) << "out_event is NULL";
out_event->Clear();
// Due to historical reasons, many linux ditributions set Hiragana_Katakana
// key as Hiragana key (which is Katkana key with shift modifier). So, we
// translate Hiragana_Katanaka key as Hiragana key by mapping table, and
// Shift + Hiragana_Katakana key as Katakana key by functionally.
// TODO(nona): Fix process modifier to handle right shift
if (IsHiraganaKatakanaKeyWithShift(keyval, keycode, modifiers)) {
modifiers &= ~IBUS_SHIFT_MASK;
keyval = IBUS_Katakana;
}
string kana_key_string;
if ((method == config::Config::KANA) && IsKanaAvailable(
keyval, keycode, modifiers, layout_is_jp, &kana_key_string)) {
out_event->set_key_code(keyval);
out_event->set_key_string(kana_key_string);
} else if (IsAscii(keyval, keycode, modifiers)) {
if (IBUS_LOCK_MASK & modifiers) {
out_event->add_modifier_keys(commands::KeyEvent::CAPS);
}
out_event->set_key_code(keyval);
} else if (IsModifierKey(keyval, keycode, modifiers)) {
ModifierKeyMap::const_iterator i = modifier_key_map_.find(keyval);
DCHECK(i != modifier_key_map_.end());
out_event->add_modifier_keys(i->second);
} else if (IsSpecialKey(keyval, keycode, modifiers)) {
SpecialKeyMap::const_iterator i = special_key_map_.find(keyval);
DCHECK(i != special_key_map_.end());
out_event->set_special_key(i->second);
} else {
VLOG(1) << "Unknown keyval: " << keyval;
return false;
}
for (ModifierKeyMap::const_iterator i = modifier_mask_map_.begin();
i != modifier_mask_map_.end(); ++i) {
// Do not set a SHIFT modifier when |keyval| is a printable key by following
// the Mozc's rule.
if ((i->second == commands::KeyEvent::SHIFT) &&
IsPrintable(keyval, keycode, modifiers)) {
continue;
}
if (i->first & modifiers) {
out_event->add_modifier_keys(i->second);
}
}
return true;
}
void KeyTranslator::Init() {
for (int i = 0; i < arraysize(special_key_map); ++i) {
CHECK(special_key_map_.insert(make_pair(special_key_map[i].from,
special_key_map[i].to)).second);
}
for (int i = 0; i < arraysize(modifier_key_map); ++i) {
CHECK(modifier_key_map_.insert(make_pair(modifier_key_map[i].from,
modifier_key_map[i].to)).second);
}
for (int i = 0; i < arraysize(modifier_mask_map); ++i) {
CHECK(modifier_mask_map_.insert(make_pair(modifier_mask_map[i].from,
modifier_mask_map[i].to)).second);
}
for (int i = 0; i < arraysize(kana_map_jp); ++i) {
CHECK(kana_map_jp_.insert(
make_pair(kana_map_jp[i].code, make_pair(
kana_map_jp[i].no_shift, kana_map_jp[i].shift))).second);
}
for (int i = 0; i < arraysize(kana_map_us); ++i) {
CHECK(kana_map_us_.insert(
make_pair(kana_map_us[i].code, make_pair(
kana_map_us[i].no_shift, kana_map_us[i].shift))).second);
}
}
bool KeyTranslator::IsModifierKey(guint keyval,
guint keycode,
guint modifiers) const {
return modifier_key_map_.find(keyval) != modifier_key_map_.end();
}
bool KeyTranslator::IsSpecialKey(guint keyval,
guint keycode,
guint modifiers) const {
return special_key_map_.find(keyval) != special_key_map_.end();
}
bool KeyTranslator::IsHiraganaKatakanaKeyWithShift(guint keyval,
guint keycode,
guint modifiers) {
return ((modifiers & IBUS_SHIFT_MASK) && (keyval == IBUS_Hiragana_Katakana));
}
bool KeyTranslator::IsKanaAvailable(guint keyval,
guint keycode,
guint modifiers,
bool layout_is_jp,
string *out) const {
if ((modifiers & IBUS_CONTROL_MASK) || (modifiers & IBUS_MOD1_MASK)) {
return false;
}
const KanaMap &kana_map = layout_is_jp ? kana_map_jp_ : kana_map_us_;
KanaMap::const_iterator iter = kana_map.find(keyval);
if (iter == kana_map.end()) {
return false;
}
if (out) {
// When a Japanese keyboard is in use, the yen-sign key and the backslash
// key generate the same |keyval|. In this case, we have to check |keycode|
// to return an appropriate string. See the following IBus issue for
// details: http://code.google.com/p/ibus/issues/detail?id=52
if (keyval == '\\' && layout_is_jp) {
if (keycode == IBUS_bar) {
*out = "\xe3\x83\xbc"; // "ー"
} else {
*out = "\xe3\x82\x8d"; // "ろ"
}
} else {
*out = (modifiers & IBUS_SHIFT_MASK) ?
iter->second.second : iter->second.first;
}
}
return true;
}
// TODO(nona): resolve S-'0' problem (b/4338394).
// TODO(nona): Current printable detection is weak. To enhance accuracy, use xkb
// key map
bool KeyTranslator::IsPrintable(guint keyval, guint keycode, guint modifiers) {
if ((modifiers & IBUS_CONTROL_MASK) || (modifiers & IBUS_MOD1_MASK)) {
return false;
}
return IsAscii(keyval, keycode, modifiers);
}
bool KeyTranslator::IsAscii(guint keyval, guint keycode, guint modifiers) {
return (keyval > IBUS_space &&
// Note: Space key (0x20) is a special key in Mozc.
keyval <= IBUS_asciitilde); // 0x7e.
}
} // namespace ibus
} // namespace mozc