| // Copyright 2015 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // x11key contains X11 numeric codes for the keyboard and mouse. |
| package x11key // import "golang.org/x/exp/shiny/driver/internal/x11key" |
| |
| import ( |
| "golang.org/x/mobile/event/key" |
| ) |
| |
| // These constants come from /usr/include/X11/X.h |
| const ( |
| ShiftMask = 1 << 0 |
| LockMask = 1 << 1 |
| ControlMask = 1 << 2 |
| Mod1Mask = 1 << 3 |
| Mod2Mask = 1 << 4 |
| Mod3Mask = 1 << 5 |
| Mod4Mask = 1 << 6 |
| Mod5Mask = 1 << 7 |
| Button1Mask = 1 << 8 |
| Button2Mask = 1 << 9 |
| Button3Mask = 1 << 10 |
| Button4Mask = 1 << 11 |
| Button5Mask = 1 << 12 |
| ) |
| |
| type KeysymTable [256][2]uint32 |
| |
| func (t *KeysymTable) Lookup(detail uint8, state uint16) (rune, key.Code) { |
| // The key event's rune depends on whether the shift key is down. |
| unshifted := rune(t[detail][0]) |
| r := unshifted |
| if state&ShiftMask != 0 { |
| r = rune(t[detail][1]) |
| // In X11, a zero keysym when shift is down means to use what the |
| // keysym is when shift is up. |
| if r == 0 { |
| r = unshifted |
| } |
| } |
| |
| // The key event's code is independent of whether the shift key is down. |
| var c key.Code |
| if 0 <= unshifted && unshifted < 0x80 { |
| // TODO: distinguish the regular '2' key and number-pad '2' key (with |
| // Num-Lock). |
| c = asciiKeycodes[unshifted] |
| } else { |
| r, c = -1, nonUnicodeKeycodes[unshifted] |
| } |
| |
| // TODO: Unicode-but-not-ASCII keysyms like the Swiss keyboard's 'รถ'. |
| return r, c |
| } |
| |
| func KeyModifiers(state uint16) (m key.Modifiers) { |
| if state&ShiftMask != 0 { |
| m |= key.ModShift |
| } |
| if state&ControlMask != 0 { |
| m |= key.ModControl |
| } |
| if state&Mod1Mask != 0 { |
| m |= key.ModAlt |
| } |
| if state&Mod4Mask != 0 { |
| m |= key.ModMeta |
| } |
| return m |
| } |
| |
| // These constants come from /usr/include/X11/{keysymdef,XF86keysym}.h |
| const ( |
| xkISOLeftTab = 0xfe20 |
| xkBackSpace = 0xff08 |
| xkTab = 0xff09 |
| xkReturn = 0xff0d |
| xkEscape = 0xff1b |
| xkMultiKey = 0xff20 |
| xkHome = 0xff50 |
| xkLeft = 0xff51 |
| xkUp = 0xff52 |
| xkRight = 0xff53 |
| xkDown = 0xff54 |
| xkPageUp = 0xff55 |
| xkPageDown = 0xff56 |
| xkEnd = 0xff57 |
| xkInsert = 0xff63 |
| xkMenu = 0xff67 |
| xkF1 = 0xffbe |
| xkF2 = 0xffbf |
| xkF3 = 0xffc0 |
| xkF4 = 0xffc1 |
| xkF5 = 0xffc2 |
| xkF6 = 0xffc3 |
| xkF7 = 0xffc4 |
| xkF8 = 0xffc5 |
| xkF9 = 0xffc6 |
| xkF10 = 0xffc7 |
| xkF11 = 0xffc8 |
| xkF12 = 0xffc9 |
| xkShiftL = 0xffe1 |
| xkShiftR = 0xffe2 |
| xkControlL = 0xffe3 |
| xkControlR = 0xffe4 |
| xkAltL = 0xffe9 |
| xkAltR = 0xffea |
| xkSuperL = 0xffeb |
| xkSuperR = 0xffec |
| xkDelete = 0xffff |
| |
| xf86xkAudioLowerVolume = 0x1008ff11 |
| xf86xkAudioMute = 0x1008ff12 |
| xf86xkAudioRaiseVolume = 0x1008ff13 |
| ) |
| |
| // nonUnicodeKeycodes maps from those xproto.Keysym values (converted to runes) |
| // that do not correspond to a Unicode code point, such as "Page Up", "F1" or |
| // "Left Shift", to key.Code values. |
| var nonUnicodeKeycodes = map[rune]key.Code{ |
| xkISOLeftTab: key.CodeTab, |
| xkBackSpace: key.CodeDeleteBackspace, |
| xkTab: key.CodeTab, |
| xkReturn: key.CodeReturnEnter, |
| xkEscape: key.CodeEscape, |
| xkHome: key.CodeHome, |
| xkLeft: key.CodeLeftArrow, |
| xkUp: key.CodeUpArrow, |
| xkRight: key.CodeRightArrow, |
| xkDown: key.CodeDownArrow, |
| xkPageUp: key.CodePageUp, |
| xkPageDown: key.CodePageDown, |
| xkEnd: key.CodeEnd, |
| xkInsert: key.CodeInsert, |
| xkMenu: key.CodeRightGUI, // TODO: CodeRightGUI or CodeMenu?? |
| xkMultiKey: key.CodeCompose, |
| |
| xkF1: key.CodeF1, |
| xkF2: key.CodeF2, |
| xkF3: key.CodeF3, |
| xkF4: key.CodeF4, |
| xkF5: key.CodeF5, |
| xkF6: key.CodeF6, |
| xkF7: key.CodeF7, |
| xkF8: key.CodeF8, |
| xkF9: key.CodeF9, |
| xkF10: key.CodeF10, |
| xkF11: key.CodeF11, |
| xkF12: key.CodeF12, |
| |
| xkShiftL: key.CodeLeftShift, |
| xkShiftR: key.CodeRightShift, |
| xkControlL: key.CodeLeftControl, |
| xkControlR: key.CodeRightControl, |
| xkAltL: key.CodeLeftAlt, |
| xkAltR: key.CodeRightAlt, |
| xkSuperL: key.CodeLeftGUI, |
| xkSuperR: key.CodeRightGUI, |
| |
| xkDelete: key.CodeDeleteForward, |
| |
| xf86xkAudioRaiseVolume: key.CodeVolumeUp, |
| xf86xkAudioLowerVolume: key.CodeVolumeDown, |
| xf86xkAudioMute: key.CodeMute, |
| } |
| |
| // asciiKeycodes maps lower-case ASCII runes to key.Code values. |
| var asciiKeycodes = [0x80]key.Code{ |
| 'a': key.CodeA, |
| 'b': key.CodeB, |
| 'c': key.CodeC, |
| 'd': key.CodeD, |
| 'e': key.CodeE, |
| 'f': key.CodeF, |
| 'g': key.CodeG, |
| 'h': key.CodeH, |
| 'i': key.CodeI, |
| 'j': key.CodeJ, |
| 'k': key.CodeK, |
| 'l': key.CodeL, |
| 'm': key.CodeM, |
| 'n': key.CodeN, |
| 'o': key.CodeO, |
| 'p': key.CodeP, |
| 'q': key.CodeQ, |
| 'r': key.CodeR, |
| 's': key.CodeS, |
| 't': key.CodeT, |
| 'u': key.CodeU, |
| 'v': key.CodeV, |
| 'w': key.CodeW, |
| 'x': key.CodeX, |
| 'y': key.CodeY, |
| 'z': key.CodeZ, |
| |
| '1': key.Code1, |
| '2': key.Code2, |
| '3': key.Code3, |
| '4': key.Code4, |
| '5': key.Code5, |
| '6': key.Code6, |
| '7': key.Code7, |
| '8': key.Code8, |
| '9': key.Code9, |
| '0': key.Code0, |
| |
| ' ': key.CodeSpacebar, |
| '-': key.CodeHyphenMinus, |
| '=': key.CodeEqualSign, |
| '[': key.CodeLeftSquareBracket, |
| ']': key.CodeRightSquareBracket, |
| '\\': key.CodeBackslash, |
| ';': key.CodeSemicolon, |
| '\'': key.CodeApostrophe, |
| '`': key.CodeGraveAccent, |
| ',': key.CodeComma, |
| '.': key.CodeFullStop, |
| '/': key.CodeSlash, |
| |
| // TODO: distinguish CodeKeypadSlash vs CodeSlash, and similarly for other |
| // keypad codes. |
| } |