1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/events/keycodes/keyboard_code_conversion_xkb.h"
6 
7 #include "build/build_config.h"
8 #include "ui/events/keycodes/dom/dom_key.h"
9 
10 #ifndef XK_dead_greek
11 #define XK_dead_greek 0xfe8c
12 #endif
13 
14 namespace ui {
15 
16 // We support dead keys beyond those with predefined keysym names,
17 // expressed as numeric constants with |kDeadKeyFlag| set.
18 // Xkbcommon accepts and does not use any bits in 0x0E000000.
19 //
20 constexpr xkb_keysym_t kDeadKeyFlag = 0x08000000;
21 constexpr int32_t kUnicodeMax = 0x10FFFF;
22 
NonPrintableXKeySymToDomKey(xkb_keysym_t keysym)23 DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym) {
24   switch (keysym) {
25     case XKB_KEY_BackSpace:
26       return DomKey::BACKSPACE;
27     case XKB_KEY_Tab:
28     case XKB_KEY_KP_Tab:
29     case XKB_KEY_ISO_Left_Tab:
30       return DomKey::TAB;
31     case XKB_KEY_Clear:
32     case XKB_KEY_KP_Begin:
33     case XKB_KEY_XF86Clear:
34       return DomKey::CLEAR;
35     case XKB_KEY_Return:
36     case XKB_KEY_KP_Enter:
37       return DomKey::ENTER;
38     case XKB_KEY_Linefeed:
39       return DomKey::ENTER;
40     case XKB_KEY_Pause:
41       return DomKey::PAUSE;
42     case XKB_KEY_Scroll_Lock:
43       return DomKey::SCROLL_LOCK;
44     case XKB_KEY_Escape:
45       return DomKey::ESCAPE;
46     case XKB_KEY_Multi_key:
47       return DomKey::COMPOSE;
48     case XKB_KEY_Kanji:
49       return DomKey::KANJI_MODE;
50     case XKB_KEY_Muhenkan:
51       return DomKey::NON_CONVERT;
52     case XKB_KEY_Henkan_Mode:
53       return DomKey::CONVERT;
54     case XKB_KEY_Romaji:
55       return DomKey::ROMAJI;
56     case XKB_KEY_Hiragana:
57       return DomKey::HIRAGANA;
58     case XKB_KEY_Katakana:
59       return DomKey::KATAKANA;
60     case XKB_KEY_Hiragana_Katakana:
61       return DomKey::HIRAGANA_KATAKANA;
62     case XKB_KEY_Zenkaku:
63       return DomKey::ZENKAKU;
64     case XKB_KEY_Hankaku:
65       return DomKey::HANKAKU;
66     case XKB_KEY_Zenkaku_Hankaku:
67       return DomKey::ZENKAKU_HANKAKU;
68     case XKB_KEY_Kana_Lock:
69       return DomKey::KANA_MODE;
70     case XKB_KEY_Eisu_Shift:
71     case XKB_KEY_Eisu_toggle:
72       return DomKey::ALPHANUMERIC;
73     case XKB_KEY_Hangul:
74       return DomKey::HANGUL_MODE;
75     case XKB_KEY_Hangul_Hanja:
76       return DomKey::HANJA_MODE;
77     case XKB_KEY_Codeinput:
78       return DomKey::CODE_INPUT;
79     case XKB_KEY_SingleCandidate:
80       return DomKey::SINGLE_CANDIDATE;
81     case XKB_KEY_MultipleCandidate:
82       return DomKey::ALL_CANDIDATES;
83     case XKB_KEY_PreviousCandidate:
84       return DomKey::PREVIOUS_CANDIDATE;
85     case XKB_KEY_Home:
86     case XKB_KEY_KP_Home:
87       return DomKey::HOME;
88     case XKB_KEY_Left:
89     case XKB_KEY_KP_Left:
90       return DomKey::ARROW_LEFT;
91     case XKB_KEY_Up:
92     case XKB_KEY_KP_Up:
93       return DomKey::ARROW_UP;
94     case XKB_KEY_Right:
95     case XKB_KEY_KP_Right:
96       return DomKey::ARROW_RIGHT;
97     case XKB_KEY_Down:
98     case XKB_KEY_KP_Down:
99       return DomKey::ARROW_DOWN;
100     case XKB_KEY_Prior:
101     case XKB_KEY_KP_Prior:
102       return DomKey::PAGE_UP;
103     case XKB_KEY_Next:
104     case XKB_KEY_KP_Next:
105     case XKB_KEY_XF86ScrollDown:
106       return DomKey::PAGE_DOWN;
107     case XKB_KEY_End:
108     case XKB_KEY_KP_End:
109     case XKB_KEY_XF86ScrollUp:
110       return DomKey::END;
111     case XKB_KEY_Select:
112       return DomKey::SELECT;
113     // Treat Print/PrintScreen as PrintScreen https://crbug.com/683097.
114     case XKB_KEY_Print:
115     case XKB_KEY_3270_PrintScreen:
116       return DomKey::PRINT_SCREEN;
117     case XKB_KEY_Execute:
118       return DomKey::EXECUTE;
119     case XKB_KEY_Insert:
120     case XKB_KEY_KP_Insert:
121       return DomKey::INSERT;
122     case XKB_KEY_Undo:
123       return DomKey::UNDO;
124     case XKB_KEY_Redo:
125       return DomKey::REDO;
126     case XKB_KEY_Menu:
127       return DomKey::CONTEXT_MENU;
128     case XKB_KEY_Find:
129       return DomKey::FIND;
130     case XKB_KEY_Cancel:
131       return DomKey::CANCEL;
132     case XKB_KEY_Help:
133       return DomKey::HELP;
134     case XKB_KEY_Break:
135     case XKB_KEY_3270_Attn:
136       return DomKey::ATTN;
137     case XKB_KEY_Mode_switch:
138       return DomKey::MODE_CHANGE;
139     case XKB_KEY_Num_Lock:
140       return DomKey::NUM_LOCK;
141     case XKB_KEY_F1:
142     case XKB_KEY_KP_F1:
143       return DomKey::F1;
144     case XKB_KEY_F2:
145     case XKB_KEY_KP_F2:
146       return DomKey::F2;
147     case XKB_KEY_F3:
148     case XKB_KEY_KP_F3:
149       return DomKey::F3;
150     case XKB_KEY_F4:
151     case XKB_KEY_KP_F4:
152       return DomKey::F4;
153     case XKB_KEY_F5:
154       return DomKey::F5;
155     case XKB_KEY_F6:
156       return DomKey::F6;
157     case XKB_KEY_F7:
158       return DomKey::F7;
159     case XKB_KEY_F8:
160       return DomKey::F8;
161     case XKB_KEY_F9:
162       return DomKey::F9;
163     case XKB_KEY_F10:
164       return DomKey::F10;
165     case XKB_KEY_F11:
166       return DomKey::F11;
167     case XKB_KEY_F12:
168       return DomKey::F12;
169     case XKB_KEY_XF86Tools:  // XKB 'inet' mapping of F13
170     case XKB_KEY_F13:
171       return DomKey::F13;
172     case XKB_KEY_F14:
173     case XKB_KEY_XF86Launch5:  // XKB 'inet' mapping of F14
174       return DomKey::F14;
175     case XKB_KEY_F15:
176     case XKB_KEY_XF86Launch6:  // XKB 'inet' mapping of F15
177       return DomKey::F15;
178     case XKB_KEY_F16:
179     case XKB_KEY_XF86Launch7:  // XKB 'inet' mapping of F16
180       return DomKey::F16;
181     case XKB_KEY_F17:
182     case XKB_KEY_XF86Launch8:  // XKB 'inet' mapping of F17
183       return DomKey::F17;
184     case XKB_KEY_F18:
185     case XKB_KEY_XF86Launch9:  // XKB 'inet' mapping of F18
186       return DomKey::F18;
187     case XKB_KEY_F19:
188       return DomKey::F19;
189     case XKB_KEY_F20:
190       return DomKey::F20;
191     case XKB_KEY_F21:
192       return DomKey::F21;
193     case XKB_KEY_F22:
194       return DomKey::F22;
195     case XKB_KEY_F23:
196       return DomKey::F23;
197     case XKB_KEY_F24:
198       return DomKey::F24;
199     case XKB_KEY_Shift_L:
200     case XKB_KEY_Shift_R:
201       return DomKey::SHIFT;
202     case XKB_KEY_Control_L:
203     case XKB_KEY_Control_R:
204       return DomKey::CONTROL;
205     case XKB_KEY_Caps_Lock:
206       return DomKey::CAPS_LOCK;
207 #if defined(OS_CHROMEOS)
208     case XKB_KEY_Meta_L:
209     case XKB_KEY_Meta_R:
210     case XKB_KEY_Alt_L:
211     case XKB_KEY_Alt_R:
212       // The Shift+Alt generates a KeySym for the Meta key. On ChromeOS the Meta
213       // key is not used and we should still get the Alt key. crbug.com/541468.
214       return DomKey::ALT;
215 #else
216     case XKB_KEY_Meta_L:
217     case XKB_KEY_Meta_R:
218       return DomKey::META;
219     case XKB_KEY_Alt_L:
220     case XKB_KEY_Alt_R:
221       return DomKey::ALT;
222 #endif  // defined(OS_CHROMEOS)
223     case XKB_KEY_Super_L:
224     case XKB_KEY_Super_R:
225       return DomKey::META;
226     case XKB_KEY_Hyper_L:
227     case XKB_KEY_Hyper_R:
228       return DomKey::HYPER;
229     case XKB_KEY_Delete:
230       return DomKey::DEL;
231     case XKB_KEY_SunProps:
232       return DomKey::PROPS;
233     case XKB_KEY_XF86Next_VMode:
234       return DomKey::VIDEO_MODE_NEXT;
235     case XKB_KEY_XF86MonBrightnessUp:
236       return DomKey::BRIGHTNESS_UP;
237     case XKB_KEY_XF86MonBrightnessDown:
238       return DomKey::BRIGHTNESS_DOWN;
239     case XKB_KEY_XF86Standby:
240     case XKB_KEY_XF86Sleep:
241     case XKB_KEY_XF86Suspend:
242       return DomKey::STANDBY;
243     case XKB_KEY_XF86AudioLowerVolume:
244       return DomKey::AUDIO_VOLUME_DOWN;
245     case XKB_KEY_XF86AudioMute:
246       return DomKey::AUDIO_VOLUME_MUTE;
247     case XKB_KEY_XF86AudioRaiseVolume:
248       return DomKey::AUDIO_VOLUME_UP;
249     case XKB_KEY_XF86AudioPlay:
250       return DomKey::MEDIA_PLAY_PAUSE;
251     case XKB_KEY_XF86AudioStop:
252       return DomKey::MEDIA_STOP;
253     case XKB_KEY_XF86AudioPrev:
254       return DomKey::MEDIA_TRACK_PREVIOUS;
255     case XKB_KEY_XF86AudioNext:
256       return DomKey::MEDIA_TRACK_NEXT;
257     case XKB_KEY_XF86HomePage:
258       return DomKey::BROWSER_HOME;
259     case XKB_KEY_XF86Mail:
260       return DomKey::LAUNCH_MAIL;
261     case XKB_KEY_XF86Search:
262       return DomKey::BROWSER_SEARCH;
263     case XKB_KEY_XF86AudioRecord:
264       return DomKey::MEDIA_RECORD;
265     case XKB_KEY_XF86Calculator:
266       return DomKey::LAUNCH_CALCULATOR;
267     case XKB_KEY_XF86Calendar:
268       return DomKey::LAUNCH_CALENDAR;
269     case XKB_KEY_XF86Back:
270       return DomKey::BROWSER_BACK;
271     case XKB_KEY_XF86Forward:
272       return DomKey::BROWSER_FORWARD;
273     case XKB_KEY_XF86Stop:
274       return DomKey::BROWSER_STOP;
275     case XKB_KEY_XF86Refresh:
276     case XKB_KEY_XF86Reload:
277       return DomKey::BROWSER_REFRESH;
278     case XKB_KEY_XF86PowerOff:
279       return DomKey::POWER_OFF;
280     case XKB_KEY_XF86WakeUp:
281       return DomKey::WAKE_UP;
282     case XKB_KEY_XF86Eject:
283       return DomKey::EJECT;
284     case XKB_KEY_XF86ScreenSaver:
285       return DomKey::LAUNCH_SCREEN_SAVER;
286     case XKB_KEY_XF86WWW:
287       return DomKey::LAUNCH_WEB_BROWSER;
288     case XKB_KEY_XF86Favorites:
289       return DomKey::BROWSER_FAVORITES;
290     case XKB_KEY_XF86AudioPause:
291       return DomKey::MEDIA_PAUSE;
292     case XKB_KEY_XF86AudioMedia:
293     case XKB_KEY_XF86Music:
294       return DomKey::LAUNCH_MUSIC_PLAYER;
295     case XKB_KEY_XF86MyComputer:
296     case XKB_KEY_XF86Explorer:
297       return DomKey::LAUNCH_MY_COMPUTER;
298     case XKB_KEY_XF86AudioRewind:
299       return DomKey::MEDIA_REWIND;
300     case XKB_KEY_XF86CD:
301     case XKB_KEY_XF86Video:
302       return DomKey::LAUNCH_MEDIA_PLAYER;
303     case XKB_KEY_XF86Close:
304       return DomKey::CLOSE;
305     case XKB_KEY_XF86Copy:
306     case XKB_KEY_SunCopy:
307       return DomKey::COPY;
308     case XKB_KEY_XF86Cut:
309     case XKB_KEY_SunCut:
310       return DomKey::CUT;
311     case XKB_KEY_XF86Display:
312       return DomKey::DISPLAY_SWAP;
313     case XKB_KEY_XF86Excel:
314       return DomKey::LAUNCH_SPREADSHEET;
315     case XKB_KEY_XF86LogOff:
316       return DomKey::LOG_OFF;
317     case XKB_KEY_XF86New:
318       return DomKey::NEW;
319     case XKB_KEY_XF86Open:
320     case XKB_KEY_SunOpen:
321       return DomKey::OPEN;
322     case XKB_KEY_XF86Paste:
323     case XKB_KEY_SunPaste:
324       return DomKey::PASTE;
325     case XKB_KEY_XF86Reply:
326       return DomKey::MAIL_REPLY;
327     case XKB_KEY_XF86Save:
328       return DomKey::SAVE;
329     case XKB_KEY_XF86Send:
330       return DomKey::MAIL_SEND;
331     case XKB_KEY_XF86Spell:
332       return DomKey::SPELL_CHECK;
333     case XKB_KEY_XF86SplitScreen:
334       return DomKey::SPLIT_SCREEN_TOGGLE;
335     case XKB_KEY_XF86Word:
336     case XKB_KEY_XF86OfficeHome:
337       return DomKey::LAUNCH_WORD_PROCESSOR;
338     case XKB_KEY_XF86ZoomIn:
339       return DomKey::ZOOM_IN;
340     case XKB_KEY_XF86ZoomOut:
341       return DomKey::ZOOM_OUT;
342     case XKB_KEY_XF86WebCam:
343       return DomKey::LAUNCH_WEB_CAM;
344     case XKB_KEY_XF86MailForward:
345       return DomKey::MAIL_FORWARD;
346     case XKB_KEY_XF86AudioForward:
347       return DomKey::MEDIA_FAST_FORWARD;
348     case XKB_KEY_XF86AudioRandomPlay:
349       return DomKey::RANDOM_TOGGLE;
350     case XKB_KEY_XF86Subtitle:
351       return DomKey::SUBTITLE;
352     case XKB_KEY_XF86Hibernate:
353       return DomKey::HIBERNATE;
354     case XKB_KEY_3270_EraseEOF:
355       return DomKey::ERASE_EOF;
356     case XKB_KEY_3270_Play:
357       return DomKey::PLAY;
358     case XKB_KEY_3270_ExSelect:
359       return DomKey::EX_SEL;
360     case XKB_KEY_3270_CursorSelect:
361       return DomKey::CR_SEL;
362     case XKB_KEY_ISO_Level3_Shift:
363       return DomKey::ALT_GRAPH;
364     case XKB_KEY_ISO_Level3_Latch:
365       return DomKey::ALT_GRAPH_LATCH;
366     case XKB_KEY_ISO_Level5_Shift:
367       return DomKey::SHIFT_LEVEL5;
368     case XKB_KEY_ISO_Next_Group:
369       return DomKey::GROUP_NEXT;
370     case XKB_KEY_ISO_Prev_Group:
371       return DomKey::GROUP_PREVIOUS;
372     case XKB_KEY_ISO_First_Group:
373       return DomKey::GROUP_FIRST;
374     case XKB_KEY_ISO_Last_Group:
375       return DomKey::GROUP_LAST;
376     case XKB_KEY_dead_grave:
377       // combining grave accent
378       return DomKey::DeadKeyFromCombiningCharacter(0x0300);
379     case XKB_KEY_dead_acute:
380       // combining acute accent
381       return DomKey::DeadKeyFromCombiningCharacter(0x0301);
382     case XKB_KEY_dead_circumflex:
383       // combining circumflex accent
384       return DomKey::DeadKeyFromCombiningCharacter(0x0302);
385     case XKB_KEY_dead_tilde:
386       // combining tilde
387       return DomKey::DeadKeyFromCombiningCharacter(0x0303);
388     case XKB_KEY_dead_macron:
389       // combining macron
390       return DomKey::DeadKeyFromCombiningCharacter(0x0304);
391     case XKB_KEY_dead_breve:
392       // combining breve
393       return DomKey::DeadKeyFromCombiningCharacter(0x0306);
394     case XKB_KEY_dead_abovedot:
395       // combining dot above
396       return DomKey::DeadKeyFromCombiningCharacter(0x0307);
397     case XKB_KEY_dead_diaeresis:
398       // combining diaeresis
399       return DomKey::DeadKeyFromCombiningCharacter(0x0308);
400     case XKB_KEY_dead_abovering:
401       // combining ring above
402       return DomKey::DeadKeyFromCombiningCharacter(0x030A);
403     case XKB_KEY_dead_doubleacute:
404       // combining double acute accent
405       return DomKey::DeadKeyFromCombiningCharacter(0x030B);
406     case XKB_KEY_dead_caron:
407       // combining caron
408       return DomKey::DeadKeyFromCombiningCharacter(0x030C);
409     case XKB_KEY_dead_cedilla:
410       // combining cedilla
411       return DomKey::DeadKeyFromCombiningCharacter(0x0327);
412     case XKB_KEY_dead_ogonek:
413       // combining ogonek
414       return DomKey::DeadKeyFromCombiningCharacter(0x0328);
415     case XKB_KEY_dead_iota:
416       // combining greek ypogegrammeni
417       return DomKey::DeadKeyFromCombiningCharacter(0x0345);
418     case XKB_KEY_dead_voiced_sound:
419       // combining voiced sound mark
420       return DomKey::DeadKeyFromCombiningCharacter(0x3099);
421     case XKB_KEY_dead_semivoiced_sound:
422       // combining semi-voiced sound mark
423       return DomKey::DeadKeyFromCombiningCharacter(0x309A);
424     case XKB_KEY_dead_belowdot:
425       // combining dot below
426       return DomKey::DeadKeyFromCombiningCharacter(0x0323);
427     case XKB_KEY_dead_hook:
428       // combining hook above
429       return DomKey::DeadKeyFromCombiningCharacter(0x0309);
430     case XKB_KEY_dead_horn:
431       // combining horn
432       return DomKey::DeadKeyFromCombiningCharacter(0x031B);
433     case XKB_KEY_dead_stroke:
434       // combining long solidus overlay
435       return DomKey::DeadKeyFromCombiningCharacter(0x0338);
436     case XKB_KEY_dead_abovecomma:
437       // combining comma above
438       return DomKey::DeadKeyFromCombiningCharacter(0x0313);
439     case XKB_KEY_dead_abovereversedcomma:
440       // combining reversed comma above
441       return DomKey::DeadKeyFromCombiningCharacter(0x0314);
442     case XKB_KEY_dead_doublegrave:
443       // combining double grave accent
444       return DomKey::DeadKeyFromCombiningCharacter(0x030F);
445     case XKB_KEY_dead_belowring:
446       // combining ring below
447       return DomKey::DeadKeyFromCombiningCharacter(0x0325);
448     case XKB_KEY_dead_belowmacron:
449       // combining macron below
450       return DomKey::DeadKeyFromCombiningCharacter(0x0331);
451     case XKB_KEY_dead_belowcircumflex:
452       // combining circumflex accent below
453       return DomKey::DeadKeyFromCombiningCharacter(0x032D);
454     case XKB_KEY_dead_belowtilde:
455       // combining tilde below
456       return DomKey::DeadKeyFromCombiningCharacter(0x0330);
457     case XKB_KEY_dead_belowbreve:
458       // combining breve below
459       return DomKey::DeadKeyFromCombiningCharacter(0x032E);
460     case XKB_KEY_dead_belowdiaeresis:
461       // combining diaeresis below
462       return DomKey::DeadKeyFromCombiningCharacter(0x0324);
463     case XKB_KEY_dead_invertedbreve:
464       // combining inverted breve
465       return DomKey::DeadKeyFromCombiningCharacter(0x0311);
466     case XKB_KEY_dead_belowcomma:
467       // combining comma below
468       return DomKey::DeadKeyFromCombiningCharacter(0x0326);
469     case XKB_KEY_dead_currency:
470       // currency sign
471       return DomKey::DeadKeyFromCombiningCharacter(0x00A4);
472     case XKB_KEY_dead_greek:
473       // greek question mark
474       return DomKey::DeadKeyFromCombiningCharacter(0x037E);
475     default:
476       if (keysym & kDeadKeyFlag) {
477         int32_t character = keysym & ~kDeadKeyFlag;
478         if ((character >= 0) && (character <= kUnicodeMax)) {
479           return DomKey::DeadKeyFromCombiningCharacter(character);
480         }
481       }
482       return DomKey::NONE;
483   }
484 }
XKeySymToDomKey(xkb_keysym_t keysym,base::char16 character)485 DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character) {
486   DomKey dom_key = NonPrintableXKeySymToDomKey(keysym);
487   if (dom_key != DomKey::NONE)
488     return dom_key;
489   return DomKey::FromCharacter(character);
490 }
491 
492 }  // namespace ui
493