zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

key.go (8284B)


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