win32input.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package input
  2. import (
  3. "unicode"
  4. "github.com/erikgeiser/coninput"
  5. )
  6. func parseWin32InputKeyEvent(vkc coninput.VirtualKeyCode, _ coninput.VirtualKeyCode, r rune, keyDown bool, cks coninput.ControlKeyState, repeatCount uint16) Event {
  7. var key Key
  8. isCtrl := cks.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED)
  9. switch vkc {
  10. case coninput.VK_SHIFT:
  11. // We currently ignore these keys when they are pressed alone.
  12. return nil
  13. case coninput.VK_MENU:
  14. if cks.Contains(coninput.LEFT_ALT_PRESSED) {
  15. key = Key{Sym: KeyLeftAlt}
  16. } else if cks.Contains(coninput.RIGHT_ALT_PRESSED) {
  17. key = Key{Sym: KeyRightAlt}
  18. } else if !keyDown {
  19. return nil
  20. }
  21. case coninput.VK_CONTROL:
  22. if cks.Contains(coninput.LEFT_CTRL_PRESSED) {
  23. key = Key{Sym: KeyLeftCtrl}
  24. } else if cks.Contains(coninput.RIGHT_CTRL_PRESSED) {
  25. key = Key{Sym: KeyRightCtrl}
  26. } else if !keyDown {
  27. return nil
  28. }
  29. case coninput.VK_CAPITAL:
  30. key = Key{Sym: KeyCapsLock}
  31. default:
  32. var ok bool
  33. key, ok = vkKeyEvent[vkc]
  34. if !ok {
  35. if isCtrl {
  36. key = vkCtrlRune(key, r, vkc)
  37. } else {
  38. key = Key{Rune: r}
  39. }
  40. }
  41. }
  42. if isCtrl {
  43. key.Mod |= ModCtrl
  44. }
  45. if cks.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED) {
  46. key.Mod |= ModAlt
  47. }
  48. if cks.Contains(coninput.SHIFT_PRESSED) {
  49. key.Mod |= ModShift
  50. }
  51. if cks.Contains(coninput.CAPSLOCK_ON) {
  52. key.Mod |= ModCapsLock
  53. }
  54. if cks.Contains(coninput.NUMLOCK_ON) {
  55. key.Mod |= ModNumLock
  56. }
  57. if cks.Contains(coninput.SCROLLLOCK_ON) {
  58. key.Mod |= ModScrollLock
  59. }
  60. // Use the unshifted key
  61. if cks.Contains(coninput.SHIFT_PRESSED ^ coninput.CAPSLOCK_ON) {
  62. key.AltRune = unicode.ToUpper(key.Rune)
  63. } else {
  64. key.AltRune = unicode.ToLower(key.Rune)
  65. }
  66. var e Event = KeyPressEvent(key)
  67. key.IsRepeat = repeatCount > 1
  68. if !keyDown {
  69. e = KeyReleaseEvent(key)
  70. }
  71. if repeatCount <= 1 {
  72. return e
  73. }
  74. var kevents []Event
  75. for i := 0; i < int(repeatCount); i++ {
  76. kevents = append(kevents, e)
  77. }
  78. return MultiEvent(kevents)
  79. }
  80. var vkKeyEvent = map[coninput.VirtualKeyCode]Key{
  81. coninput.VK_RETURN: {Sym: KeyEnter},
  82. coninput.VK_BACK: {Sym: KeyBackspace},
  83. coninput.VK_TAB: {Sym: KeyTab},
  84. coninput.VK_ESCAPE: {Sym: KeyEscape},
  85. coninput.VK_SPACE: {Sym: KeySpace, Rune: ' '},
  86. coninput.VK_UP: {Sym: KeyUp},
  87. coninput.VK_DOWN: {Sym: KeyDown},
  88. coninput.VK_RIGHT: {Sym: KeyRight},
  89. coninput.VK_LEFT: {Sym: KeyLeft},
  90. coninput.VK_HOME: {Sym: KeyHome},
  91. coninput.VK_END: {Sym: KeyEnd},
  92. coninput.VK_PRIOR: {Sym: KeyPgUp},
  93. coninput.VK_NEXT: {Sym: KeyPgDown},
  94. coninput.VK_DELETE: {Sym: KeyDelete},
  95. coninput.VK_SELECT: {Sym: KeySelect},
  96. coninput.VK_SNAPSHOT: {Sym: KeyPrintScreen},
  97. coninput.VK_INSERT: {Sym: KeyInsert},
  98. coninput.VK_LWIN: {Sym: KeyLeftSuper},
  99. coninput.VK_RWIN: {Sym: KeyRightSuper},
  100. coninput.VK_APPS: {Sym: KeyMenu},
  101. coninput.VK_NUMPAD0: {Sym: KeyKp0},
  102. coninput.VK_NUMPAD1: {Sym: KeyKp1},
  103. coninput.VK_NUMPAD2: {Sym: KeyKp2},
  104. coninput.VK_NUMPAD3: {Sym: KeyKp3},
  105. coninput.VK_NUMPAD4: {Sym: KeyKp4},
  106. coninput.VK_NUMPAD5: {Sym: KeyKp5},
  107. coninput.VK_NUMPAD6: {Sym: KeyKp6},
  108. coninput.VK_NUMPAD7: {Sym: KeyKp7},
  109. coninput.VK_NUMPAD8: {Sym: KeyKp8},
  110. coninput.VK_NUMPAD9: {Sym: KeyKp9},
  111. coninput.VK_MULTIPLY: {Sym: KeyKpMultiply},
  112. coninput.VK_ADD: {Sym: KeyKpPlus},
  113. coninput.VK_SEPARATOR: {Sym: KeyKpComma},
  114. coninput.VK_SUBTRACT: {Sym: KeyKpMinus},
  115. coninput.VK_DECIMAL: {Sym: KeyKpDecimal},
  116. coninput.VK_DIVIDE: {Sym: KeyKpDivide},
  117. coninput.VK_F1: {Sym: KeyF1},
  118. coninput.VK_F2: {Sym: KeyF2},
  119. coninput.VK_F3: {Sym: KeyF3},
  120. coninput.VK_F4: {Sym: KeyF4},
  121. coninput.VK_F5: {Sym: KeyF5},
  122. coninput.VK_F6: {Sym: KeyF6},
  123. coninput.VK_F7: {Sym: KeyF7},
  124. coninput.VK_F8: {Sym: KeyF8},
  125. coninput.VK_F9: {Sym: KeyF9},
  126. coninput.VK_F10: {Sym: KeyF10},
  127. coninput.VK_F11: {Sym: KeyF11},
  128. coninput.VK_F12: {Sym: KeyF12},
  129. coninput.VK_F13: {Sym: KeyF13},
  130. coninput.VK_F14: {Sym: KeyF14},
  131. coninput.VK_F15: {Sym: KeyF15},
  132. coninput.VK_F16: {Sym: KeyF16},
  133. coninput.VK_F17: {Sym: KeyF17},
  134. coninput.VK_F18: {Sym: KeyF18},
  135. coninput.VK_F19: {Sym: KeyF19},
  136. coninput.VK_F20: {Sym: KeyF20},
  137. coninput.VK_F21: {Sym: KeyF21},
  138. coninput.VK_F22: {Sym: KeyF22},
  139. coninput.VK_F23: {Sym: KeyF23},
  140. coninput.VK_F24: {Sym: KeyF24},
  141. coninput.VK_NUMLOCK: {Sym: KeyNumLock},
  142. coninput.VK_SCROLL: {Sym: KeyScrollLock},
  143. coninput.VK_LSHIFT: {Sym: KeyLeftShift},
  144. coninput.VK_RSHIFT: {Sym: KeyRightShift},
  145. coninput.VK_LCONTROL: {Sym: KeyLeftCtrl},
  146. coninput.VK_RCONTROL: {Sym: KeyRightCtrl},
  147. coninput.VK_LMENU: {Sym: KeyLeftAlt},
  148. coninput.VK_RMENU: {Sym: KeyRightAlt},
  149. coninput.VK_OEM_4: {Rune: '['},
  150. // TODO: add more keys
  151. }
  152. func vkCtrlRune(k Key, r rune, kc coninput.VirtualKeyCode) Key {
  153. switch r {
  154. case '@':
  155. k.Rune = '@'
  156. case '\x01':
  157. k.Rune = 'a'
  158. case '\x02':
  159. k.Rune = 'b'
  160. case '\x03':
  161. k.Rune = 'c'
  162. case '\x04':
  163. k.Rune = 'd'
  164. case '\x05':
  165. k.Rune = 'e'
  166. case '\x06':
  167. k.Rune = 'f'
  168. case '\a':
  169. k.Rune = 'g'
  170. case '\b':
  171. k.Rune = 'h'
  172. case '\t':
  173. k.Rune = 'i'
  174. case '\n':
  175. k.Rune = 'j'
  176. case '\v':
  177. k.Rune = 'k'
  178. case '\f':
  179. k.Rune = 'l'
  180. case '\r':
  181. k.Rune = 'm'
  182. case '\x0e':
  183. k.Rune = 'n'
  184. case '\x0f':
  185. k.Rune = 'o'
  186. case '\x10':
  187. k.Rune = 'p'
  188. case '\x11':
  189. k.Rune = 'q'
  190. case '\x12':
  191. k.Rune = 'r'
  192. case '\x13':
  193. k.Rune = 's'
  194. case '\x14':
  195. k.Rune = 't'
  196. case '\x15':
  197. k.Rune = 'u'
  198. case '\x16':
  199. k.Rune = 'v'
  200. case '\x17':
  201. k.Rune = 'w'
  202. case '\x18':
  203. k.Rune = 'x'
  204. case '\x19':
  205. k.Rune = 'y'
  206. case '\x1a':
  207. k.Rune = 'z'
  208. case '\x1b':
  209. k.Rune = ']'
  210. case '\x1c':
  211. k.Rune = '\\'
  212. case '\x1f':
  213. k.Rune = '_'
  214. }
  215. switch kc {
  216. case coninput.VK_OEM_4:
  217. k.Rune = '['
  218. }
  219. // https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
  220. if k.Rune == 0 &&
  221. (kc >= 0x30 && kc <= 0x39) ||
  222. (kc >= 0x41 && kc <= 0x5a) {
  223. k.Rune = rune(kc)
  224. }
  225. return k
  226. }