github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/shiny/driver/internal/win32/key.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 package win32 6 7 import ( 8 "fmt" 9 "unicode/utf16" 10 11 "golang.org/x/mobile/event/key" 12 ) 13 14 // convVirtualKeyCode converts a Win32 virtual key code number 15 // into the standard keycodes used by the key package. 16 func convVirtualKeyCode(vKey uint32) key.Code { 17 switch vKey { 18 case 0x01: // VK_LBUTTON left mouse button 19 case 0x02: // VK_RBUTTON right mouse button 20 case 0x03: // VK_CANCEL control-break processing 21 case 0x04: // VK_MBUTTON middle mouse button 22 case 0x05: // VK_XBUTTON1 X1 mouse button 23 case 0x06: // VK_XBUTTON2 X2 mouse button 24 case 0x08: // VK_BACK 25 return key.CodeDeleteBackspace 26 case 0x09: // VK_TAB 27 return key.CodeTab 28 case 0x0C: // VK_CLEAR 29 case 0x0D: // VK_RETURN 30 return key.CodeReturnEnter 31 case 0x10: // VK_SHIFT 32 return key.CodeLeftShift 33 case 0x11: // VK_CONTROL 34 return key.CodeLeftControl 35 case 0x12: // VK_MENU 36 return key.CodeLeftAlt 37 case 0x13: // VK_PAUSE 38 case 0x14: // VK_CAPITAL 39 return key.CodeCapsLock 40 case 0x15: // VK_KANA, VK_HANGUEL, VK_HANGUL 41 case 0x17: // VK_JUNJA 42 case 0x18: // VK_FINA, L 43 case 0x19: // VK_HANJA, VK_KANJI 44 case 0x1B: // VK_ESCAPE 45 return key.CodeEscape 46 case 0x1C: // VK_CONVERT 47 case 0x1D: // VK_NONCONVERT 48 case 0x1E: // VK_ACCEPT 49 case 0x1F: // VK_MODECHANGE 50 case 0x20: // VK_SPACE 51 return key.CodeSpacebar 52 case 0x21: // VK_PRIOR 53 return key.CodePageUp 54 case 0x22: // VK_NEXT 55 return key.CodePageDown 56 case 0x23: // VK_END 57 return key.CodeEnd 58 case 0x24: // VK_HOME 59 return key.CodeHome 60 case 0x25: // VK_LEFT 61 return key.CodeLeftArrow 62 case 0x26: // VK_UP 63 return key.CodeUpArrow 64 case 0x27: // VK_RIGHT 65 return key.CodeRightArrow 66 case 0x28: // VK_DOWN 67 return key.CodeDownArrow 68 case 0x29: // VK_SELECT 69 case 0x2A: // VK_PRINT 70 case 0x2B: // VK_EXECUTE 71 case 0x2C: // VK_SNAPSHOT 72 case 0x2D: // VK_INSERT 73 case 0x2E: // VK_DELETE 74 return key.CodeDeleteForward 75 case 0x2F: // VK_HELP 76 return key.CodeHelp 77 case 0x30: 78 return key.Code0 79 case 0x31: 80 return key.Code1 81 case 0x32: 82 return key.Code2 83 case 0x33: 84 return key.Code3 85 case 0x34: 86 return key.Code4 87 case 0x35: 88 return key.Code5 89 case 0x36: 90 return key.Code6 91 case 0x37: 92 return key.Code7 93 case 0x38: 94 return key.Code8 95 case 0x39: 96 return key.Code9 97 case 0x41: 98 return key.CodeA 99 case 0x42: 100 return key.CodeB 101 case 0x43: 102 return key.CodeC 103 case 0x44: 104 return key.CodeD 105 case 0x45: 106 return key.CodeE 107 case 0x46: 108 return key.CodeF 109 case 0x47: 110 return key.CodeG 111 case 0x48: 112 return key.CodeH 113 case 0x49: 114 return key.CodeI 115 case 0x4A: 116 return key.CodeJ 117 case 0x4B: 118 return key.CodeK 119 case 0x4C: 120 return key.CodeL 121 case 0x4D: 122 return key.CodeM 123 case 0x4E: 124 return key.CodeN 125 case 0x4F: 126 return key.CodeO 127 case 0x50: 128 return key.CodeP 129 case 0x51: 130 return key.CodeQ 131 case 0x52: 132 return key.CodeR 133 case 0x53: 134 return key.CodeS 135 case 0x54: 136 return key.CodeT 137 case 0x55: 138 return key.CodeU 139 case 0x56: 140 return key.CodeV 141 case 0x57: 142 return key.CodeW 143 case 0x58: 144 return key.CodeX 145 case 0x59: 146 return key.CodeY 147 case 0x5A: 148 return key.CodeZ 149 case 0x5B: // VK_LWIN 150 return key.CodeLeftGUI 151 case 0x5C: // VK_RWIN 152 return key.CodeRightGUI 153 case 0x5D: // VK_APPS 154 case 0x5F: // VK_SLEEP 155 case 0x60: // VK_NUMPAD0 156 return key.CodeKeypad0 157 case 0x61: // VK_NUMPAD1 158 return key.CodeKeypad1 159 case 0x62: // VK_NUMPAD2 160 return key.CodeKeypad2 161 case 0x63: // VK_NUMPAD3 162 return key.CodeKeypad3 163 case 0x64: // VK_NUMPAD4 164 return key.CodeKeypad4 165 case 0x65: // VK_NUMPAD5 166 return key.CodeKeypad5 167 case 0x66: // VK_NUMPAD6 168 return key.CodeKeypad6 169 case 0x67: // VK_NUMPAD7 170 return key.CodeKeypad7 171 case 0x68: // VK_NUMPAD8 172 return key.CodeKeypad8 173 case 0x69: // VK_NUMPAD9 174 return key.CodeKeypad9 175 case 0x6A: // VK_MULTIPLY 176 return key.CodeKeypadAsterisk 177 case 0x6B: // VK_ADD 178 return key.CodeKeypadPlusSign 179 case 0x6C: // VK_SEPARATOR 180 case 0x6D: // VK_SUBTRACT 181 return key.CodeKeypadHyphenMinus 182 case 0x6E: // VK_DECIMAL 183 return key.CodeFullStop 184 case 0x6F: // VK_DIVIDE 185 return key.CodeKeypadSlash 186 case 0x70: // VK_F1 187 return key.CodeF1 188 case 0x71: // VK_F2 189 return key.CodeF2 190 case 0x72: // VK_F3 191 return key.CodeF3 192 case 0x73: // VK_F4 193 return key.CodeF4 194 case 0x74: // VK_F5 195 return key.CodeF5 196 case 0x75: // VK_F6 197 return key.CodeF6 198 case 0x76: // VK_F7 199 return key.CodeF7 200 case 0x77: // VK_F8 201 return key.CodeF8 202 case 0x78: // VK_F9 203 return key.CodeF9 204 case 0x79: // VK_F10 205 return key.CodeF10 206 case 0x7A: // VK_F11 207 return key.CodeF11 208 case 0x7B: // VK_F12 209 return key.CodeF12 210 case 0x7C: // VK_F13 211 return key.CodeF13 212 case 0x7D: // VK_F14 213 return key.CodeF14 214 case 0x7E: // VK_F15 215 return key.CodeF15 216 case 0x7F: // VK_F16 217 return key.CodeF16 218 case 0x80: // VK_F17 219 return key.CodeF17 220 case 0x81: // VK_F18 221 return key.CodeF18 222 case 0x82: // VK_F19 223 return key.CodeF19 224 case 0x83: // VK_F20 225 return key.CodeF20 226 case 0x84: // VK_F21 227 return key.CodeF21 228 case 0x85: // VK_F22 229 return key.CodeF22 230 case 0x86: // VK_F23 231 return key.CodeF23 232 case 0x87: // VK_F24 233 return key.CodeF24 234 case 0x90: // VK_NUMLOCK 235 return key.CodeKeypadNumLock 236 case 0x91: // VK_SCROLL 237 case 0xA0: // VK_LSHIFT 238 return key.CodeLeftShift 239 case 0xA1: // VK_RSHIFT 240 return key.CodeRightShift 241 case 0xA2: // VK_LCONTROL 242 return key.CodeLeftControl 243 case 0xA3: // VK_RCONTROL 244 return key.CodeRightControl 245 case 0xA4: // VK_LMENU 246 case 0xA5: // VK_RMENU 247 case 0xA6: // VK_BROWSER_BACK 248 case 0xA7: // VK_BROWSER_FORWARD 249 case 0xA8: // VK_BROWSER_REFRESH 250 case 0xA9: // VK_BROWSER_STOP 251 case 0xAA: // VK_BROWSER_SEARCH 252 case 0xAB: // VK_BROWSER_FAVORITES 253 case 0xAC: // VK_BROWSER_HOME 254 case 0xAD: // VK_VOLUME_MUTE 255 return key.CodeMute 256 case 0xAE: // VK_VOLUME_DOWN 257 return key.CodeVolumeDown 258 case 0xAF: // VK_VOLUME_UP 259 return key.CodeVolumeUp 260 case 0xB0: // VK_MEDIA_NEXT_TRACK 261 case 0xB1: // VK_MEDIA_PREV_TRACK 262 case 0xB2: // VK_MEDIA_STOP 263 case 0xB3: // VK_MEDIA_PLAY_PAUSE 264 case 0xB4: // VK_LAUNCH_MAIL 265 case 0xB5: // VK_LAUNCH_MEDIA_SELECT 266 case 0xB6: // VK_LAUNCH_APP1 267 case 0xB7: // VK_LAUNCH_APP2 268 case 0xBA: // VK_OEM_1 ';:' 269 return key.CodeSemicolon 270 case 0xBB: // VK_OEM_PLUS '+' 271 return key.CodeEqualSign 272 case 0xBC: // VK_OEM_COMMA ',' 273 return key.CodeComma 274 case 0xBD: // VK_OEM_MINUS '-' 275 return key.CodeHyphenMinus 276 case 0xBE: // VK_OEM_PERIOD '.' 277 return key.CodeFullStop 278 case 0xBF: // VK_OEM_2 '/?' 279 return key.CodeSlash 280 case 0xC0: // VK_OEM_3 '`~' 281 return key.CodeGraveAccent 282 case 0xDB: // VK_OEM_4 '[{' 283 return key.CodeLeftSquareBracket 284 case 0xDC: // VK_OEM_5 '\|' 285 return key.CodeBackslash 286 case 0xDD: // VK_OEM_6 ']}' 287 return key.CodeRightSquareBracket 288 case 0xDE: // VK_OEM_7 'single-quote/double-quote' 289 return key.CodeApostrophe 290 case 0xDF: // VK_OEM_8 291 return key.CodeUnknown 292 case 0xE2: // VK_OEM_102 293 case 0xE5: // VK_PROCESSKEY 294 case 0xE7: // VK_PACKET 295 case 0xF6: // VK_ATTN 296 case 0xF7: // VK_CRSEL 297 case 0xF8: // VK_EXSEL 298 case 0xF9: // VK_EREOF 299 case 0xFA: // VK_PLAY 300 case 0xFB: // VK_ZOOM 301 case 0xFC: // VK_NONAME 302 case 0xFD: // VK_PA1 303 case 0xFE: // VK_OEM_CLEAR 304 } 305 return key.CodeUnknown 306 } 307 308 func readRune(vKey uint32, scanCode uint8) rune { 309 var ( 310 keystate [256]byte 311 buf [4]uint16 312 ) 313 if err := _GetKeyboardState(&keystate[0]); err != nil { 314 panic(fmt.Sprintf("win32: %v", err)) 315 } 316 // TODO: cache GetKeyboardLayout result, update on WM_INPUTLANGCHANGE 317 layout := _GetKeyboardLayout(0) 318 ret := _ToUnicodeEx(vKey, uint32(scanCode), &keystate[0], &buf[0], int32(len(buf)), 0, layout) 319 if ret < 1 { 320 return -1 321 } 322 return utf16.Decode(buf[:ret])[0] 323 } 324 325 func sendKeyEvent(hwnd HWND, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { 326 e := key.Event{ 327 Rune: readRune(uint32(wParam), uint8(lParam>>16)), 328 Code: convVirtualKeyCode(uint32(wParam)), 329 Modifiers: keyModifiers(), 330 } 331 switch uMsg { 332 case _WM_KEYDOWN: 333 const prevMask = 1 << 30 334 if repeat := lParam&prevMask == prevMask; repeat { 335 e.Direction = key.DirNone 336 } else { 337 e.Direction = key.DirPress 338 } 339 case _WM_KEYUP: 340 e.Direction = key.DirRelease 341 default: 342 panic(fmt.Sprintf("win32: unexpected key message: %d", uMsg)) 343 } 344 345 KeyEvent(hwnd, e) 346 return 0 347 }