OLD | NEW |
(Empty) | |
| 1 // Use of this source code is governed by a BSD-style license that can be |
| 2 // found in the LICENSE file. |
| 3 |
| 4 #include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h" |
| 5 |
| 6 #include <xkbcommon/xkbcommon-names.h> |
| 7 |
| 8 #include "base/logging.h" |
| 9 #include "ui/events/event_constants.h" |
| 10 #include "ui/events/keycodes/dom3/dom_key.h" |
| 11 #include "ui/events/keycodes/dom4/keycode_converter.h" |
| 12 #include "ui/events/ozone/layout/layout_util.h" |
| 13 #include "ui/events/ozone/layout/xkb/xkb_keyboard_code_conversion.h" |
| 14 |
| 15 namespace ui { |
| 16 |
| 17 namespace { |
| 18 |
| 19 // Temporarily hard-code an initial layout to test libxkbcommon. |
| 20 // TODO: remove this after SetCurrentLayoutByName() is implemented. |
| 21 const char* temporary_initial_keymap = |
| 22 "xkb_keymap{" |
| 23 "xkb_keycodes \"evdev_aliases(qwerty)\"{minimum=8;maximum=255;" |
| 24 "<ESC>=9;<AE01>=10;<AE02>=11;<AE03>=12;<AE04>=13;<AE05>=14;" |
| 25 "<AE06>=15;<AE07>=16;<AE08>=17;<AE09>=18;<AE10>=19;<AE11>=20;" |
| 26 "<AE12>=21;<BKSP>=22;<TAB>=23;<AD01>=24;<AD02>=25;<AD03>=26;" |
| 27 "<AD04>=27;<AD05>=28;<AD06>=29;<AD07>=30;<AD08>=31;<AD09>=32;" |
| 28 "<AD10>=33;<AD11>=34;<AD12>=35;<RTRN>=36;<LCTL>=37;<AC01>=38;" |
| 29 "<AC02>=39;<AC03>=40;<AC04>=41;<AC05>=42;<AC06>=43;<AC07>=44;" |
| 30 "<AC08>=45;<AC09>=46;<AC10>=47;<AC11>=48;<TLDE>=49;<LFSH>=50;" |
| 31 "<BKSL>=51;<AB01>=52;<AB02>=53;<AB03>=54;<AB04>=55;<AB05>=56;" |
| 32 "<AB06>=57;<AB07>=58;<AB08>=59;<AB09>=60;<AB10>=61;<RTSH>=62;" |
| 33 "<KPMU>=63;<LALT>=64;<SPCE>=65;<CAPS>=66;<FK01>=67;<FK02>=68;" |
| 34 "<FK03>=69;<FK04>=70;<FK05>=71;<FK06>=72;<FK07>=73;<FK08>=74;" |
| 35 "<FK09>=75;<FK10>=76;<FK11>=95;<FK12>=96;<FK13>=191;<FK14>=192;" |
| 36 "<FK15>=193;<FK16>=194;<FK17>=195;<FK18>=196;<FK19>=197;<FK20>=198;" |
| 37 "<FK21>=199;<FK22>=200;<FK23>=201;<FK24>=202;<LWIN>=133;<RWIN>=134;" |
| 38 "<NMLK>=77;<SCLK>=78;<KP7>=79;<KP8>=80;<KP9>=81;<KPSU>=82;<KP4>=83;" |
| 39 "<KP5>=84;<KP6>=85;<KPAD>=86;<KP1>=87;<KP2>=88;<KP3>=89;<KP0>=90;" |
| 40 "<KPDL>=91;<LVL3>=92;<LSGT>=94;<FK11>=95;<FK12>=96;<KATA>=98;<HIRA>=99;" |
| 41 "<HENK>=100;<HKTG>=101;<MUHE>=102;<KPEN>=104;<RCTL>=105;" |
| 42 "<KPDV>=106;<PRSC>=107;<RALT>=108;<LNFD>=109;<HOME>=110;<UP>=111;" |
| 43 "<PGUP>=112;<LEFT>=113;<RGHT>=114;<END>=115;<DOWN>=116;<PGDN>=117;" |
| 44 "<INS>=118;<DELE>=119;<MUTE>=121;<VOL->=122;<VOL+>=123;<POWR>=124;" |
| 45 "<MDSW>=203;<ALT>=204;<META>=205;<SUPR>=206;<HYPR>=207;};" |
| 46 "xkb_types \"complete\"{virtual_modifiers NumLock,Alt,LevelThree,LAlt," |
| 47 "RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;" |
| 48 "type \"ONE_LEVEL\"{modifiers=none;level_name[Level1]=\"Any\";};" |
| 49 "type \"TWO_LEVEL\"{modifiers=Shift;map[Shift]=Level2;" |
| 50 "level_name[Level1]=\"Base\";level_name[Level2]=\"Shift\";};" |
| 51 "type \"ALPHABETIC\"{modifiers=Shift+Lock;" |
| 52 "map[Shift]=Level2;map[Lock]=Level2;" |
| 53 "level_name[Level1]=\"Base\";level_name[Level2]=\"Caps\";};" |
| 54 "type \"FOUR_LEVEL\"{modifiers=Shift+LevelThree;map[Shift]=Level2;" |
| 55 "map[LevelThree]=Level3;map[Shift+LevelThree]=Level4;" |
| 56 "level_name[Level1]=\"Base\";level_name[Level2]=\"Shift\";" |
| 57 "level_name[Level3]=\"Alt Base\";level_name[Level4]=\"Shift Alt\";};" |
| 58 "type \"KEYPAD\"{modifiers=Shift+NumLock;" |
| 59 "map[Shift]=Level2;map[NumLock]=Level2;" |
| 60 "level_name[Level1]=\"Base\";level_name[Level2]=\"Number\";};};" |
| 61 "xkb_compatibility \"complete\"{virtual_modifiers NumLock,Alt,LevelThree," |
| 62 "LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;" |
| 63 "interpret.useModMapMods=AnyLevel;interpret.repeat=False;" |
| 64 "interpret ISO_Level2_Latch+Exactly(Shift){useModMapMods=level1;" |
| 65 "action=LatchMods(modifiers=Shift,clearLocks,latchToLock);};" |
| 66 "interpret Shift_Lock+AnyOf(Shift+Lock){action=LockMods(modifiers=Shift);};" |
| 67 "interpret Num_Lock+AnyOf(all){virtualModifier=NumLock;" |
| 68 "action=LockMods(modifiers=NumLock);};" |
| 69 "interpret ISO_Level3_Shift+AnyOf(all){virtualModifier=LevelThree;" |
| 70 "useModMapMods=level1;action=SetMods(modifiers=LevelThree,clearLocks);};" |
| 71 "interpret ISO_Level3_Latch+AnyOf(all){" |
| 72 "virtualModifier=LevelThree;useModMapMods=level1;" |
| 73 "action=LatchMods(modifiers=LevelThree,clearLocks,latchToLock);};" |
| 74 "interpret ISO_Level3_Lock+AnyOf(all){virtualModifier=LevelThree;" |
| 75 "useModMapMods=level1;action=LockMods(modifiers=LevelThree);};" |
| 76 "interpret Alt_L+AnyOf(all){virtualModifier=Alt;" |
| 77 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 78 "interpret Alt_R+AnyOf(all){virtualModifier=Alt;" |
| 79 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 80 "interpret Meta_L+AnyOf(all){virtualModifier=Meta;" |
| 81 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 82 "interpret Meta_R+AnyOf(all){virtualModifier=Meta;" |
| 83 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 84 "interpret Super_L+AnyOf(all){virtualModifier=Super;" |
| 85 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 86 "interpret Super_R+AnyOf(all){virtualModifier=Super;" |
| 87 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 88 "interpret Hyper_L+AnyOf(all){virtualModifier=Hyper;" |
| 89 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 90 "interpret Hyper_R+AnyOf(all){virtualModifier=Hyper;" |
| 91 "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| 92 "interpret Mode_switch+AnyOfOrNone(all){virtualModifier=AltGr;" |
| 93 "useModMapMods=level1;action=SetGroup(group=+1);};" |
| 94 "interpret ISO_Level3_Shift+AnyOfOrNone(all){" |
| 95 "action=SetMods(modifiers=LevelThree,clearLocks);};" |
| 96 "interpret ISO_Level3_Latch+AnyOfOrNone(all){" |
| 97 "action=LatchMods(modifiers=LevelThree,clearLocks,latchToLock);};" |
| 98 "interpret ISO_Level3_Lock+AnyOfOrNone(all){" |
| 99 "action=LockMods(modifiers=LevelThree);};" |
| 100 "interpret Alt_L+AnyOfOrNone(all){" |
| 101 "action=SetMods(modifiers=Alt,clearLocks);};" |
| 102 "interpret Alt_R+AnyOfOrNone(all){" |
| 103 "action=SetMods(modifiers=Alt,clearLocks);};" |
| 104 "interpret Meta_L+AnyOfOrNone(all){" |
| 105 "action=SetMods(modifiers=Meta,clearLocks);};" |
| 106 "interpret Meta_R+AnyOfOrNone(all){" |
| 107 "action=SetMods(modifiers=Meta,clearLocks);};" |
| 108 "interpret Super_L+AnyOfOrNone(all){" |
| 109 "action=SetMods(modifiers=Super,clearLocks);};" |
| 110 "interpret Super_R+AnyOfOrNone(all){" |
| 111 "action=SetMods(modifiers=Super,clearLocks);};" |
| 112 "interpret Hyper_L+AnyOfOrNone(all){" |
| 113 "action=SetMods(modifiers=Hyper,clearLocks);};" |
| 114 "interpret Hyper_R+AnyOfOrNone(all){" |
| 115 "action=SetMods(modifiers=Hyper,clearLocks);};" |
| 116 "interpret Shift_L+AnyOfOrNone(all){" |
| 117 "action=SetMods(modifiers=Shift,clearLocks);};" |
| 118 "interpret XF86Switch_VT_1+AnyOfOrNone(all){repeat=True;" |
| 119 "action=SwitchScreen(screen=1,!same);};" |
| 120 "interpret XF86Switch_VT_2+AnyOfOrNone(all){repeat=True;" |
| 121 "action=SwitchScreen(screen=2,!same);};" |
| 122 "interpret XF86Switch_VT_3+AnyOfOrNone(all){repeat=True;" |
| 123 "action=SwitchScreen(screen=3,!same);};" |
| 124 "interpret XF86Switch_VT_4+AnyOfOrNone(all){repeat=True;" |
| 125 "action=SwitchScreen(screen=4,!same);};" |
| 126 "interpret Caps_Lock+AnyOfOrNone(all){action=LockMods(modifiers=Lock);};" |
| 127 "interpret Any+Exactly(Lock){action=LockMods(modifiers=Lock);};" |
| 128 "interpret Any+AnyOf(all){action=SetMods(modifiers=modMapMods,clearLocks);" |
| 129 "};};" |
| 130 "xkb_symbols \"pc_us_inet(evdev)\"{name[group1]=\"English (US)\";" |
| 131 "key<ESC>{[Escape]};key<AE01>{[1,exclam]};key<AE02>{[2,at]};" |
| 132 "key<AE03>{[3,numbersign]};key<AE04>{[4,dollar]};key<AE05>{[5,percent]};" |
| 133 "key<AE06>{[6,asciicircum]};key<AE07>{[7,ampersand]};" |
| 134 "key<AE08>{[8,asterisk]};key<AE09>{[9,parenleft]};" |
| 135 "key<AE10>{[0,parenright]};key<AE11>{[minus,underscore]};" |
| 136 "key<AE12>{[equal,plus]};key<BKSP>{[BackSpace,BackSpace]};" |
| 137 "key<TAB>{[Tab,ISO_Left_Tab]};key<AD01>{[q,Q]};key<AD02>{[w,W]};" |
| 138 "key<AD03>{[e,E]};key<AD04>{[r,R]};key<AD05>{[t,T]};key<AD06>{[y,Y]};" |
| 139 "key<AD07>{[u,U]};key<AD08>{[i,I]};key<AD09>{[o,O]};key<AD10>{[p,P]};" |
| 140 "key<AD11>{[bracketleft,braceleft]};key<AD12>{[bracketright,braceright]};" |
| 141 "key<RTRN>{[Return]};key<LCTL>{[Control_L]};key<AC01>{[a,A]};" |
| 142 "key<AC02>{[s,S]};key<AC03>{[d,D]};key<AC04>{[f,F]};key<AC05>{[g,G]};" |
| 143 "key<AC06>{[h,H]};key<AC07>{[j,J]};key<AC08>{[k,K]};key<AC09>{[l,L]};" |
| 144 "key<AC10>{[semicolon,colon]};key<AC11>{[apostrophe,quotedbl]};" |
| 145 "key<TLDE>{[grave,asciitilde]};key<LFSH>{[Shift_L]};" |
| 146 "key<BKSL>{[backslash,bar]};key<AB01>{[z,Z]};key<AB02>{[x,X]};" |
| 147 "key<AB03>{[c,C]};key<AB04>{[v,V]};key<AB05>{[b,B]};key<AB06>{[n,N]};" |
| 148 "key<AB07>{[m,M]};key<AB08>{[comma,less]};key<AB09>{[period,greater]};" |
| 149 "key<AB10>{[slash,question]};key<RTSH>{[Shift_R]};" |
| 150 "key<KPMU>{[KP_Multiply,KP_Multiply]};key<LALT>{[Alt_L,Meta_L]};" |
| 151 "key<SPCE>{[space]};key<CAPS>{[Caps_Lock]};key<FK01>{[F1,F1]};" |
| 152 "key<FK02>{[F2,F2]};key<FK03>{[F3,F3]};key<FK04>{[F4,F4]};" |
| 153 "key<FK05>{[F5,F5]};key<FK06>{[F6,F6]};key<FK07>{[F7,F7]};" |
| 154 "key<FK08>{[F8,F8]};key<FK09>{[F9,F9]};key<FK10>{[F10,F10]};" |
| 155 "key<FK11>{[F11,F11]};key<FK12>{[F12,F12]};key<FK13>{[F13,F13]};" |
| 156 "key<FK14>{[F14,F14]};key<FK15>{[F15,F15]};key<FK16>{[F16,F16]};" |
| 157 "key<FK17>{[F17,F17]};key<FK18>{[F18,F18]};key<FK19>{[F19,F19]};" |
| 158 "key<FK20>{[F20,F20]};key<FK21>{[F21,F21]};key<FK22>{[F22,F22]};" |
| 159 "key<FK23>{[F23,F23]}; key<FK24>{[F24,F24]};" |
| 160 "key<NMLK>{[Num_Lock]};key<SCLK>{[Scroll_Lock]};" |
| 161 "key<KP7>{[KP_Home,KP_7]};key<KP8>{[KP_Up,KP_8]};key<KP9>{[KP_Prior,KP_9]};" |
| 162 "key<KPSU>{[KP_Subtract,KP_Subtract]};key<KP4>{[KP_Left,KP_4]};" |
| 163 "key<KP5>{[KP_Begin,KP_5]};key<KP6>{[KP_Right,KP_6]};" |
| 164 "key<KPAD>{[KP_Add,KP_Add]};key<KP1>{[KP_End,KP_1]};" |
| 165 "key<KP2>{[KP_Down,KP_2]};key<KP3>{[KP_Next,KP_3]};" |
| 166 "key<KP0>{[KP_Insert,KP_0]};key<KPDL>{[KP_Delete,KP_Decimal]};" |
| 167 "key<LVL3>{[ISO_Level3_Shift]};key<LSGT>{[less,greater, bar,brokenbar]};" |
| 168 "key<FK11>{[F11,F11]};key<FK12>{[F12,F12]};key<KATA>{[Katakana]};" |
| 169 "key<HIRA>{[Hiragana]};key<HENK>{[Henkan_Mode]};" |
| 170 "key<HKTG>{[Hiragana_Katakana]};key<MUHE>{[Muhenkan]};" |
| 171 "key<KPEN>{[KP_Enter]};key<RCTL>{[Control_R]};key<MDSW>{[Mode_switch]};" |
| 172 "key<KPDV>{[KP_Divide,KP_Divide]};key<PRSC>{[Print,Sys_Req]};" |
| 173 "key<RALT>{type=\"TWO_LEVEL\",symbols[Group1]=[Alt_R,Meta_R]};" |
| 174 "key<LNFD>{[Linefeed]};key<HOME>{[Home]};key<UP>{[Up]};key<PGUP>{[Prior]};" |
| 175 "key<LEFT>{[Left]};key<RGHT>{[Right]};key<END>{[End]};key<DOWN>{[Down]};" |
| 176 "key<PGDN>{[Next]};key<INS>{[Insert]};key<DELE>{[Delete]};" |
| 177 "key<MUTE>{[XF86AudioMute]};key<VOL->{[XF86AudioLowerVolume]};" |
| 178 "key<VOL+>{[XF86AudioRaiseVolume]};key<POWR>{[XF86PowerOff]};" |
| 179 "key<ALT>{[NoSymbol,Alt_L]};key<META>{[NoSymbol,Meta_L]};" |
| 180 "key<SUPR>{[NoSymbol,Super_L]};key<HYPR>{[NoSymbol,Hyper_L]};" |
| 181 "key<LWIN>{[Super_L,Super_L]};key<RWIN>{[Super_R,Super_R]};" |
| 182 "modifier_map Control{<LCTL>};modifier_map Shift{<LFSH>};" |
| 183 "modifier_map Shift{<RTSH>};modifier_map Mod1{<LALT>};" |
| 184 "modifier_map Lock{<CAPS>};modifier_map Mod2{<NMLK>};" |
| 185 "modifier_map Mod5{<LVL3>};modifier_map Control{<RCTL>};" |
| 186 "modifier_map Mod1{<RALT>};modifier_map Mod5{<MDSW>};" |
| 187 "modifier_map Mod1{<META>};modifier_map Mod4{<SUPR>};" |
| 188 "modifier_map Mod4{<LWIN>};modifier_map Mod4{<RWIN>};" |
| 189 "modifier_map Mod4{<HYPR>};};};"; |
| 190 |
| 191 DomKey CharacterToDomKey(base::char16 character) { |
| 192 switch (character) { |
| 193 case 0x08: |
| 194 return DomKey::BACKSPACE; |
| 195 case 0x09: |
| 196 return DomKey::TAB; |
| 197 case 0x0A: |
| 198 case 0x0D: |
| 199 return DomKey::ENTER; |
| 200 case 0x1B: |
| 201 return DomKey::ESCAPE; |
| 202 default: |
| 203 return DomKey::CHARACTER; |
| 204 } |
| 205 } |
| 206 |
| 207 KeyboardCode DifficultKeyboardCode(DomCode dom_code, |
| 208 int flags, |
| 209 DomKey dom_key, |
| 210 base::char16 character) { |
| 211 // TODO(kpschoedel): correct key_code for non-US layouts along the lines |
| 212 // of KeyboardCodeFromXKeyEvent() |
| 213 return DomCodeToKeyboardCode(dom_code); |
| 214 } |
| 215 |
| 216 } // anonymous namespace |
| 217 |
| 218 XkbKeyCodeConverter::XkbKeyCodeConverter() { |
| 219 } |
| 220 |
| 221 XkbKeyCodeConverter::~XkbKeyCodeConverter() { |
| 222 } |
| 223 |
| 224 XkbKeyboardLayoutEngine::XkbKeyboardLayoutEngine( |
| 225 const XkbKeyCodeConverter& converter) |
| 226 : key_code_converter_(converter) { |
| 227 // TODO: add XKB_CONTEXT_NO_ENVIRONMENT_NAMES |
| 228 xkb_context_.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES)); |
| 229 |
| 230 // Temporary initial keymap to avoid file I/O on initialization. |
| 231 // TODO: remove this after SetCurrentLayoutByName() is implemented. |
| 232 xkb_keymap* keymap = xkb_keymap_new_from_string( |
| 233 xkb_context_.get(), temporary_initial_keymap, XKB_KEYMAP_FORMAT_TEXT_V1, |
| 234 XKB_KEYMAP_COMPILE_NO_FLAGS); |
| 235 SetKeymap(keymap); |
| 236 } |
| 237 |
| 238 XkbKeyboardLayoutEngine::~XkbKeyboardLayoutEngine() { |
| 239 } |
| 240 |
| 241 bool XkbKeyboardLayoutEngine::CanSetCurrentLayout() const { |
| 242 #if defined(OS_CHROMEOS) |
| 243 return true; |
| 244 #else |
| 245 return false; |
| 246 #endif |
| 247 } |
| 248 |
| 249 bool XkbKeyboardLayoutEngine::SetCurrentLayoutByName( |
| 250 const std::string& layout_name) { |
| 251 #if defined(OS_CHROMEOS) |
| 252 // TODO(fengyuan) |
| 253 // End successful set with SetKeymap(keymap) to update other fields. |
| 254 return false; |
| 255 #else |
| 256 return false; |
| 257 #endif |
| 258 } |
| 259 |
| 260 bool XkbKeyboardLayoutEngine::UsesISOLevel5Shift() const { |
| 261 // NOTIMPLEMENTED(); |
| 262 return false; |
| 263 } |
| 264 |
| 265 bool XkbKeyboardLayoutEngine::UsesAltGr() const { |
| 266 // NOTIMPLEMENTED(); |
| 267 return false; |
| 268 } |
| 269 |
| 270 bool XkbKeyboardLayoutEngine::Lookup(DomCode dom_code, |
| 271 int flags, |
| 272 DomKey* dom_key, |
| 273 base::char16* character, |
| 274 KeyboardCode* key_code) const { |
| 275 xkb_keycode_t xkb_keycode = key_code_converter_.DomCodeToXkbKeyCode(dom_code); |
| 276 if (xkb_keycode == key_code_converter_.InvalidXkbKeyCode()) { |
| 277 LOG(ERROR) << "No XKB keycode for DomCode 0x" << std::hex |
| 278 << static_cast<int>(dom_code) << " '" |
| 279 << KeycodeConverter::DomCodeToCodeString(dom_code) << "'"; |
| 280 return false; |
| 281 } |
| 282 xkb_mod_mask_t xkb_flags = EventFlagsToXkbFlags(flags); |
| 283 xkb_keysym_t xkb_keysym; |
| 284 if (!XkbLookup(xkb_keycode, xkb_flags, &xkb_keysym, character)) |
| 285 return false; |
| 286 *dom_key = XkbKeySymToDomKey(xkb_keysym); |
| 287 if (*dom_key == DomKey::NONE) { |
| 288 *dom_key = CharacterToDomKey(*character); |
| 289 *key_code = DifficultKeyboardCode(dom_code, flags, *dom_key, *character); |
| 290 } else if (*dom_key == DomKey::DEAD) { |
| 291 *character = XkbKeySymDeadKey(xkb_keysym); |
| 292 *key_code = DomCodeToKeyboardCode(dom_code); |
| 293 } else { |
| 294 *key_code = NonPrintableDomKeyToKeyboardCode(*dom_key); |
| 295 if (*key_code == VKEY_UNKNOWN) |
| 296 *key_code = DomCodeToKeyboardCode(dom_code); |
| 297 } |
| 298 return true; |
| 299 } |
| 300 |
| 301 void XkbKeyboardLayoutEngine::SetKeymap(xkb_keymap* keymap) { |
| 302 xkb_state_.reset(xkb_state_new(keymap)); |
| 303 // Update flag map. |
| 304 static const struct { |
| 305 int ui_flag; |
| 306 const char* xkb_name; |
| 307 } flags[] = {{ui::EF_CONTROL_DOWN, XKB_MOD_NAME_CTRL}, |
| 308 {ui::EF_SHIFT_DOWN, XKB_MOD_NAME_SHIFT}, |
| 309 {ui::EF_ALT_DOWN, XKB_MOD_NAME_ALT}, |
| 310 {ui::EF_CAPS_LOCK_DOWN, XKB_MOD_NAME_CAPS}, |
| 311 {ui::EF_COMMAND_DOWN, XKB_MOD_NAME_LOGO}, |
| 312 {ui::EF_NUMPAD_KEY, XKB_MOD_NAME_NUM}, |
| 313 {ui::EF_MOD3_DOWN, "Mod3"}, |
| 314 {ui::EF_ALTGR_DOWN, "Mod5"}}; |
| 315 xkb_flag_map_.clear(); |
| 316 xkb_flag_map_.resize(arraysize(flags)); |
| 317 for (size_t i = 0; i < arraysize(flags); ++i) { |
| 318 xkb_mod_index_t index = xkb_keymap_mod_get_index(keymap, flags[i].xkb_name); |
| 319 if (index == XKB_MOD_INVALID) { |
| 320 DVLOG(3) << "XKB keyboard layout does not contain " << flags[i].xkb_name; |
| 321 } else { |
| 322 xkb_mod_mask_t flag = static_cast<xkb_mod_mask_t>(1) << index; |
| 323 XkbFlagMapEntry e = {flags[i].ui_flag, flag}; |
| 324 xkb_flag_map_.push_back(e); |
| 325 } |
| 326 } |
| 327 } |
| 328 |
| 329 xkb_mod_mask_t XkbKeyboardLayoutEngine::EventFlagsToXkbFlags( |
| 330 int ui_flags) const { |
| 331 xkb_mod_mask_t xkb_flags = 0; |
| 332 for (const auto& entry : xkb_flag_map_) { |
| 333 if (ui_flags & entry.ui_flag) |
| 334 xkb_flags |= entry.xkb_flag; |
| 335 } |
| 336 return xkb_flags; |
| 337 } |
| 338 |
| 339 bool XkbKeyboardLayoutEngine::XkbLookup(xkb_keycode_t xkb_keycode, |
| 340 xkb_mod_mask_t xkb_flags, |
| 341 xkb_keysym_t* xkb_keysym, |
| 342 base::char16* character) const { |
| 343 if (!xkb_state_) { |
| 344 LOG(ERROR) << "No current XKB state"; |
| 345 return false; |
| 346 } |
| 347 xkb_state_update_mask(xkb_state_.get(), xkb_flags, 0, 0, 0, 0, 0); |
| 348 *xkb_keysym = xkb_state_key_get_one_sym(xkb_state_.get(), xkb_keycode); |
| 349 if (*xkb_keysym == XKB_KEY_NoSymbol) |
| 350 return false; |
| 351 uint32_t c = xkb_state_key_get_utf32(xkb_state_.get(), xkb_keycode); |
| 352 DLOG_IF(ERROR, c != (c & 0xFFFF)) << "Non-BMP character:" << c; |
| 353 *character = static_cast<base::char16>(c); |
| 354 return true; |
| 355 } |
| 356 |
| 357 } // namespace ui |
OLD | NEW |