blob: f76a3cdb08711d451f67432c03eaea3b260dc00e [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/linux/keyboard_layout_monitor_utils.h"
namespace remoting {
// GDK doesn't return unicode value for dead keys, so we map them here.
const char* DeadKeyToUtf8String(guint keyval) {
// Some of these have spacing forms and some don't. For consistency, these are
// all of the form space+combining character. This file is a good resource to
// figure out what the various dead keys are supposed to do:
// https://cgit.freedesktop.org/xorg/lib/libX11/plain/nls/en_US.UTF-8/Compose.pre
// See also ui/events/keycodes/keysym_to_unicode.cc, which does a similar
// mapping.
switch (keyval) {
case GDK_KEY_dead_grave:
return " \xcc\x80"; // U+0300
case GDK_KEY_dead_acute:
return " \xcc\x81"; // U+0301
case GDK_KEY_dead_circumflex:
return " \xcc\x82"; // U+0302
case GDK_KEY_dead_tilde:
return " \xcc\x83"; // U+0303
case GDK_KEY_dead_macron:
return " \xcc\x84"; // U+0304
case GDK_KEY_dead_breve:
return " \xcc\x86"; // U+0306
case GDK_KEY_dead_abovedot:
return " \xcc\x87"; // U+0307
case GDK_KEY_dead_diaeresis:
return " \xcc\x88"; // U+0308
case GDK_KEY_dead_abovering:
return " \xcc\x8a"; // U+030A
case GDK_KEY_dead_doubleacute:
return " \xcc\x8b"; // U+030B
case GDK_KEY_dead_caron:
return " \xcc\x8c"; // U+030C
case GDK_KEY_dead_cedilla:
return " \xcc\xa7"; // U+0327
case GDK_KEY_dead_ogonek:
return " \xcc\xa8"; // U+0328
case GDK_KEY_dead_iota:
return " \xcd\x85"; // U+0345
case GDK_KEY_dead_voiced_sound:
return " \xe3\x82\x99"; // U+3099
case GDK_KEY_dead_semivoiced_sound:
return " \xe3\x82\x9a"; // U+309A
case GDK_KEY_dead_belowdot:
return " \xcc\xa3"; // U+0323
case GDK_KEY_dead_hook:
return " \xcc\x89"; // U+0309
case GDK_KEY_dead_horn:
return " \xcc\x9b"; // U+031B
case GDK_KEY_dead_stroke:
return " \xcc\xb7"; // U+0337
case GDK_KEY_dead_abovecomma:
return " \xcc\x93"; // U+0313
case GDK_KEY_dead_abovereversedcomma:
return " \xcc\x94"; // U+0314
case GDK_KEY_dead_doublegrave:
return " \xcc\x8f"; // U+030F
case GDK_KEY_dead_belowring:
return " \xcc\xa5"; // U+0325
case GDK_KEY_dead_belowmacron:
return " \xcc\xb1"; // U+0331
case GDK_KEY_dead_belowcircumflex:
return " \xcc\xad"; // U+032D
case GDK_KEY_dead_belowtilde:
return " \xcc\xb0"; // U+0330
case GDK_KEY_dead_belowbreve:
return " \xcc\xae"; // U+032E
case GDK_KEY_dead_belowdiaeresis:
return " \xcc\xa4"; // U+0324
case GDK_KEY_dead_invertedbreve:
return " \xcc\x91"; // U+0311
case GDK_KEY_dead_belowcomma:
return " \xcc\xa6"; // U+0326
case GDK_KEY_dead_currency:
// This one is a bit different: instead of adding a diacritic to a
// character, it allows entering of various currency symbols. E.g.,
// dead_currency+e generates the euro sign (€). Combining this dead key
// with space generates the general currency symbol.
return "\xc2\xa4"; // Currency symbol (¤), U+00A4
// I can't find any information about what these do. There is, e.g.,
// "combining latin small letter a" (U+0363) that places a tiny "a" above
// the preceding character (and similar for the other lower-case letters),
// but no equivalent capital versions. These don't show up in Compose.pre,
// so they're probably not used much, if at all.
// case GDK_KEY_dead_a:
// case GDK_KEY_dead_A:
// case GDK_KEY_dead_e:
// case GDK_KEY_dead_E:
// case GDK_KEY_dead_i:
// case GDK_KEY_dead_I:
// case GDK_KEY_dead_o:
// case GDK_KEY_dead_O:
// case GDK_KEY_dead_u:
// case GDK_KEY_dead_U:
// case GDK_KEY_dead_small_schwa:
// case GDK_KEY_dead_capital_schwa:
case GDK_KEY_dead_greek:
// Like dead_currency above, this key is used to generate different
// symbols entirely (greek letters, in this case). E.g., dead_greek+a
// generates Greek alpha (α). Combining this dead key with space generates
// the micro sign (µ), a distinct code point from Greek mu (μ), which is
// generated by dead_greek+m.
return "\xce\xbc"; // Micro symbol (μ), U+00B5
default:
return nullptr;
}
}
protocol::LayoutKeyFunction KeyvalToFunction(guint keyval) {
switch (keyval) {
case GDK_KEY_Control_L:
case GDK_KEY_Control_R:
return protocol::LayoutKeyFunction::CONTROL;
case GDK_KEY_Alt_L:
case GDK_KEY_Alt_R:
return protocol::LayoutKeyFunction::ALT;
case GDK_KEY_Shift_L:
case GDK_KEY_Shift_R:
return protocol::LayoutKeyFunction::SHIFT;
case GDK_KEY_Super_L:
case GDK_KEY_Super_R:
return protocol::LayoutKeyFunction::META;
case GDK_KEY_ISO_Level3_Shift:
return protocol::LayoutKeyFunction::ALT_GR;
case GDK_KEY_ISO_Level5_Shift:
return protocol::LayoutKeyFunction::MOD5;
case GDK_KEY_Multi_key:
return protocol::LayoutKeyFunction::COMPOSE;
case GDK_KEY_Num_Lock:
return protocol::LayoutKeyFunction::NUM_LOCK;
case GDK_KEY_Caps_Lock:
return protocol::LayoutKeyFunction::CAPS_LOCK;
case GDK_KEY_Scroll_Lock:
return protocol::LayoutKeyFunction::SCROLL_LOCK;
case GDK_KEY_BackSpace:
return protocol::LayoutKeyFunction::BACKSPACE;
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
return protocol::LayoutKeyFunction::ENTER;
case GDK_KEY_Tab: // Unshifted
case GDK_KEY_ISO_Left_Tab: // Shifted
case GDK_KEY_KP_Tab:
return protocol::LayoutKeyFunction::TAB;
case GDK_KEY_Insert:
case GDK_KEY_KP_Insert:
return protocol::LayoutKeyFunction::INSERT;
case GDK_KEY_Delete:
case GDK_KEY_KP_Delete:
return protocol::LayoutKeyFunction::DELETE_;
case GDK_KEY_Home:
case GDK_KEY_KP_Home:
return protocol::LayoutKeyFunction::HOME;
case GDK_KEY_End:
case GDK_KEY_KP_End:
return protocol::LayoutKeyFunction::END;
case GDK_KEY_Page_Up:
case GDK_KEY_KP_Page_Up:
return protocol::LayoutKeyFunction::PAGE_UP;
case GDK_KEY_Page_Down:
case GDK_KEY_KP_Page_Down:
return protocol::LayoutKeyFunction::PAGE_DOWN;
case GDK_KEY_Clear:
return protocol::LayoutKeyFunction::CLEAR;
case GDK_KEY_Up:
case GDK_KEY_KP_Up:
return protocol::LayoutKeyFunction::ARROW_UP;
case GDK_KEY_Down:
case GDK_KEY_KP_Down:
return protocol::LayoutKeyFunction::ARROW_DOWN;
case GDK_KEY_Left:
case GDK_KEY_KP_Left:
return protocol::LayoutKeyFunction::ARROW_LEFT;
case GDK_KEY_Right:
case GDK_KEY_KP_Right:
return protocol::LayoutKeyFunction::ARROW_RIGHT;
case GDK_KEY_F1:
case GDK_KEY_KP_F1:
return protocol::LayoutKeyFunction::F1;
case GDK_KEY_F2:
case GDK_KEY_KP_F2:
return protocol::LayoutKeyFunction::F2;
case GDK_KEY_F3:
case GDK_KEY_KP_F3:
return protocol::LayoutKeyFunction::F3;
case GDK_KEY_F4:
case GDK_KEY_KP_F4:
return protocol::LayoutKeyFunction::F4;
case GDK_KEY_F5:
return protocol::LayoutKeyFunction::F5;
case GDK_KEY_F6:
return protocol::LayoutKeyFunction::F6;
case GDK_KEY_F7:
return protocol::LayoutKeyFunction::F7;
case GDK_KEY_F8:
return protocol::LayoutKeyFunction::F8;
case GDK_KEY_F9:
return protocol::LayoutKeyFunction::F9;
case GDK_KEY_F10:
return protocol::LayoutKeyFunction::F10;
case GDK_KEY_F11:
return protocol::LayoutKeyFunction::F11;
case GDK_KEY_F12:
return protocol::LayoutKeyFunction::F12;
case GDK_KEY_F13:
return protocol::LayoutKeyFunction::F13;
case GDK_KEY_F14:
return protocol::LayoutKeyFunction::F14;
case GDK_KEY_F15:
return protocol::LayoutKeyFunction::F15;
case GDK_KEY_F16:
return protocol::LayoutKeyFunction::F16;
case GDK_KEY_F17:
return protocol::LayoutKeyFunction::F17;
case GDK_KEY_F18:
return protocol::LayoutKeyFunction::F18;
case GDK_KEY_F19:
return protocol::LayoutKeyFunction::F19;
case GDK_KEY_F20:
return protocol::LayoutKeyFunction::F20;
case GDK_KEY_F21:
return protocol::LayoutKeyFunction::F21;
case GDK_KEY_F22:
return protocol::LayoutKeyFunction::F22;
case GDK_KEY_F23:
return protocol::LayoutKeyFunction::F23;
case GDK_KEY_F24:
return protocol::LayoutKeyFunction::F24;
case GDK_KEY_Escape:
return protocol::LayoutKeyFunction::ESCAPE;
case GDK_KEY_Menu:
return protocol::LayoutKeyFunction::CONTEXT_MENU;
case GDK_KEY_Pause:
return protocol::LayoutKeyFunction::PAUSE;
case GDK_KEY_Print: // Unshifted
case GDK_KEY_Sys_Req: // Shifted
return protocol::LayoutKeyFunction::PRINT_SCREEN;
case GDK_KEY_Zenkaku_Hankaku: // Unshifted
case GDK_KEY_Kanji: // Shifted
return protocol::LayoutKeyFunction::HANKAKU_ZENKAKU_KANJI;
case GDK_KEY_Henkan:
return protocol::LayoutKeyFunction::HENKAN;
case GDK_KEY_Muhenkan:
return protocol::LayoutKeyFunction::MUHENKAN;
case GDK_KEY_Hiragana_Katakana: // Unshifted
case GDK_KEY_Romaji: // Shifted
return protocol::KATAKANA_HIRAGANA_ROMAJI;
case GDK_KEY_Eisu_toggle:
return protocol::LayoutKeyFunction::EISU;
case GDK_KEY_Hangul:
return protocol::LayoutKeyFunction::HAN_YEONG;
case GDK_KEY_Hangul_Hanja:
return protocol::LayoutKeyFunction::HANJA;
default:
return protocol::LayoutKeyFunction::UNKNOWN;
}
}
} // namespace remoting