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  }