Chromium Code Reviews| Index: ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| index a756db9131a69dfdc20747c23bf5f8514021a2f6..86808cb842a3431fbd88ee652ffaf5291aa16538 100644 |
| --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| @@ -6,7 +6,10 @@ |
| #include <xkbcommon/xkbcommon-names.h> |
| +#include "base/bind.h" |
| +#include "base/location.h" |
| #include "base/logging.h" |
| +#include "base/threading/worker_pool.h" |
| #include "ui/events/event_constants.h" |
| #include "ui/events/keycodes/dom3/dom_code.h" |
| #include "ui/events/keycodes/dom3/dom_key.h" |
| @@ -18,6 +21,177 @@ namespace ui { |
| namespace { |
| +// Fallback keymap - us-qwerty. |
| +const char* us_keymap = |
| + "xkb_keymap{" |
| + "xkb_keycodes \"evdev_aliases(qwerty)\"{minimum=8;maximum=255;" |
| + "<ESC>=9;<AE01>=10;<AE02>=11;<AE03>=12;<AE04>=13;<AE05>=14;" |
| + "<AE06>=15;<AE07>=16;<AE08>=17;<AE09>=18;<AE10>=19;<AE11>=20;" |
| + "<AE12>=21;<BKSP>=22;<TAB>=23;<AD01>=24;<AD02>=25;<AD03>=26;" |
| + "<AD04>=27;<AD05>=28;<AD06>=29;<AD07>=30;<AD08>=31;<AD09>=32;" |
| + "<AD10>=33;<AD11>=34;<AD12>=35;<RTRN>=36;<LCTL>=37;<AC01>=38;" |
| + "<AC02>=39;<AC03>=40;<AC04>=41;<AC05>=42;<AC06>=43;<AC07>=44;" |
| + "<AC08>=45;<AC09>=46;<AC10>=47;<AC11>=48;<TLDE>=49;<LFSH>=50;" |
| + "<BKSL>=51;<AB01>=52;<AB02>=53;<AB03>=54;<AB04>=55;<AB05>=56;" |
| + "<AB06>=57;<AB07>=58;<AB08>=59;<AB09>=60;<AB10>=61;<RTSH>=62;" |
| + "<KPMU>=63;<LALT>=64;<SPCE>=65;<CAPS>=66;<FK01>=67;<FK02>=68;" |
| + "<FK03>=69;<FK04>=70;<FK05>=71;<FK06>=72;<FK07>=73;<FK08>=74;" |
| + "<FK09>=75;<FK10>=76;<FK11>=95;<FK12>=96;<FK13>=191;<FK14>=192;" |
| + "<FK15>=193;<FK16>=194;<FK17>=195;<FK18>=196;<FK19>=197;<FK20>=198;" |
| + "<FK21>=199;<FK22>=200;<FK23>=201;<FK24>=202;<LWIN>=133;<RWIN>=134;" |
| + "<NMLK>=77;<SCLK>=78;<KP7>=79;<KP8>=80;<KP9>=81;<KPSU>=82;<KP4>=83;" |
| + "<KP5>=84;<KP6>=85;<KPAD>=86;<KP1>=87;<KP2>=88;<KP3>=89;<KP0>=90;" |
| + "<KPDL>=91;<LVL3>=92;<LSGT>=94;<FK11>=95;<FK12>=96;<KATA>=98;<HIRA>=99;" |
| + "<HENK>=100;<HKTG>=101;<MUHE>=102;<KPEN>=104;<RCTL>=105;" |
| + "<KPDV>=106;<PRSC>=107;<RALT>=108;<LNFD>=109;<HOME>=110;<UP>=111;" |
| + "<PGUP>=112;<LEFT>=113;<RGHT>=114;<END>=115;<DOWN>=116;<PGDN>=117;" |
| + "<INS>=118;<DELE>=119;<MUTE>=121;<VOL->=122;<VOL+>=123;<POWR>=124;" |
| + "<MDSW>=203;<ALT>=204;<META>=205;<SUPR>=206;<HYPR>=207;};" |
| + "xkb_types \"complete\"{virtual_modifiers NumLock,Alt,LevelThree,LAlt," |
| + "RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;" |
| + "type \"ONE_LEVEL\"{modifiers=none;level_name[Level1]=\"Any\";};" |
| + "type \"TWO_LEVEL\"{modifiers=Shift;map[Shift]=Level2;" |
| + "level_name[Level1]=\"Base\";level_name[Level2]=\"Shift\";};" |
| + "type \"ALPHABETIC\"{modifiers=Shift+Lock;" |
| + "map[Shift]=Level2;map[Lock]=Level2;" |
| + "level_name[Level1]=\"Base\";level_name[Level2]=\"Caps\";};" |
| + "type \"FOUR_LEVEL\"{modifiers=Shift+LevelThree;map[Shift]=Level2;" |
| + "map[LevelThree]=Level3;map[Shift+LevelThree]=Level4;" |
| + "level_name[Level1]=\"Base\";level_name[Level2]=\"Shift\";" |
| + "level_name[Level3]=\"Alt Base\";level_name[Level4]=\"Shift Alt\";};" |
| + "type \"KEYPAD\"{modifiers=Shift+NumLock;" |
| + "map[Shift]=Level2;map[NumLock]=Level2;" |
| + "level_name[Level1]=\"Base\";level_name[Level2]=\"Number\";};};" |
| + "xkb_compatibility \"complete\"{virtual_modifiers NumLock,Alt,LevelThree," |
| + "LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;" |
| + "interpret.useModMapMods=AnyLevel;interpret.repeat=False;" |
| + "interpret ISO_Level2_Latch+Exactly(Shift){useModMapMods=level1;" |
| + "action=LatchMods(modifiers=Shift,clearLocks,latchToLock);};" |
| + "interpret Shift_Lock+AnyOf(Shift+Lock){action=LockMods(modifiers=Shift);};" |
| + "interpret Num_Lock+AnyOf(all){virtualModifier=NumLock;" |
| + "action=LockMods(modifiers=NumLock);};" |
| + "interpret ISO_Level3_Shift+AnyOf(all){virtualModifier=LevelThree;" |
| + "useModMapMods=level1;action=SetMods(modifiers=LevelThree,clearLocks);};" |
| + "interpret ISO_Level3_Latch+AnyOf(all){" |
| + "virtualModifier=LevelThree;useModMapMods=level1;" |
| + "action=LatchMods(modifiers=LevelThree,clearLocks,latchToLock);};" |
| + "interpret ISO_Level3_Lock+AnyOf(all){virtualModifier=LevelThree;" |
| + "useModMapMods=level1;action=LockMods(modifiers=LevelThree);};" |
| + "interpret Alt_L+AnyOf(all){virtualModifier=Alt;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Alt_R+AnyOf(all){virtualModifier=Alt;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Meta_L+AnyOf(all){virtualModifier=Meta;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Meta_R+AnyOf(all){virtualModifier=Meta;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Super_L+AnyOf(all){virtualModifier=Super;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Super_R+AnyOf(all){virtualModifier=Super;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Hyper_L+AnyOf(all){virtualModifier=Hyper;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Hyper_R+AnyOf(all){virtualModifier=Hyper;" |
| + "action=SetMods(modifiers=modMapMods,clearLocks);};" |
| + "interpret Mode_switch+AnyOfOrNone(all){virtualModifier=AltGr;" |
| + "useModMapMods=level1;action=SetGroup(group=+1);};" |
| + "interpret ISO_Level3_Shift+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=LevelThree,clearLocks);};" |
| + "interpret ISO_Level3_Latch+AnyOfOrNone(all){" |
| + "action=LatchMods(modifiers=LevelThree,clearLocks,latchToLock);};" |
| + "interpret ISO_Level3_Lock+AnyOfOrNone(all){" |
| + "action=LockMods(modifiers=LevelThree);};" |
| + "interpret Alt_L+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Alt,clearLocks);};" |
| + "interpret Alt_R+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Alt,clearLocks);};" |
| + "interpret Meta_L+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Meta,clearLocks);};" |
| + "interpret Meta_R+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Meta,clearLocks);};" |
| + "interpret Super_L+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Super,clearLocks);};" |
| + "interpret Super_R+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Super,clearLocks);};" |
| + "interpret Hyper_L+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Hyper,clearLocks);};" |
| + "interpret Hyper_R+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Hyper,clearLocks);};" |
| + "interpret Shift_L+AnyOfOrNone(all){" |
| + "action=SetMods(modifiers=Shift,clearLocks);};" |
| + "interpret XF86Switch_VT_1+AnyOfOrNone(all){repeat=True;" |
| + "action=SwitchScreen(screen=1,!same);};" |
| + "interpret XF86Switch_VT_2+AnyOfOrNone(all){repeat=True;" |
| + "action=SwitchScreen(screen=2,!same);};" |
| + "interpret XF86Switch_VT_3+AnyOfOrNone(all){repeat=True;" |
| + "action=SwitchScreen(screen=3,!same);};" |
| + "interpret XF86Switch_VT_4+AnyOfOrNone(all){repeat=True;" |
| + "action=SwitchScreen(screen=4,!same);};" |
| + "interpret Caps_Lock+AnyOfOrNone(all){action=LockMods(modifiers=Lock);};" |
| + "interpret Any+Exactly(Lock){action=LockMods(modifiers=Lock);};" |
| + "interpret Any+AnyOf(all){action=SetMods(modifiers=modMapMods,clearLocks);" |
| + "};};" |
| + "xkb_symbols \"pc_us_inet(evdev)\"{name[group1]=\"English (US)\";" |
| + "key<ESC>{[Escape]};key<AE01>{[1,exclam]};key<AE02>{[2,at]};" |
| + "key<AE03>{[3,numbersign]};key<AE04>{[4,dollar]};key<AE05>{[5,percent]};" |
| + "key<AE06>{[6,asciicircum]};key<AE07>{[7,ampersand]};" |
| + "key<AE08>{[8,asterisk]};key<AE09>{[9,parenleft]};" |
| + "key<AE10>{[0,parenright]};key<AE11>{[minus,underscore]};" |
| + "key<AE12>{[equal,plus]};key<BKSP>{[BackSpace,BackSpace]};" |
| + "key<TAB>{[Tab,ISO_Left_Tab]};key<AD01>{[q,Q]};key<AD02>{[w,W]};" |
| + "key<AD03>{[e,E]};key<AD04>{[r,R]};key<AD05>{[t,T]};key<AD06>{[y,Y]};" |
| + "key<AD07>{[u,U]};key<AD08>{[i,I]};key<AD09>{[o,O]};key<AD10>{[p,P]};" |
| + "key<AD11>{[bracketleft,braceleft]};key<AD12>{[bracketright,braceright]};" |
| + "key<RTRN>{[Return]};key<LCTL>{[Control_L]};key<AC01>{[a,A]};" |
| + "key<AC02>{[s,S]};key<AC03>{[d,D]};key<AC04>{[f,F]};key<AC05>{[g,G]};" |
| + "key<AC06>{[h,H]};key<AC07>{[j,J]};key<AC08>{[k,K]};key<AC09>{[l,L]};" |
| + "key<AC10>{[semicolon,colon]};key<AC11>{[apostrophe,quotedbl]};" |
| + "key<TLDE>{[grave,asciitilde]};key<LFSH>{[Shift_L]};" |
| + "key<BKSL>{[backslash,bar]};key<AB01>{[z,Z]};key<AB02>{[x,X]};" |
| + "key<AB03>{[c,C]};key<AB04>{[v,V]};key<AB05>{[b,B]};key<AB06>{[n,N]};" |
| + "key<AB07>{[m,M]};key<AB08>{[comma,less]};key<AB09>{[period,greater]};" |
| + "key<AB10>{[slash,question]};key<RTSH>{[Shift_R]};" |
| + "key<KPMU>{[KP_Multiply,KP_Multiply]};key<LALT>{[Alt_L,Meta_L]};" |
| + "key<SPCE>{[space]};key<CAPS>{[Caps_Lock]};key<FK01>{[F1,F1]};" |
| + "key<FK02>{[F2,F2]};key<FK03>{[F3,F3]};key<FK04>{[F4,F4]};" |
| + "key<FK05>{[F5,F5]};key<FK06>{[F6,F6]};key<FK07>{[F7,F7]};" |
| + "key<FK08>{[F8,F8]};key<FK09>{[F9,F9]};key<FK10>{[F10,F10]};" |
| + "key<FK11>{[F11,F11]};key<FK12>{[F12,F12]};key<FK13>{[F13,F13]};" |
| + "key<FK14>{[F14,F14]};key<FK15>{[F15,F15]};key<FK16>{[F16,F16]};" |
| + "key<FK17>{[F17,F17]};key<FK18>{[F18,F18]};key<FK19>{[F19,F19]};" |
| + "key<FK20>{[F20,F20]};key<FK21>{[F21,F21]};key<FK22>{[F22,F22]};" |
| + "key<FK23>{[F23,F23]}; key<FK24>{[F24,F24]};" |
| + "key<NMLK>{[Num_Lock]};key<SCLK>{[Scroll_Lock]};" |
| + "key<KP7>{[KP_Home,KP_7]};key<KP8>{[KP_Up,KP_8]};key<KP9>{[KP_Prior,KP_9]};" |
| + "key<KPSU>{[KP_Subtract,KP_Subtract]};key<KP4>{[KP_Left,KP_4]};" |
| + "key<KP5>{[KP_Begin,KP_5]};key<KP6>{[KP_Right,KP_6]};" |
| + "key<KPAD>{[KP_Add,KP_Add]};key<KP1>{[KP_End,KP_1]};" |
| + "key<KP2>{[KP_Down,KP_2]};key<KP3>{[KP_Next,KP_3]};" |
| + "key<KP0>{[KP_Insert,KP_0]};key<KPDL>{[KP_Delete,KP_Decimal]};" |
| + "key<LVL3>{[ISO_Level3_Shift]};key<LSGT>{[less,greater, bar,brokenbar]};" |
| + "key<FK11>{[F11,F11]};key<FK12>{[F12,F12]};key<KATA>{[Katakana]};" |
| + "key<HIRA>{[Hiragana]};key<HENK>{[Henkan_Mode]};" |
| + "key<HKTG>{[Hiragana_Katakana]};key<MUHE>{[Muhenkan]};" |
| + "key<KPEN>{[KP_Enter]};key<RCTL>{[Control_R]};key<MDSW>{[Mode_switch]};" |
| + "key<KPDV>{[KP_Divide,KP_Divide]};key<PRSC>{[Print,Sys_Req]};" |
| + "key<RALT>{type=\"TWO_LEVEL\",symbols[Group1]=[Alt_R,Meta_R]};" |
| + "key<LNFD>{[Linefeed]};key<HOME>{[Home]};key<UP>{[Up]};key<PGUP>{[Prior]};" |
| + "key<LEFT>{[Left]};key<RGHT>{[Right]};key<END>{[End]};key<DOWN>{[Down]};" |
| + "key<PGDN>{[Next]};key<INS>{[Insert]};key<DELE>{[Delete]};" |
| + "key<MUTE>{[XF86AudioMute]};key<VOL->{[XF86AudioLowerVolume]};" |
| + "key<VOL+>{[XF86AudioRaiseVolume]};key<POWR>{[XF86PowerOff]};" |
| + "key<ALT>{[NoSymbol,Alt_L]};key<META>{[NoSymbol,Meta_L]};" |
| + "key<SUPR>{[NoSymbol,Super_L]};key<HYPR>{[NoSymbol,Hyper_L]};" |
| + "key<LWIN>{[Super_L,Super_L]};key<RWIN>{[Super_R,Super_R]};" |
| + "modifier_map Control{<LCTL>};modifier_map Shift{<LFSH>};" |
| + "modifier_map Shift{<RTSH>};modifier_map Mod1{<LALT>};" |
| + "modifier_map Lock{<CAPS>};modifier_map Mod2{<NMLK>};" |
| + "modifier_map Mod5{<LVL3>};modifier_map Control{<RCTL>};" |
| + "modifier_map Mod1{<RALT>};modifier_map Mod5{<MDSW>};" |
| + "modifier_map Mod1{<META>};modifier_map Mod4{<SUPR>};" |
| + "modifier_map Mod4{<LWIN>};modifier_map Mod4{<RWIN>};" |
| + "modifier_map Mod4{<HYPR>};};};"; |
| + |
| DomKey CharacterToDomKey(base::char16 character) { |
| switch (character) { |
| case 0x08: |
| @@ -618,6 +792,60 @@ const PrintableSimpleEntry kSimpleMap[] = { |
| } // anonymous namespace |
| +XkbKeyboardLayoutEngine::XkbKeymapLoader::XkbKeymapLoader( |
| + XkbKeyboardLayoutEngine* layout_engine) : layout_engine_(layout_engine) { |
| +} |
| + |
| +void XkbKeyboardLayoutEngine::XkbKeymapLoader::loadKeymap( |
| + const std::string& layout_name) { |
| + size_t dash_index = layout_name.find('-'); |
| + size_t parentheses_index = layout_name.find('('); |
| + std::string layout_id = layout_name; |
| + std::string layout_variant = ""; |
| + if (parentheses_index != std::string::npos) { |
| + layout_id = layout_name.substr(0, parentheses_index); |
| + size_t close_index = layout_name.find(')', parentheses_index); |
| + if (close_index == std::string::npos) |
| + close_index = layout_name.size(); |
| + layout_variant = layout_name.substr(parentheses_index + 1, |
| + close_index - parentheses_index - 1); |
| + } else if (dash_index != std::string::npos) { |
| + layout_id = layout_name.substr(0, dash_index); |
| + layout_variant = layout_name.substr(dash_index + 1); |
| + } |
| + names = new xkb_rule_names { |
| + .rules = NULL, |
| + .model = "pc101", |
| + .layout = layout_id.c_str(), |
| + .variant = layout_variant.c_str(), |
| + .options = "" |
| + }; |
| + base::WorkerPool::PostTask( |
| + FROM_HERE, |
| + base::Bind(&XkbKeyboardLayoutEngine::XkbKeymapLoader::startLoadKeymap, |
| + this, |
| + layout_name, |
| + base::Unretained(names)), |
| + true); |
| +} |
| + |
| +void XkbKeyboardLayoutEngine::XkbKeymapLoader::startLoadKeymap( |
| + const std::string& layout_name, xkb_rule_names* names) { |
| + xkb_keymap* keymap = xkb_keymap_new_from_names( |
| + layout_engine_->xkb_context_.get(), |
| + names, |
| + XKB_KEYMAP_COMPILE_NO_FLAGS); |
| + |
| + delete names; |
| + if (keymap) { |
|
Shu Chen
2014/12/24 02:18:45
Please move the below block to UI thread via PostT
FengYuan
2014/12/26 02:42:20
Done.
|
| + layout_engine_->xkb_keymaps_[layout_name] = keymap; |
| + layout_engine_->SetKeymap(keymap); |
| + } else { |
| + // If keymap file failed to load, use the default us-qwerty keymap. |
| + layout_engine_->SetCurrentLayoutByName("us"); |
|
Shu Chen
2014/12/24 02:18:45
It'd be better to do:
if (!keymap)
keymap = lay
FengYuan
2014/12/26 02:42:20
Done.
|
| + } |
| +} |
| + |
| XkbKeyCodeConverter::XkbKeyCodeConverter() { |
| } |
| @@ -631,9 +859,20 @@ XkbKeyboardLayoutEngine::XkbKeyboardLayoutEngine( |
| xkb_context_.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES)); |
| xkb_context_include_path_append(xkb_context_.get(), |
| "/usr/share/X11/xkb"); |
| + xkb_keymap* keymap = xkb_keymap_new_from_string( |
| + xkb_context_.get(), us_keymap, XKB_KEYMAP_FORMAT_TEXT_V1, |
| + XKB_KEYMAP_COMPILE_NO_FLAGS); |
| + xkb_keymaps_["us"] = keymap; |
| + SetKeymap(keymap); |
| } |
| XkbKeyboardLayoutEngine::~XkbKeyboardLayoutEngine() { |
| + std::map<std::string, xkb_keymap*>::const_iterator it = xkb_keymaps_.begin(); |
| + for(;it != xkb_keymaps_.end(); ++it) { |
| + xkb_keymap_unref(it->second); |
| + } |
| + if (keymap_loader_) |
| + delete keymap_loader_; |
|
Shu Chen
2014/12/24 02:18:45
Please make keymap_loader_ as scoped_ptr.
FengYuan
2014/12/26 02:42:20
Done.
|
| } |
| bool XkbKeyboardLayoutEngine::CanSetCurrentLayout() const { |
| @@ -647,35 +886,15 @@ bool XkbKeyboardLayoutEngine::CanSetCurrentLayout() const { |
| bool XkbKeyboardLayoutEngine::SetCurrentLayoutByName( |
| const std::string& layout_name) { |
| #if defined(OS_CHROMEOS) |
| - size_t dash_index = layout_name.find('-'); |
| - size_t parentheses_index = layout_name.find('('); |
| - std::string layout_id = layout_name; |
| - std::string layout_variant = ""; |
| - if (parentheses_index != std::string::npos) { |
| - layout_id = layout_name.substr(0, parentheses_index); |
| - size_t close_index = layout_name.find(')', parentheses_index); |
| - if (close_index == std::string::npos) |
| - close_index = layout_name.size(); |
| - layout_variant = layout_name.substr(parentheses_index + 1, |
| - close_index - parentheses_index - 1); |
| - } else if (dash_index != std::string::npos) { |
| - layout_id = layout_name.substr(0, dash_index); |
| - layout_variant = layout_name.substr(dash_index + 1); |
| - } |
| - struct xkb_rule_names names = { |
| - .rules = NULL, |
| - .model = "pc101", |
| - .layout = layout_id.c_str(), |
| - .variant = layout_variant.c_str(), |
| - .options = "" |
| - }; |
| - xkb_keymap* keymap = xkb_keymap_new_from_names(xkb_context_.get(), |
| - &names, |
| - XKB_KEYMAP_COMPILE_NO_FLAGS); |
| + xkb_keymap* keymap = xkb_keymaps_[layout_name]; |
| if (keymap) { |
| SetKeymap(keymap); |
| - return true; |
| + } else { |
| + if (!keymap_loader_) |
| + keymap_loader_ = new XkbKeymapLoader(this); |
| + keymap_loader_->loadKeymap(layout_name); |
| } |
| + return true; |
| #endif // defined(OS_CHROMEOS) |
| return false; |
| } |