1 module gfx.window.xkeyboard;
2 
3 version(linux):
4 
5 import gfx.core.rc : Disposable;
6 import gfx.window : gfxWindowLog, KeyEvent, KeyHandler;
7 import gfx.window.keys;
8 
9 import xkbcommon.keysyms;
10 import xkbcommon.xkbcommon;
11 
12 /// Keyboard class whose state is driven by xkbcommon
13 abstract class XKeyboard : Disposable
14 {
15     private xkb_context* _ctx;
16     private xkb_keymap* _keymap;
17     private xkb_state* _state;
18     private KeyMods _mods;
19 
20     this(xkb_context* ctx, xkb_keymap* keymap, xkb_state* state)
21     {
22         _ctx = ctx;
23         _keymap = keymap;
24         _state = state;
25     }
26 
27     override void dispose()
28     {
29         xkb_state_unref(_state);
30         xkb_keymap_unref(_keymap);
31         xkb_context_unref(_ctx);
32     }
33 
34     void updateState(uint depressedMods, uint latchedMods, uint lockedMods,
35                      uint depressedLayout, uint latchedLayout, uint lockedLayout)
36     {
37         xkb_state_update_mask(_state,
38             depressedMods, latchedMods, lockedMods,
39             depressedLayout, latchedLayout, lockedLayout
40         );
41     }
42 
43     @property KeyMods mods() const
44     {
45         return _mods;
46     }
47 
48     void processKeyDown(uint keycode, KeyHandler handler)
49     {
50         import std.exception : assumeUnique;
51 
52         const code = codeForKeycode(keycode);
53         const mods = modsForCode(code);
54         _mods |= mods;
55 
56         if (!handler) return;
57 
58         const keysym = xkb_state_key_get_one_sym(_state, keycode);
59         const sym = symForKeysym(keysym);
60         const size = xkb_state_key_get_utf8(_state, keycode, null, 0);
61         string text;
62         if (size > 0) {
63             char[] buf = new char[size+1];
64             xkb_state_key_get_utf8(_state, keycode, buf.ptr, size+1);
65             buf = buf[0 .. size];
66             text = assumeUnique(buf);
67         }
68 
69         handler(KeyEvent(sym, code, mods, text));
70     }
71 
72     void processKeyUp(uint keycode, KeyHandler handler)
73     {
74         import std.exception : assumeUnique;
75 
76         const code = codeForKeycode(keycode);
77         const mods = modsForCode(code);
78         _mods &= ~mods;
79 
80         if (!handler) return;
81 
82         const keysym = xkb_state_key_get_one_sym(_state, keycode);
83         const sym = symForKeysym(keysym);
84 
85         handler(KeyEvent(sym, code, mods, null));
86     }
87 
88 }
89 
90 KeyMods modsForCode(in KeyCode code)
91 {
92     switch(code)
93     {
94         case KeyCode.leftCtrl: return KeyMods.leftCtrl;
95         case KeyCode.leftShift: return KeyMods.leftShift;
96         case KeyCode.leftAlt: return KeyMods.leftAlt;
97         case KeyCode.leftSuper: return KeyMods.leftSuper;
98         case KeyCode.rightCtrl: return KeyMods.rightCtrl;
99         case KeyCode.rightShift: return KeyMods.rightShift;
100         case KeyCode.rightAlt: return KeyMods.rightAlt;
101         case KeyCode.rightSuper: return KeyMods.rightSuper;
102         default: return KeyMods.none;
103     }
104 }
105 
106 
107 KeySym symForKeysym(uint keysym)
108 {
109     if (keysym >= 0x20 && keysym < 0x80) {
110         if (keysym >= 0x61 && keysym <= 0x7a) {
111             keysym &= ~KeySym.latin1SmallMask;
112         }
113         return cast(KeySym)keysym;
114     }
115     if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F24) {
116         return cast(KeySym)(KeySym.f1 + (keysym - XKB_KEY_F1));
117     }
118     auto k = (keysym in keysymMap);
119     if (k) {
120         return *k;
121     }
122     return KeySym.unknown;
123 }
124 
125 
126 KeyCode codeForKeycode(xkb_keycode_t keycode)
127 {
128     if (keycode >= keycodeTable.length)
129     {
130         gfxWindowLog.warningf("keycode 0x%x is out of bounds", keycode);
131         return KeyCode.unknown;
132     }
133     return keycodeTable[keycode];
134 }
135 
136 
137 private
138 {
139     immutable KeySym[uint] keysymMap;
140     immutable KeyCode[256] keycodeTable;
141 
142     shared static this() {
143 
144         keycodeTable = [
145             // 0x00     0
146             KeyCode.unknown,
147             KeyCode.unknown,
148             KeyCode.unknown,
149             KeyCode.unknown,
150             KeyCode.unknown,
151             KeyCode.unknown,
152             KeyCode.unknown,
153             KeyCode.unknown,
154             KeyCode.unknown,
155             KeyCode.escape,
156             KeyCode.d1,
157             KeyCode.d2,
158             KeyCode.d3,
159             KeyCode.d4,
160             KeyCode.d5,
161             KeyCode.d6,
162             // 0x10     16
163             KeyCode.d7,
164             KeyCode.d8,
165             KeyCode.d9,
166             KeyCode.d0,
167             KeyCode.minus,
168             KeyCode.equals,
169             KeyCode.backspace,
170             KeyCode.tab,
171             KeyCode.q,
172             KeyCode.w,
173             KeyCode.e,
174             KeyCode.r,
175             KeyCode.t,
176             KeyCode.y,
177             KeyCode.u,
178             KeyCode.i,
179             // 0x20     32
180             KeyCode.o,
181             KeyCode.p,
182             KeyCode.leftBracket,
183             KeyCode.rightBracket,
184             KeyCode.enter,
185             KeyCode.leftCtrl,
186             KeyCode.a,
187             KeyCode.s,
188             KeyCode.d,
189             KeyCode.f,
190             KeyCode.g,
191             KeyCode.h,
192             KeyCode.j,
193             KeyCode.k,
194             KeyCode.l,
195             KeyCode.semicolon,
196             // 0x30     48
197             KeyCode.quote,
198             KeyCode.grave,
199             KeyCode.uK_Hash,
200             KeyCode.leftShift,
201             KeyCode.z,
202             KeyCode.x,
203             KeyCode.c,
204             KeyCode.v,
205             KeyCode.b,
206             KeyCode.n,
207             KeyCode.m,
208             KeyCode.comma,
209             KeyCode.period,
210             KeyCode.slash,
211             KeyCode.rightShift,
212             KeyCode.kp_Multiply,
213             // 0x40     64
214             KeyCode.leftAlt,
215             KeyCode.space,
216             KeyCode.capsLock,
217             KeyCode.f1,
218             KeyCode.f2,
219             KeyCode.f3,
220             KeyCode.f4,
221             KeyCode.f5,
222             KeyCode.f6,
223             KeyCode.f7,
224             KeyCode.f8,
225             KeyCode.f9,
226             KeyCode.f10,
227             KeyCode.kp_NumLock,
228             KeyCode.scrollLock,
229             KeyCode.kp_7,
230             // 0x50     80
231             KeyCode.kp_8,
232             KeyCode.kp_9,
233             KeyCode.kp_Subtract,
234             KeyCode.kp_4,
235             KeyCode.kp_5,
236             KeyCode.kp_6,
237             KeyCode.kp_Add,
238             KeyCode.kp_1,
239             KeyCode.kp_2,
240             KeyCode.kp_3,
241             KeyCode.kp_0,
242             KeyCode.kp_Period,
243             KeyCode.unknown,
244             KeyCode.unknown,
245             KeyCode.uK_Backslash,
246             KeyCode.f11,
247             // 0x60     96
248             KeyCode.f12,
249             KeyCode.unknown,
250             KeyCode.lang3,     // Katakana
251             KeyCode.lang4,     // Hiragana
252             KeyCode.unknown,   // Henkan
253             KeyCode.unknown,   // Hiragana_Katakana
254             KeyCode.unknown,   // Muhenkan
255             KeyCode.unknown,
256             KeyCode.kp_Enter,
257             KeyCode.rightCtrl,
258             KeyCode.kp_Divide,
259             KeyCode.printScreen,
260             KeyCode.rightAlt,
261             KeyCode.unknown,  // line feed
262             KeyCode.home,
263             KeyCode.up,
264             // 0x70     112
265             KeyCode.pageUp,
266             KeyCode.left,
267             KeyCode.right,
268             KeyCode.end,
269             KeyCode.down,
270             KeyCode.pageDown,
271             KeyCode.insert,
272             KeyCode.delete_,
273             KeyCode.unknown,
274             KeyCode.mute,
275             KeyCode.volumeDown,
276             KeyCode.volumeUp,
277             KeyCode.unknown,  // power off
278             KeyCode.kp_Equal,
279             KeyCode.kp_PlusMinus,
280             KeyCode.pause,
281             // 0x80     128
282             KeyCode.unknown, // launch A
283             KeyCode.kp_Decimal,
284             KeyCode.lang1,     // hangul
285             KeyCode.lang2,     // hangul/hanja toggle
286             KeyCode.unknown,
287             KeyCode.unknown,
288             KeyCode.unknown,
289             KeyCode.menu,
290             KeyCode.cancel,
291             KeyCode.again,
292             KeyCode.unknown,  // SunProps
293             KeyCode.undo,
294             KeyCode.unknown,  // SunFront
295             KeyCode.copy,
296             KeyCode.unknown,  // Open
297             KeyCode.paste,
298             // 0x90     144
299             KeyCode.find,
300             KeyCode.cut,
301             KeyCode.help,
302             KeyCode.unknown,  // XF86MenuKB
303             KeyCode.unknown,  // XF86Calculator
304             KeyCode.unknown,
305             KeyCode.unknown,  //XF86Sleep
306             KeyCode.unknown,  //XF86Wakeup
307             KeyCode.unknown,  //XF86Explorer
308             KeyCode.unknown,  //XF86Send
309             KeyCode.unknown,
310             KeyCode.unknown,  //Xfer
311             KeyCode.unknown,  //launch1
312             KeyCode.unknown,  //launch2
313             KeyCode.unknown,  //WWW
314             KeyCode.unknown,  //DOS
315             // 0xA0     160
316             KeyCode.unknown,  // Screensaver
317             KeyCode.unknown,
318             KeyCode.unknown,   // RotateWindows
319             KeyCode.unknown,   // Mail
320             KeyCode.unknown,   // Favorites
321             KeyCode.unknown,   // MyComputer
322             KeyCode.unknown,   // Back
323             KeyCode.unknown,   // Forward
324             KeyCode.unknown,
325             KeyCode.unknown,   // Eject
326             KeyCode.unknown,   // Eject
327             KeyCode.unknown,   // AudioNext
328             KeyCode.unknown,   // AudioPlay
329             KeyCode.unknown,   // AudioPrev
330             KeyCode.unknown,   // AudioStop
331             KeyCode.unknown,   // AudioRecord
332             // 0xB0     176
333             KeyCode.unknown,   // AudioRewind
334             KeyCode.unknown,   // Phone
335             KeyCode.unknown,
336             KeyCode.unknown,   // Tools
337             KeyCode.unknown,   // HomePage
338             KeyCode.unknown,   // Reload
339             KeyCode.unknown,   // Close
340             KeyCode.unknown,
341             KeyCode.unknown,
342             KeyCode.unknown,   // ScrollUp
343             KeyCode.unknown,   // ScrollDown
344             KeyCode.unknown,   // parentleft
345             KeyCode.unknown,   // parentright
346             KeyCode.unknown,   // New
347             KeyCode.unknown,   // Redo
348             KeyCode.unknown,   // Tools
349             // 0xC0     192
350             KeyCode.unknown,   // Launch5
351             KeyCode.unknown,   // Launch6
352             KeyCode.unknown,   // Launch7
353             KeyCode.unknown,   // Launch8
354             KeyCode.unknown,   // Launch9
355             KeyCode.unknown,
356             KeyCode.unknown,   // AudioMicMute
357             KeyCode.unknown,   // TouchpadToggle
358             KeyCode.unknown,   // TouchpadPadOn
359             KeyCode.unknown,   // TouchpadOff
360             KeyCode.unknown,
361             KeyCode.unknown,   // Mode_switch
362             KeyCode.unknown,   // Alt_L
363             KeyCode.unknown,   // Meta_L
364             KeyCode.unknown,   // Super_L
365             KeyCode.unknown,   // Hyper_L
366             // 0xD0     208
367             KeyCode.unknown,   // AudioPlay
368             KeyCode.unknown,   // AudioPause
369             KeyCode.unknown,   // Launch3
370             KeyCode.unknown,   // Launch4
371             KeyCode.unknown,   // LaunchB
372             KeyCode.unknown,   // Suspend
373             KeyCode.unknown,   // Close
374             KeyCode.unknown,   // AudioPlay
375             KeyCode.unknown,   // AudioForward
376             KeyCode.unknown,
377             KeyCode.unknown,   // Print
378             KeyCode.unknown,
379             KeyCode.unknown,   // WebCam
380             KeyCode.unknown,
381             KeyCode.unknown,
382             KeyCode.unknown,   // Mail
383             // 0xE0     224
384             KeyCode.unknown,   // Messenger
385             KeyCode.unknown,   // Seach
386             KeyCode.unknown,   // GO
387             KeyCode.unknown,   // Finance
388             KeyCode.unknown,   // Game
389             KeyCode.unknown,   // Shop
390             KeyCode.unknown,
391             KeyCode.unknown,   // Cancel
392             KeyCode.unknown,   // MonBrightnessDown
393             KeyCode.unknown,   // MonBrightnessUp
394             KeyCode.unknown,   // AudioMedia
395             KeyCode.unknown,   // Display
396             KeyCode.unknown,   // KbdLightOnOff
397             KeyCode.unknown,   // KbdBrightnessDown
398             KeyCode.unknown,   // KbdBrightnessUp
399             KeyCode.unknown,   // Send
400             // 0xF0     240
401             KeyCode.unknown,   // Reply
402             KeyCode.unknown,   // MailForward
403             KeyCode.unknown,   // Save
404             KeyCode.unknown,   // Documents
405             KeyCode.unknown,   // Battery
406             KeyCode.unknown,   // Bluetooth
407             KeyCode.unknown,   // WLan
408             KeyCode.unknown,
409             KeyCode.unknown,
410             KeyCode.unknown,
411             KeyCode.unknown,
412             KeyCode.unknown,
413             KeyCode.unknown,
414             KeyCode.unknown,
415             KeyCode.unknown,
416             KeyCode.unknown
417         ];
418 
419 
420 
421         KeySym[uint] map;
422 
423         map[XKB_KEY_Escape] =                   KeySym.escape;
424         map[XKB_KEY_Tab] =                      KeySym.tab;
425         map[XKB_KEY_ISO_Left_Tab] =             KeySym.leftTab;
426         map[XKB_KEY_BackSpace] =                KeySym.backspace;
427         map[XKB_KEY_Return] =                   KeySym.return_;
428         map[XKB_KEY_Insert] =                   KeySym.insert;
429         map[XKB_KEY_Delete] =                   KeySym.delete_;
430         map[XKB_KEY_Clear] =                    KeySym.delete_;
431         map[XKB_KEY_Pause] =                    KeySym.pause;
432         map[XKB_KEY_Print] =                    KeySym.print;
433         map[0x1005FF60] =                       KeySym.sysRq;         // hardcoded Sun SysReq
434         map[0x1007ff00] =                       KeySym.sysRq;         // hardcoded X386 SysReq
435 
436         // cursor movement
437 
438         map[XKB_KEY_Home] =                     KeySym.home;
439         map[XKB_KEY_End] =                      KeySym.end;
440         map[XKB_KEY_Left] =                     KeySym.left;
441         map[XKB_KEY_Up] =                       KeySym.up;
442         map[XKB_KEY_Right] =                    KeySym.right;
443         map[XKB_KEY_Down] =                     KeySym.down;
444         map[XKB_KEY_Page_Up] =                  KeySym.pageUp;
445         map[XKB_KEY_Page_Down] =                KeySym.pageDown;
446         map[XKB_KEY_Prior] =                    KeySym.pageUp;
447         map[XKB_KEY_Next] =                     KeySym.pageDown;
448 
449         // modifiers
450 
451         map[XKB_KEY_Shift_L] =                  KeySym.leftShift;
452         map[XKB_KEY_Shift_R] =                  KeySym.rightShift;
453         map[XKB_KEY_Shift_Lock] =               KeySym.shift;
454         map[XKB_KEY_Control_L] =                KeySym.leftCtrl;
455         map[XKB_KEY_Control_R] =                KeySym.rightCtrl;
456         //map[XKB_KEY_Meta_L] =                   KeySym.leftMeta;
457         //map[XKB_KEY_Meta_R] =                   KeySym.rightMeta;
458         map[XKB_KEY_Alt_L] =                    KeySym.leftAlt;
459         map[XKB_KEY_Alt_R] =                    KeySym.rightAlt;
460         map[XKB_KEY_Caps_Lock] =                KeySym.capsLock;
461         map[XKB_KEY_Num_Lock] =                 KeySym.numLock;
462         map[XKB_KEY_Scroll_Lock] =              KeySym.scrollLock;
463         map[XKB_KEY_Super_L] =                  KeySym.leftSuper;
464         map[XKB_KEY_Super_R] =                  KeySym.rightSuper;
465         map[XKB_KEY_Menu] =                     KeySym.menu;
466         map[XKB_KEY_Help] =                     KeySym.help;
467         map[0x1000FF74] =                       KeySym.leftTab; // hardcoded HP backtab
468         map[0x1005FF10] =                       KeySym.f11;     // hardcoded Sun F36 (labeled F11)
469         map[0x1005FF11] =                       KeySym.f12;     // hardcoded Sun F37 (labeled F12)
470 
471         // numeric and function keypad keys
472 
473         map[XKB_KEY_KP_Enter] =                 KeySym.kp_Enter;
474         map[XKB_KEY_KP_Delete] =                KeySym.kp_Delete;
475         map[XKB_KEY_KP_Home] =                  KeySym.kp_Home;
476         map[XKB_KEY_KP_Begin] =                 KeySym.kp_Begin;
477         map[XKB_KEY_KP_End] =                   KeySym.kp_End;
478         map[XKB_KEY_KP_Page_Up] =               KeySym.kp_PageUp;
479         map[XKB_KEY_KP_Page_Down] =             KeySym.kp_PageDown;
480         map[XKB_KEY_KP_Up] =                    KeySym.kp_Up;
481         map[XKB_KEY_KP_Down] =                  KeySym.kp_Down;
482         map[XKB_KEY_KP_Left] =                  KeySym.kp_Left;
483         map[XKB_KEY_KP_Right] =                 KeySym.kp_Right;
484         map[XKB_KEY_KP_Equal] =                 KeySym.kp_Equal;
485         map[XKB_KEY_KP_Multiply] =              KeySym.kp_Multiply;
486         map[XKB_KEY_KP_Add] =                   KeySym.kp_Add;
487         map[XKB_KEY_KP_Divide] =                KeySym.kp_Divide;
488         map[XKB_KEY_KP_Subtract] =              KeySym.kp_Subtract;
489         map[XKB_KEY_KP_Decimal] =               KeySym.kp_Decimal;
490         map[XKB_KEY_KP_Separator] =             KeySym.kp_Separator;
491 
492         map[XKB_KEY_KP_0] =                     KeySym.kp_0;
493         map[XKB_KEY_KP_1] =                     KeySym.kp_1;
494         map[XKB_KEY_KP_2] =                     KeySym.kp_2;
495         map[XKB_KEY_KP_3] =                     KeySym.kp_3;
496         map[XKB_KEY_KP_4] =                     KeySym.kp_4;
497         map[XKB_KEY_KP_6] =                     KeySym.kp_6;
498         map[XKB_KEY_KP_7] =                     KeySym.kp_7;
499         map[XKB_KEY_KP_8] =                     KeySym.kp_8;
500         map[XKB_KEY_KP_9] =                     KeySym.kp_9;
501 
502         // International input method support keys
503 
504         // International & multi-key character composition
505         map[XKB_KEY_ISO_Level3_Shift] =         KeySym.altGr;
506         //map[XKB_KEY_Multi_key] =                KeySym.multi_key;
507         //map[XKB_KEY_Codeinput] =                KeySym.codeinput;
508         //map[XKB_KEY_SingleCandidate] =          KeySym.singleCandidate;
509         //map[XKB_KEY_MultipleCandidate] =        KeySym.multipleCandidate;
510         //map[XKB_KEY_PreviousCandidate] =        KeySym.previousCandidate;
511 
512         // Misc Functions
513         map[XKB_KEY_Mode_switch] =              KeySym.modeSwitch;
514 
515         //// Japanese keyboard support
516         //map[XKB_KEY_Kanji] =                    KeySym.kanji;
517         //map[XKB_KEY_Muhenkan] =                 KeySym.muhenkan;
518         //map[XKB_KEY_Henkan_Mode] =            KeySym.henkan_Mode;
519         //map[XKB_KEY_Henkan_Mode] =              KeySym.henkan;
520         //map[XKB_KEY_Henkan] =                   KeySym.henkan;
521         //map[XKB_KEY_Romaji] =                   KeySym.romaji;
522         //map[XKB_KEY_Hiragana] =                 KeySym.hiragana;
523         //map[XKB_KEY_Katakana] =                 KeySym.katakana;
524         //map[XKB_KEY_Hiragana_Katakana] =        KeySym.hiragana_Katakana;
525         //map[XKB_KEY_Zenkaku] =                  KeySym.zenkaku;
526         //map[XKB_KEY_Hankaku] =                  KeySym.hankaku;
527         //map[XKB_KEY_Zenkaku_Hankaku] =          KeySym.zenkaku_Hankaku;
528         //map[XKB_KEY_Touroku] =                  KeySym.touroku;
529         //map[XKB_KEY_Massyo] =                   KeySym.massyo;
530         //map[XKB_KEY_Kana_Lock] =                KeySym.kana_Lock;
531         //map[XKB_KEY_Kana_Shift] =               KeySym.kana_Shift;
532         //map[XKB_KEY_Eisu_Shift] =               KeySym.eisu_Shift;
533         //map[XKB_KEY_Eisu_toggle] =              KeySym.eisu_toggle;
534         //map[XKB_KEY_Kanji_Bangou] =           KeySym.kanji_Bangou;
535         //map[XKB_KEY_Zen_Koho] =               KeySym.zen_Koho;
536         //map[XKB_KEY_Mae_Koho] =               KeySym.mae_Koho;
537         //map[XKB_KEY_Kanji_Bangou] =             KeySym.codeinput;
538         //map[XKB_KEY_Zen_Koho] =                 KeySym.multipleCandidate;
539         //map[XKB_KEY_Mae_Koho] =                 KeySym.previousCandidate;
540 
541         //// Korean keyboard support
542         //map[XKB_KEY_HANGul] =                   KeySym.hangul;
543         //map[XKB_KEY_HANGul_Start] =             KeySym.hangul_Start;
544         //map[XKB_KEY_HANGul_End] =               KeySym.hangul_End;
545         //map[XKB_KEY_HANGul_Hanja] =             KeySym.hangul_Hanja;
546         //map[XKB_KEY_HANGul_Jamo] =              KeySym.hangul_Jamo;
547         //map[XKB_KEY_HANGul_Romaja] =            KeySym.hangul_Romaja;
548         //map[XKB_KEY_HANGul_Codeinput] =       KeySym.hangul_Codeinput;
549         //map[XKB_KEY_HANGul_Codeinput] =         KeySym.codeinput;
550         //map[XKB_KEY_HANGul_Jeonja] =            KeySym.hangul_Jeonja;
551         //map[XKB_KEY_HANGul_Banja] =             KeySym.hangul_Banja;
552         //map[XKB_KEY_HANGul_PreHanja] =          KeySym.hangul_PreHanja;
553         //map[XKB_KEY_HANGul_PostHanja] =         KeySym.hangul_PostHanja;
554         //map[XKB_KEY_HANGul_SingleCandidate] =   KeySym.hangul_SingleCandidate;
555         //map[XKB_KEY_HANGul_MultipleCandidate] = KeySym.hangul_MultipleCandidate;
556         //map[XKB_KEY_HANGul_PreviousCandidate] = KeySym.hangul_PreviousCandidate;
557         //map[XKB_KEY_HANGul_SingleCandidate] =   KeySym.singleCandidate;
558         //map[XKB_KEY_HANGul_MultipleCandidate] = KeySym.multipleCandidate;
559         //map[XKB_KEY_HANGul_PreviousCandidate] = KeySym.previousCandidate;
560         //map[XKB_KEY_HANGul_Special] =           KeySym.hangul_Special;
561         //map[XKB_KEY_HANGul_switch] =          KeySym.hangul_switch;
562         //map[XKB_KEY_HANGul_switch] =            KeySym.Mode_switch;
563 
564 
565         // Special keys from X.org - This include multimedia keys,
566             // wireless/bluetooth/uwb keys, special launcher keys, etc.
567         map[XKB_KEY_XF86Back] =                 KeySym.browserBack;
568         map[XKB_KEY_XF86Forward] =              KeySym.browserForward;
569         map[XKB_KEY_XF86Stop] =                 KeySym.browserStop;
570         map[XKB_KEY_XF86Refresh] =              KeySym.browserRefresh;
571         map[XKB_KEY_XF86Favorites] =            KeySym.browserFavorites;
572         map[XKB_KEY_XF86AudioMedia] =           KeySym.launchMedia;
573         map[XKB_KEY_XF86OpenURL] =              KeySym.openUrl;
574         map[XKB_KEY_XF86HomePage] =             KeySym.browserHome;
575         map[XKB_KEY_XF86Search] =               KeySym.browserSearch;
576         map[XKB_KEY_XF86AudioLowerVolume] =     KeySym.volumeDown;
577         map[XKB_KEY_XF86AudioMute] =            KeySym.volumeMute;
578         map[XKB_KEY_XF86AudioRaiseVolume] =     KeySym.volumeUp;
579         map[XKB_KEY_XF86AudioPlay] =            KeySym.mediaPlay;
580         map[XKB_KEY_XF86AudioStop] =            KeySym.mediaStop;
581         map[XKB_KEY_XF86AudioPrev] =            KeySym.mediaPrevious;
582         map[XKB_KEY_XF86AudioNext] =            KeySym.mediaNext;
583         map[XKB_KEY_XF86AudioRecord] =          KeySym.mediaRecord;
584         map[XKB_KEY_XF86AudioPause] =           KeySym.mediaPause;
585         map[XKB_KEY_XF86Mail] =                 KeySym.launchMail;
586         map[XKB_KEY_XF86MyComputer] =           KeySym.myComputer;
587         map[XKB_KEY_XF86Calculator] =           KeySym.calculator;
588         map[XKB_KEY_XF86Memo] =                 KeySym.memo;
589         map[XKB_KEY_XF86ToDoList] =             KeySym.todoList;
590         map[XKB_KEY_XF86Calendar] =             KeySym.calendar;
591         map[XKB_KEY_XF86PowerDown] =            KeySym.powerDown;
592         map[XKB_KEY_XF86ContrastAdjust] =       KeySym.contrastAdjust;
593         map[XKB_KEY_XF86Standby] =              KeySym.standby;
594         map[XKB_KEY_XF86MonBrightnessUp] =      KeySym.monBrightnessUp;
595         map[XKB_KEY_XF86MonBrightnessDown] =    KeySym.monBrightnessDown;
596         map[XKB_KEY_XF86KbdLightOnOff] =        KeySym.keyboardLightOnOff;
597         map[XKB_KEY_XF86KbdBrightnessUp] =      KeySym.keyboardBrightnessUp;
598         map[XKB_KEY_XF86KbdBrightnessDown] =    KeySym.keyboardBrightnessDown;
599         map[XKB_KEY_XF86PowerOff] =             KeySym.powerOff;
600         map[XKB_KEY_XF86WakeUp] =               KeySym.wakeUp;
601         map[XKB_KEY_XF86Eject] =                KeySym.eject;
602         map[XKB_KEY_XF86ScreenSaver] =          KeySym.screenSaver;
603         map[XKB_KEY_XF86WWW] =                  KeySym.www;
604         map[XKB_KEY_XF86Sleep] =                KeySym.sleep;
605         map[XKB_KEY_XF86LightBulb] =            KeySym.lightBulb;
606         map[XKB_KEY_XF86Shop] =                 KeySym.shop;
607         map[XKB_KEY_XF86History] =              KeySym.history;
608         map[XKB_KEY_XF86AddFavorite] =          KeySym.addFavorite;
609         map[XKB_KEY_XF86HotLinks] =             KeySym.hotLinks;
610         map[XKB_KEY_XF86BrightnessAdjust] =     KeySym.brightnessAdjust;
611         map[XKB_KEY_XF86Finance] =              KeySym.finance;
612         map[XKB_KEY_XF86Community] =            KeySym.community;
613         map[XKB_KEY_XF86AudioRewind] =          KeySym.audioRewind;
614         map[XKB_KEY_XF86BackForward] =          KeySym.backForward;
615         map[XKB_KEY_XF86ApplicationLeft] =      KeySym.applicationLeft;
616         map[XKB_KEY_XF86ApplicationRight] =     KeySym.applicationRight;
617         map[XKB_KEY_XF86Book] =                 KeySym.book;
618         map[XKB_KEY_XF86CD] =                   KeySym.cd;
619         map[XKB_KEY_XF86Calculater] =           KeySym.calculator;
620         map[XKB_KEY_XF86Clear] =                KeySym.clear;
621         map[XKB_KEY_XF86ClearGrab] =            KeySym.clearGrab;
622         map[XKB_KEY_XF86Close] =                KeySym.close;
623         map[XKB_KEY_XF86Copy] =                 KeySym.copy;
624         map[XKB_KEY_XF86Cut] =                  KeySym.cut;
625         map[XKB_KEY_XF86Display] =              KeySym.display;
626         map[XKB_KEY_XF86DOS] =                  KeySym.dos;
627         map[XKB_KEY_XF86Documents] =            KeySym.documents;
628         map[XKB_KEY_XF86Excel] =                KeySym.excel;
629         map[XKB_KEY_XF86Explorer] =             KeySym.explorer;
630         map[XKB_KEY_XF86Game] =                 KeySym.game;
631         map[XKB_KEY_XF86Go] =                   KeySym.go;
632         map[XKB_KEY_XF86iTouch] =               KeySym.iTouch;
633         map[XKB_KEY_XF86LogOff] =               KeySym.logOff;
634         map[XKB_KEY_XF86Market] =               KeySym.market;
635         map[XKB_KEY_XF86Meeting] =              KeySym.meeting;
636         map[XKB_KEY_XF86MenuKB] =               KeySym.menuKB;
637         map[XKB_KEY_XF86MenuPB] =               KeySym.menuPB;
638         map[XKB_KEY_XF86MySites] =              KeySym.mySites;
639         map[XKB_KEY_XF86New] =                  KeySym.new_;
640         map[XKB_KEY_XF86News] =                 KeySym.news;
641         map[XKB_KEY_XF86OfficeHome] =           KeySym.officeHome;
642         map[XKB_KEY_XF86Open] =                 KeySym.open;
643         map[XKB_KEY_XF86Option] =               KeySym.option;
644         map[XKB_KEY_XF86Paste] =                KeySym.paste;
645         map[XKB_KEY_XF86Phone] =                KeySym.phone;
646         map[XKB_KEY_XF86Reply] =                KeySym.reply;
647         map[XKB_KEY_XF86Reload] =               KeySym.reload;
648         map[XKB_KEY_XF86RotateWindows] =        KeySym.rotateWindows;
649         map[XKB_KEY_XF86RotationPB] =           KeySym.rotationPB;
650         map[XKB_KEY_XF86RotationKB] =           KeySym.rotationKB;
651         map[XKB_KEY_XF86Save] =                 KeySym.save;
652         map[XKB_KEY_XF86Send] =                 KeySym.send;
653         map[XKB_KEY_XF86Spell] =                KeySym.spell;
654         map[XKB_KEY_XF86SplitScreen] =          KeySym.splitScreen;
655         map[XKB_KEY_XF86Support] =              KeySym.support;
656         map[XKB_KEY_XF86TaskPane] =             KeySym.taskPane;
657         map[XKB_KEY_XF86Terminal] =             KeySym.terminal;
658         map[XKB_KEY_XF86Tools] =                KeySym.tools;
659         map[XKB_KEY_XF86Travel] =               KeySym.travel;
660         map[XKB_KEY_XF86Video] =                KeySym.video;
661         map[XKB_KEY_XF86Word] =                 KeySym.word;
662         map[XKB_KEY_XF86Xfer] =                 KeySym.xfer;
663         map[XKB_KEY_XF86ZoomIn] =               KeySym.zoomIn;
664         map[XKB_KEY_XF86ZoomOut] =              KeySym.zoomOut;
665         map[XKB_KEY_XF86Away] =                 KeySym.away;
666         map[XKB_KEY_XF86Messenger] =            KeySym.messenger;
667         map[XKB_KEY_XF86WebCam] =               KeySym.webCam;
668         map[XKB_KEY_XF86MailForward] =          KeySym.mailForward;
669         map[XKB_KEY_XF86Pictures] =             KeySym.pictures;
670         map[XKB_KEY_XF86Music] =                KeySym.music;
671         map[XKB_KEY_XF86Battery] =              KeySym.battery;
672         map[XKB_KEY_XF86Bluetooth] =            KeySym.bluetooth;
673         map[XKB_KEY_XF86WLAN] =                 KeySym.wlan;
674         map[XKB_KEY_XF86UWB] =                  KeySym.uwb;
675         map[XKB_KEY_XF86AudioForward] =         KeySym.audioForward;
676         map[XKB_KEY_XF86AudioRepeat] =          KeySym.audioRepeat;
677         map[XKB_KEY_XF86AudioRandomPlay] =      KeySym.audioRandomPlay;
678         map[XKB_KEY_XF86Subtitle] =             KeySym.subtitle;
679         map[XKB_KEY_XF86AudioCycleTrack] =      KeySym.audioCycleTrack;
680         map[XKB_KEY_XF86Time] =                 KeySym.time;
681         map[XKB_KEY_XF86Select] =               KeySym.select;
682         map[XKB_KEY_XF86View] =                 KeySym.view;
683         map[XKB_KEY_XF86TopMenu] =              KeySym.topMenu;
684         map[XKB_KEY_XF86Red] =                  KeySym.red;
685         map[XKB_KEY_XF86Green] =                KeySym.green;
686         map[XKB_KEY_XF86Yellow] =               KeySym.yellow;
687         map[XKB_KEY_XF86Blue] =                 KeySym.blue;
688         map[XKB_KEY_XF86Bluetooth] =            KeySym.bluetooth;
689         map[XKB_KEY_XF86Suspend] =              KeySym.suspend;
690         map[XKB_KEY_XF86Hibernate] =            KeySym.hibernate;
691         map[XKB_KEY_XF86TouchpadToggle] =       KeySym.touchpadToggle;
692         map[XKB_KEY_XF86TouchpadOn] =           KeySym.touchpadOn;
693         map[XKB_KEY_XF86TouchpadOff] =          KeySym.touchpadOff;
694         map[XKB_KEY_XF86AudioMicMute] =         KeySym.micMute;
695         map[XKB_KEY_XF86Launch0] =              KeySym.launch0;
696         map[XKB_KEY_XF86Launch1] =              KeySym.launch1;
697         map[XKB_KEY_XF86Launch2] =              KeySym.launch2;
698         map[XKB_KEY_XF86Launch3] =              KeySym.launch3;
699         map[XKB_KEY_XF86Launch4] =              KeySym.launch4;
700         map[XKB_KEY_XF86Launch5] =              KeySym.launch5;
701         map[XKB_KEY_XF86Launch6] =              KeySym.launch6;
702         map[XKB_KEY_XF86Launch7] =              KeySym.launch7;
703         map[XKB_KEY_XF86Launch8] =              KeySym.launch8;
704         map[XKB_KEY_XF86Launch9] =              KeySym.launch9;
705         map[XKB_KEY_XF86LaunchA] =              KeySym.launchA;
706         map[XKB_KEY_XF86LaunchB] =              KeySym.launchB;
707         map[XKB_KEY_XF86LaunchC] =              KeySym.launchC;
708         map[XKB_KEY_XF86LaunchD] =              KeySym.launchD;
709         map[XKB_KEY_XF86LaunchE] =              KeySym.launchE;
710         map[XKB_KEY_XF86LaunchF] =              KeySym.launchF;
711 
712         map.rehash();
713 
714 
715         import std.exception : assumeUnique;
716 
717         keysymMap = assumeUnique(map);
718     }
719 
720 }