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