github.com/as/shiny@v0.8.2/driver/internal/x11key/x11key.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // x11key contains X11 numeric codes for the keyboard and mouse. 6 package x11key // import "github.com/as/shiny/driver/internal/x11key" 7 8 import ( 9 "github.com/as/shiny/event/key" 10 ) 11 12 // These constants come from /usr/include/X11/X.h 13 const ( 14 ShiftMask = 1 << 0 15 LockMask = 1 << 1 16 ControlMask = 1 << 2 17 Mod1Mask = 1 << 3 18 Mod2Mask = 1 << 4 19 Mod3Mask = 1 << 5 20 Mod4Mask = 1 << 6 21 Mod5Mask = 1 << 7 22 Button1Mask = 1 << 8 23 Button2Mask = 1 << 9 24 Button3Mask = 1 << 10 25 Button4Mask = 1 << 11 26 Button5Mask = 1 << 12 27 ) 28 29 type KeysymTable [256][2]uint32 30 31 func (t *KeysymTable) Lookup(detail uint8, state uint16) (rune, key.Code) { 32 // The key event's rune depends on whether the shift key is down. 33 unshifted := rune(t[detail][0]) 34 r := unshifted 35 if state&ShiftMask != 0 { 36 r = rune(t[detail][1]) 37 // In X11, a zero keysym when shift is down means to use what the 38 // keysym is when shift is up. 39 if r == 0 { 40 r = unshifted 41 } 42 } 43 44 // The key event's code is independent of whether the shift key is down. 45 var c key.Code 46 if 0 <= unshifted && unshifted < 0x80 { 47 // TODO: distinguish the regular '2' key and number-pad '2' key (with 48 // Num-Lock). 49 c = asciiKeycodes[unshifted] 50 } else { 51 r, c = -1, nonUnicodeKeycodes[unshifted] 52 } 53 54 if state&ControlMask != 0 { 55 switch r { 56 case 'u': 57 r = '\x15' 58 case 'a': 59 r = '\x01' 60 case 'e': 61 r = '\x05' 62 case 'w': 63 r = '\x17' 64 } 65 } 66 67 // TODO: Unicode-but-not-ASCII keysyms like the Swiss keyboard's 'รถ'. 68 return r, c 69 } 70 71 func KeyModifiers(state uint16) (m key.Modifiers) { 72 if state&ShiftMask != 0 { 73 m |= key.ModShift 74 } 75 if state&ControlMask != 0 { 76 m |= key.ModControl 77 } 78 if state&Mod1Mask != 0 { 79 m |= key.ModAlt 80 } 81 if state&Mod4Mask != 0 { 82 m |= key.ModMeta 83 } 84 return m 85 } 86 87 // These constants come from /usr/include/X11/{keysymdef,XF86keysym}.h 88 const ( 89 xkISOLeftTab = 0xfe20 90 xkBackSpace = 0xff08 91 xkTab = 0xff09 92 xkReturn = 0xff0d 93 xkEscape = 0xff1b 94 xkMultiKey = 0xff20 95 xkHome = 0xff50 96 xkLeft = 0xff51 97 xkUp = 0xff52 98 xkRight = 0xff53 99 xkDown = 0xff54 100 xkPageUp = 0xff55 101 xkPageDown = 0xff56 102 xkEnd = 0xff57 103 xkInsert = 0xff63 104 xkMenu = 0xff67 105 xkF1 = 0xffbe 106 xkF2 = 0xffbf 107 xkF3 = 0xffc0 108 xkF4 = 0xffc1 109 xkF5 = 0xffc2 110 xkF6 = 0xffc3 111 xkF7 = 0xffc4 112 xkF8 = 0xffc5 113 xkF9 = 0xffc6 114 xkF10 = 0xffc7 115 xkF11 = 0xffc8 116 xkF12 = 0xffc9 117 xkShiftL = 0xffe1 118 xkShiftR = 0xffe2 119 xkControlL = 0xffe3 120 xkControlR = 0xffe4 121 xkAltL = 0xffe9 122 xkAltR = 0xffea 123 xkSuperL = 0xffeb 124 xkSuperR = 0xffec 125 xkDelete = 0xffff 126 127 xf86xkAudioLowerVolume = 0x1008ff11 128 xf86xkAudioMute = 0x1008ff12 129 xf86xkAudioRaiseVolume = 0x1008ff13 130 ) 131 132 // nonUnicodeKeycodes maps from those xproto.Keysym values (converted to runes) 133 // that do not correspond to a Unicode code point, such as "Page Up", "F1" or 134 // "Left Shift", to key.Code values. 135 var nonUnicodeKeycodes = map[rune]key.Code{ 136 xkISOLeftTab: key.CodeTab, 137 xkBackSpace: key.CodeDeleteBackspace, 138 xkTab: key.CodeTab, 139 xkReturn: key.CodeReturnEnter, 140 xkEscape: key.CodeEscape, 141 xkHome: key.CodeHome, 142 xkLeft: key.CodeLeftArrow, 143 xkUp: key.CodeUpArrow, 144 xkRight: key.CodeRightArrow, 145 xkDown: key.CodeDownArrow, 146 xkPageUp: key.CodePageUp, 147 xkPageDown: key.CodePageDown, 148 xkEnd: key.CodeEnd, 149 xkInsert: key.CodeInsert, 150 xkMenu: key.CodeRightGUI, // TODO: CodeRightGUI or CodeMenu?? 151 xkMultiKey: key.CodeCompose, 152 153 xkF1: key.CodeF1, 154 xkF2: key.CodeF2, 155 xkF3: key.CodeF3, 156 xkF4: key.CodeF4, 157 xkF5: key.CodeF5, 158 xkF6: key.CodeF6, 159 xkF7: key.CodeF7, 160 xkF8: key.CodeF8, 161 xkF9: key.CodeF9, 162 xkF10: key.CodeF10, 163 xkF11: key.CodeF11, 164 xkF12: key.CodeF12, 165 166 xkShiftL: key.CodeLeftShift, 167 xkShiftR: key.CodeRightShift, 168 xkControlL: key.CodeLeftControl, 169 xkControlR: key.CodeRightControl, 170 xkAltL: key.CodeLeftAlt, 171 xkAltR: key.CodeRightAlt, 172 xkSuperL: key.CodeLeftGUI, 173 xkSuperR: key.CodeRightGUI, 174 175 xkDelete: key.CodeDeleteForward, 176 177 xf86xkAudioRaiseVolume: key.CodeVolumeUp, 178 xf86xkAudioLowerVolume: key.CodeVolumeDown, 179 xf86xkAudioMute: key.CodeMute, 180 } 181 182 // asciiKeycodes maps lower-case ASCII runes to key.Code values. 183 var asciiKeycodes = [0x80]key.Code{ 184 'a': key.CodeA, 185 'b': key.CodeB, 186 'c': key.CodeC, 187 'd': key.CodeD, 188 'e': key.CodeE, 189 'f': key.CodeF, 190 'g': key.CodeG, 191 'h': key.CodeH, 192 'i': key.CodeI, 193 'j': key.CodeJ, 194 'k': key.CodeK, 195 'l': key.CodeL, 196 'm': key.CodeM, 197 'n': key.CodeN, 198 'o': key.CodeO, 199 'p': key.CodeP, 200 'q': key.CodeQ, 201 'r': key.CodeR, 202 's': key.CodeS, 203 't': key.CodeT, 204 'u': key.CodeU, 205 'v': key.CodeV, 206 'w': key.CodeW, 207 'x': key.CodeX, 208 'y': key.CodeY, 209 'z': key.CodeZ, 210 211 '1': key.Code1, 212 '2': key.Code2, 213 '3': key.Code3, 214 '4': key.Code4, 215 '5': key.Code5, 216 '6': key.Code6, 217 '7': key.Code7, 218 '8': key.Code8, 219 '9': key.Code9, 220 '0': key.Code0, 221 222 ' ': key.CodeSpacebar, 223 '-': key.CodeHyphenMinus, 224 '=': key.CodeEqualSign, 225 '[': key.CodeLeftSquareBracket, 226 ']': key.CodeRightSquareBracket, 227 '\\': key.CodeBackslash, 228 ';': key.CodeSemicolon, 229 '\'': key.CodeApostrophe, 230 '`': key.CodeGraveAccent, 231 ',': key.CodeComma, 232 '.': key.CodeFullStop, 233 '/': key.CodeSlash, 234 235 // TODO: distinguish CodeKeypadSlash vs CodeSlash, and similarly for other 236 // keypad codes. 237 }