forked from toolshed/abra
15
vendor/github.com/erikgeiser/coninput/.gitignore
generated
vendored
Normal file
15
vendor/github.com/erikgeiser/coninput/.gitignore
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
24
vendor/github.com/erikgeiser/coninput/.golangci.yml
generated
vendored
Normal file
24
vendor/github.com/erikgeiser/coninput/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- golint
|
||||
- interfacer
|
||||
- scopelint
|
||||
- maligned
|
||||
- rowserrcheck
|
||||
- funlen
|
||||
- depguard
|
||||
- goerr113
|
||||
- exhaustivestruct
|
||||
- testpackage
|
||||
- gochecknoglobals
|
||||
- wrapcheck
|
||||
- forbidigo
|
||||
- ifshort
|
||||
- cyclop
|
||||
- gomoddirectives
|
||||
linters-settings:
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
issues:
|
||||
exclude-use-default: false
|
21
vendor/github.com/erikgeiser/coninput/LICENSE
generated
vendored
Normal file
21
vendor/github.com/erikgeiser/coninput/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Erik G.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2
vendor/github.com/erikgeiser/coninput/README.md
generated
vendored
Normal file
2
vendor/github.com/erikgeiser/coninput/README.md
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# coninput
|
||||
Go library for input handling using Windows Console API
|
205
vendor/github.com/erikgeiser/coninput/keycodes.go
generated
vendored
Normal file
205
vendor/github.com/erikgeiser/coninput/keycodes.go
generated
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
package coninput
|
||||
|
||||
// VirtualKeyCode holds a virtual key code (see
|
||||
// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes).
|
||||
type VirtualKeyCode uint16
|
||||
|
||||
const (
|
||||
VK_LBUTTON VirtualKeyCode = 0x01
|
||||
VK_RBUTTON VirtualKeyCode = 0x02
|
||||
VK_CANCEL VirtualKeyCode = 0x03
|
||||
VK_MBUTTON VirtualKeyCode = 0x04
|
||||
VK_XBUTTON1 VirtualKeyCode = 0x05
|
||||
VK_XBUTTON2 VirtualKeyCode = 0x06
|
||||
VK_BACK VirtualKeyCode = 0x08
|
||||
VK_TAB VirtualKeyCode = 0x09
|
||||
VK_CLEAR VirtualKeyCode = 0x0C
|
||||
VK_RETURN VirtualKeyCode = 0x0D
|
||||
VK_SHIFT VirtualKeyCode = 0x10
|
||||
VK_CONTROL VirtualKeyCode = 0x11
|
||||
VK_MENU VirtualKeyCode = 0x12
|
||||
VK_PAUSE VirtualKeyCode = 0x13
|
||||
VK_CAPITAL VirtualKeyCode = 0x14
|
||||
VK_KANA VirtualKeyCode = 0x15
|
||||
VK_HANGEUL VirtualKeyCode = 0x15
|
||||
VK_HANGUL VirtualKeyCode = 0x15
|
||||
VK_IME_ON VirtualKeyCode = 0x16
|
||||
VK_JUNJA VirtualKeyCode = 0x17
|
||||
VK_FINAL VirtualKeyCode = 0x18
|
||||
VK_HANJA VirtualKeyCode = 0x19
|
||||
VK_KANJI VirtualKeyCode = 0x19
|
||||
VK_IME_OFF VirtualKeyCode = 0x1A
|
||||
VK_ESCAPE VirtualKeyCode = 0x1B
|
||||
VK_CONVERT VirtualKeyCode = 0x1C
|
||||
VK_NONCONVERT VirtualKeyCode = 0x1D
|
||||
VK_ACCEPT VirtualKeyCode = 0x1E
|
||||
VK_MODECHANGE VirtualKeyCode = 0x1F
|
||||
VK_SPACE VirtualKeyCode = 0x20
|
||||
VK_PRIOR VirtualKeyCode = 0x21
|
||||
VK_NEXT VirtualKeyCode = 0x22
|
||||
VK_END VirtualKeyCode = 0x23
|
||||
VK_HOME VirtualKeyCode = 0x24
|
||||
VK_LEFT VirtualKeyCode = 0x25
|
||||
VK_UP VirtualKeyCode = 0x26
|
||||
VK_RIGHT VirtualKeyCode = 0x27
|
||||
VK_DOWN VirtualKeyCode = 0x28
|
||||
VK_SELECT VirtualKeyCode = 0x29
|
||||
VK_PRINT VirtualKeyCode = 0x2A
|
||||
VK_EXECUTE VirtualKeyCode = 0x2B
|
||||
VK_SNAPSHOT VirtualKeyCode = 0x2C
|
||||
VK_INSERT VirtualKeyCode = 0x2D
|
||||
VK_DELETE VirtualKeyCode = 0x2E
|
||||
VK_HELP VirtualKeyCode = 0x2F
|
||||
VK_0 VirtualKeyCode = 0x30
|
||||
VK_1 VirtualKeyCode = 0x31
|
||||
VK_2 VirtualKeyCode = 0x32
|
||||
VK_3 VirtualKeyCode = 0x33
|
||||
VK_4 VirtualKeyCode = 0x34
|
||||
VK_5 VirtualKeyCode = 0x35
|
||||
VK_6 VirtualKeyCode = 0x36
|
||||
VK_7 VirtualKeyCode = 0x37
|
||||
VK_8 VirtualKeyCode = 0x38
|
||||
VK_9 VirtualKeyCode = 0x39
|
||||
VK_A VirtualKeyCode = 0x41
|
||||
VK_B VirtualKeyCode = 0x42
|
||||
VK_C VirtualKeyCode = 0x43
|
||||
VK_D VirtualKeyCode = 0x44
|
||||
VK_E VirtualKeyCode = 0x45
|
||||
VK_F VirtualKeyCode = 0x46
|
||||
VK_G VirtualKeyCode = 0x47
|
||||
VK_H VirtualKeyCode = 0x48
|
||||
VK_I VirtualKeyCode = 0x49
|
||||
VK_J VirtualKeyCode = 0x4A
|
||||
VK_K VirtualKeyCode = 0x4B
|
||||
VK_L VirtualKeyCode = 0x4C
|
||||
VK_M VirtualKeyCode = 0x4D
|
||||
VK_N VirtualKeyCode = 0x4E
|
||||
VK_O VirtualKeyCode = 0x4F
|
||||
VK_P VirtualKeyCode = 0x50
|
||||
VK_Q VirtualKeyCode = 0x51
|
||||
VK_R VirtualKeyCode = 0x52
|
||||
VK_S VirtualKeyCode = 0x53
|
||||
VK_T VirtualKeyCode = 0x54
|
||||
VK_U VirtualKeyCode = 0x55
|
||||
VK_V VirtualKeyCode = 0x56
|
||||
VK_W VirtualKeyCode = 0x57
|
||||
VK_X VirtualKeyCode = 0x58
|
||||
VK_Y VirtualKeyCode = 0x59
|
||||
VK_Z VirtualKeyCode = 0x5A
|
||||
VK_LWIN VirtualKeyCode = 0x5B
|
||||
VK_RWIN VirtualKeyCode = 0x5C
|
||||
VK_APPS VirtualKeyCode = 0x5D
|
||||
VK_SLEEP VirtualKeyCode = 0x5F
|
||||
VK_NUMPAD0 VirtualKeyCode = 0x60
|
||||
VK_NUMPAD1 VirtualKeyCode = 0x61
|
||||
VK_NUMPAD2 VirtualKeyCode = 0x62
|
||||
VK_NUMPAD3 VirtualKeyCode = 0x63
|
||||
VK_NUMPAD4 VirtualKeyCode = 0x64
|
||||
VK_NUMPAD5 VirtualKeyCode = 0x65
|
||||
VK_NUMPAD6 VirtualKeyCode = 0x66
|
||||
VK_NUMPAD7 VirtualKeyCode = 0x67
|
||||
VK_NUMPAD8 VirtualKeyCode = 0x68
|
||||
VK_NUMPAD9 VirtualKeyCode = 0x69
|
||||
VK_MULTIPLY VirtualKeyCode = 0x6A
|
||||
VK_ADD VirtualKeyCode = 0x6B
|
||||
VK_SEPARATOR VirtualKeyCode = 0x6C
|
||||
VK_SUBTRACT VirtualKeyCode = 0x6D
|
||||
VK_DECIMAL VirtualKeyCode = 0x6E
|
||||
VK_DIVIDE VirtualKeyCode = 0x6F
|
||||
VK_F1 VirtualKeyCode = 0x70
|
||||
VK_F2 VirtualKeyCode = 0x71
|
||||
VK_F3 VirtualKeyCode = 0x72
|
||||
VK_F4 VirtualKeyCode = 0x73
|
||||
VK_F5 VirtualKeyCode = 0x74
|
||||
VK_F6 VirtualKeyCode = 0x75
|
||||
VK_F7 VirtualKeyCode = 0x76
|
||||
VK_F8 VirtualKeyCode = 0x77
|
||||
VK_F9 VirtualKeyCode = 0x78
|
||||
VK_F10 VirtualKeyCode = 0x79
|
||||
VK_F11 VirtualKeyCode = 0x7A
|
||||
VK_F12 VirtualKeyCode = 0x7B
|
||||
VK_F13 VirtualKeyCode = 0x7C
|
||||
VK_F14 VirtualKeyCode = 0x7D
|
||||
VK_F15 VirtualKeyCode = 0x7E
|
||||
VK_F16 VirtualKeyCode = 0x7F
|
||||
VK_F17 VirtualKeyCode = 0x80
|
||||
VK_F18 VirtualKeyCode = 0x81
|
||||
VK_F19 VirtualKeyCode = 0x82
|
||||
VK_F20 VirtualKeyCode = 0x83
|
||||
VK_F21 VirtualKeyCode = 0x84
|
||||
VK_F22 VirtualKeyCode = 0x85
|
||||
VK_F23 VirtualKeyCode = 0x86
|
||||
VK_F24 VirtualKeyCode = 0x87
|
||||
VK_NUMLOCK VirtualKeyCode = 0x90
|
||||
VK_SCROLL VirtualKeyCode = 0x91
|
||||
VK_OEM_NEC_EQUAL VirtualKeyCode = 0x92
|
||||
VK_OEM_FJ_JISHO VirtualKeyCode = 0x92
|
||||
VK_OEM_FJ_MASSHOU VirtualKeyCode = 0x93
|
||||
VK_OEM_FJ_TOUROKU VirtualKeyCode = 0x94
|
||||
VK_OEM_FJ_LOYA VirtualKeyCode = 0x95
|
||||
VK_OEM_FJ_ROYA VirtualKeyCode = 0x96
|
||||
VK_LSHIFT VirtualKeyCode = 0xA0
|
||||
VK_RSHIFT VirtualKeyCode = 0xA1
|
||||
VK_LCONTROL VirtualKeyCode = 0xA2
|
||||
VK_RCONTROL VirtualKeyCode = 0xA3
|
||||
VK_LMENU VirtualKeyCode = 0xA4
|
||||
VK_RMENU VirtualKeyCode = 0xA5
|
||||
VK_BROWSER_BACK VirtualKeyCode = 0xA6
|
||||
VK_BROWSER_FORWARD VirtualKeyCode = 0xA7
|
||||
VK_BROWSER_REFRESH VirtualKeyCode = 0xA8
|
||||
VK_BROWSER_STOP VirtualKeyCode = 0xA9
|
||||
VK_BROWSER_SEARCH VirtualKeyCode = 0xAA
|
||||
VK_BROWSER_FAVORITES VirtualKeyCode = 0xAB
|
||||
VK_BROWSER_HOME VirtualKeyCode = 0xAC
|
||||
VK_VOLUME_MUTE VirtualKeyCode = 0xAD
|
||||
VK_VOLUME_DOWN VirtualKeyCode = 0xAE
|
||||
VK_VOLUME_UP VirtualKeyCode = 0xAF
|
||||
VK_MEDIA_NEXT_TRACK VirtualKeyCode = 0xB0
|
||||
VK_MEDIA_PREV_TRACK VirtualKeyCode = 0xB1
|
||||
VK_MEDIA_STOP VirtualKeyCode = 0xB2
|
||||
VK_MEDIA_PLAY_PAUSE VirtualKeyCode = 0xB3
|
||||
VK_LAUNCH_MAIL VirtualKeyCode = 0xB4
|
||||
VK_LAUNCH_MEDIA_SELECT VirtualKeyCode = 0xB5
|
||||
VK_LAUNCH_APP1 VirtualKeyCode = 0xB6
|
||||
VK_LAUNCH_APP2 VirtualKeyCode = 0xB7
|
||||
VK_OEM_1 VirtualKeyCode = 0xBA
|
||||
VK_OEM_PLUS VirtualKeyCode = 0xBB
|
||||
VK_OEM_COMMA VirtualKeyCode = 0xBC
|
||||
VK_OEM_MINUS VirtualKeyCode = 0xBD
|
||||
VK_OEM_PERIOD VirtualKeyCode = 0xBE
|
||||
VK_OEM_2 VirtualKeyCode = 0xBF
|
||||
VK_OEM_3 VirtualKeyCode = 0xC0
|
||||
VK_OEM_4 VirtualKeyCode = 0xDB
|
||||
VK_OEM_5 VirtualKeyCode = 0xDC
|
||||
VK_OEM_6 VirtualKeyCode = 0xDD
|
||||
VK_OEM_7 VirtualKeyCode = 0xDE
|
||||
VK_OEM_8 VirtualKeyCode = 0xDF
|
||||
VK_OEM_AX VirtualKeyCode = 0xE1
|
||||
VK_OEM_102 VirtualKeyCode = 0xE2
|
||||
VK_ICO_HELP VirtualKeyCode = 0xE3
|
||||
VK_ICO_00 VirtualKeyCode = 0xE4
|
||||
VK_PROCESSKEY VirtualKeyCode = 0xE5
|
||||
VK_ICO_CLEAR VirtualKeyCode = 0xE6
|
||||
VK_OEM_RESET VirtualKeyCode = 0xE9
|
||||
VK_OEM_JUMP VirtualKeyCode = 0xEA
|
||||
VK_OEM_PA1 VirtualKeyCode = 0xEB
|
||||
VK_OEM_PA2 VirtualKeyCode = 0xEC
|
||||
VK_OEM_PA3 VirtualKeyCode = 0xED
|
||||
VK_OEM_WSCTRL VirtualKeyCode = 0xEE
|
||||
VK_OEM_CUSEL VirtualKeyCode = 0xEF
|
||||
VK_OEM_ATTN VirtualKeyCode = 0xF0
|
||||
VK_OEM_FINISH VirtualKeyCode = 0xF1
|
||||
VK_OEM_COPY VirtualKeyCode = 0xF2
|
||||
VK_OEM_AUTO VirtualKeyCode = 0xF3
|
||||
VK_OEM_ENLW VirtualKeyCode = 0xF4
|
||||
VK_OEM_BACKTAB VirtualKeyCode = 0xF5
|
||||
VK_ATTN VirtualKeyCode = 0xF6
|
||||
VK_CRSEL VirtualKeyCode = 0xF7
|
||||
VK_EXSEL VirtualKeyCode = 0xF8
|
||||
VK_EREOF VirtualKeyCode = 0xF9
|
||||
VK_PLAY VirtualKeyCode = 0xFA
|
||||
VK_ZOOM VirtualKeyCode = 0xFB
|
||||
VK_NONAME VirtualKeyCode = 0xFC
|
||||
VK_PA1 VirtualKeyCode = 0xFD
|
||||
VK_OEM_CLEAR VirtualKeyCode = 0xFE
|
||||
)
|
82
vendor/github.com/erikgeiser/coninput/mode.go
generated
vendored
Normal file
82
vendor/github.com/erikgeiser/coninput/mode.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package coninput
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// AddInputModes returns the given mode with one or more additional modes enabled.
|
||||
func AddInputModes(mode uint32, enableModes ...uint32) uint32 {
|
||||
for _, enableMode := range enableModes {
|
||||
mode |= enableMode
|
||||
}
|
||||
|
||||
return mode
|
||||
}
|
||||
|
||||
// RemoveInputModes returns the given mode with one or more additional modes disabled.
|
||||
func RemoveInputModes(mode uint32, disableModes ...uint32) uint32 {
|
||||
for _, disableMode := range disableModes {
|
||||
mode &^= disableMode
|
||||
}
|
||||
|
||||
return mode
|
||||
}
|
||||
|
||||
// ToggleInputModes returns the given mode with one or more additional modes toggeled.
|
||||
func ToggleInputModes(mode uint32, toggleModes ...uint32) uint32 {
|
||||
for _, toggeMode := range toggleModes {
|
||||
mode ^= toggeMode
|
||||
}
|
||||
|
||||
return mode
|
||||
}
|
||||
|
||||
var inputModes = []struct {
|
||||
mode uint32
|
||||
name string
|
||||
}{
|
||||
{mode: windows.ENABLE_ECHO_INPUT, name: "ENABLE_ECHO_INPUT"},
|
||||
{mode: windows.ENABLE_INSERT_MODE, name: "ENABLE_INSERT_MODE"},
|
||||
{mode: windows.ENABLE_LINE_INPUT, name: "ENABLE_LINE_INPUT"},
|
||||
{mode: windows.ENABLE_MOUSE_INPUT, name: "ENABLE_MOUSE_INPUT"},
|
||||
{mode: windows.ENABLE_PROCESSED_INPUT, name: "ENABLE_PROCESSED_INPUT"},
|
||||
{mode: windows.ENABLE_QUICK_EDIT_MODE, name: "ENABLE_QUICK_EDIT_MODE"},
|
||||
{mode: windows.ENABLE_WINDOW_INPUT, name: "ENABLE_WINDOW_INPUT"},
|
||||
{mode: windows.ENABLE_VIRTUAL_TERMINAL_INPUT, name: "ENABLE_VIRTUAL_TERMINAL_INPUT"},
|
||||
}
|
||||
|
||||
// ListInputMode returnes the isolated enabled input modes as a list.
|
||||
func ListInputModes(mode uint32) []uint32 {
|
||||
modes := []uint32{}
|
||||
|
||||
for _, inputMode := range inputModes {
|
||||
if mode&inputMode.mode > 0 {
|
||||
modes = append(modes, inputMode.mode)
|
||||
}
|
||||
}
|
||||
|
||||
return modes
|
||||
}
|
||||
|
||||
// ListInputMode returnes the isolated enabled input mode names as a list.
|
||||
func ListInputModeNames(mode uint32) []string {
|
||||
modes := []string{}
|
||||
|
||||
for _, inputMode := range inputModes {
|
||||
if mode&inputMode.mode > 0 {
|
||||
modes = append(modes, inputMode.name)
|
||||
}
|
||||
}
|
||||
|
||||
return modes
|
||||
}
|
||||
|
||||
// DescribeInputMode returns a string containing the names of each enabled input mode.
|
||||
func DescribeInputMode(mode uint32) string {
|
||||
return strings.Join(ListInputModeNames(mode), "|")
|
||||
}
|
154
vendor/github.com/erikgeiser/coninput/read.go
generated
vendored
Normal file
154
vendor/github.com/erikgeiser/coninput/read.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package coninput
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
procReadConsoleInputW = modkernel32.NewProc("ReadConsoleInputW")
|
||||
procPeekConsoleInputW = modkernel32.NewProc("PeekConsoleInputW")
|
||||
procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents")
|
||||
procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
|
||||
)
|
||||
|
||||
// NewStdinHandle is a shortcut for windows.GetStdHandle(windows.STD_INPUT_HANDLE).
|
||||
func NewStdinHandle() (windows.Handle, error) {
|
||||
return windows.GetStdHandle(windows.STD_INPUT_HANDLE)
|
||||
}
|
||||
|
||||
// WinReadConsoleInput is a thin wrapper around the Windows console API function
|
||||
// ReadConsoleInput (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). In most
|
||||
// cases it is more practical to either use ReadConsoleInput or
|
||||
// ReadNConsoleInputs.
|
||||
func WinReadConsoleInput(consoleInput windows.Handle, buffer *InputRecord,
|
||||
length uint32, numberOfEventsRead *uint32) error {
|
||||
r, _, e := syscall.Syscall6(procReadConsoleInputW.Addr(), 4,
|
||||
uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length),
|
||||
uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0)
|
||||
if r == 0 {
|
||||
return error(e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadNConsoleInputs is a wrapper around ReadConsoleInput (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/readconsoleinput) that
|
||||
// automates the event buffer allocation in oder to provide io.Reader-like
|
||||
// sematics. maxEvents must be greater than zero.
|
||||
func ReadNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) {
|
||||
if maxEvents == 0 {
|
||||
return nil, fmt.Errorf("maxEvents cannot be zero")
|
||||
}
|
||||
|
||||
var inputRecords = make([]InputRecord, maxEvents)
|
||||
n, err := ReadConsoleInput(console, inputRecords)
|
||||
|
||||
return inputRecords[:n], err
|
||||
}
|
||||
|
||||
// ReadConsoleInput provides an ideomatic interface to the Windows console API
|
||||
// function ReadConsoleInput (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). The size
|
||||
// of inputRecords must be greater than zero.
|
||||
func ReadConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) {
|
||||
if len(inputRecords) == 0 {
|
||||
return 0, fmt.Errorf("size of input record buffer cannot be zero")
|
||||
}
|
||||
|
||||
var read uint32
|
||||
err := WinReadConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read)
|
||||
|
||||
return read, err
|
||||
}
|
||||
|
||||
// WinPeekConsoleInput is a thin wrapper around the Windows console API function
|
||||
// PeekConsoleInput (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). In most
|
||||
// cases it is more practical to either use PeekConsoleInput or
|
||||
// PeekNConsoleInputs.
|
||||
func WinPeekConsoleInput(consoleInput windows.Handle, buffer *InputRecord,
|
||||
length uint32, numberOfEventsRead *uint32) error {
|
||||
r, _, e := syscall.Syscall6(procPeekConsoleInputW.Addr(), 4,
|
||||
uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length),
|
||||
uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0)
|
||||
if r == 0 {
|
||||
return error(e)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// PeekNConsoleInputs is a wrapper around PeekConsoleInput (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput) that
|
||||
// automates the event buffer allocation in oder to provide io.Reader-like
|
||||
// sematics. maxEvents must be greater than zero.
|
||||
func PeekNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) {
|
||||
if maxEvents == 0 {
|
||||
return nil, fmt.Errorf("maxEvents cannot be zero")
|
||||
}
|
||||
|
||||
var inputRecords = make([]InputRecord, maxEvents)
|
||||
n, err := PeekConsoleInput(console, inputRecords)
|
||||
|
||||
return inputRecords[:n], err
|
||||
}
|
||||
|
||||
// PeekConsoleInput provides an ideomatic interface to the Windows console API
|
||||
// function PeekConsoleInput (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). The size
|
||||
// of inputRecords must be greater than zero.
|
||||
func PeekConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) {
|
||||
if len(inputRecords) == 0 {
|
||||
return 0, fmt.Errorf("size of input record buffer cannot be zero")
|
||||
}
|
||||
|
||||
var read uint32
|
||||
|
||||
err := WinPeekConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read)
|
||||
|
||||
return read, err
|
||||
}
|
||||
|
||||
// WinGetNumberOfConsoleInputEvents provides an ideomatic interface to the
|
||||
// Windows console API function GetNumberOfConsoleInputEvents (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents).
|
||||
func WinGetNumberOfConsoleInputEvents(consoleInput windows.Handle, numberOfEvents *uint32) error {
|
||||
r, _, e := syscall.Syscall6(procGetNumberOfConsoleInputEvents.Addr(), 2,
|
||||
uintptr(consoleInput), uintptr(unsafe.Pointer(numberOfEvents)), 0,
|
||||
0, 0, 0)
|
||||
if r == 0 {
|
||||
return error(e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNumberOfConsoleInputEvents provides an ideomatic interface to the Windows
|
||||
// console API function GetNumberOfConsoleInputEvents (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents).
|
||||
func GetNumberOfConsoleInputEvents(console windows.Handle) (uint32, error) {
|
||||
var nEvents uint32
|
||||
err := WinGetNumberOfConsoleInputEvents(console, &nEvents)
|
||||
|
||||
return nEvents, err
|
||||
}
|
||||
|
||||
func FlushConsoleInputBuffer(consoleInput windows.Handle) error {
|
||||
r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1, uintptr(consoleInput), 0, 0)
|
||||
if r == 0 {
|
||||
return error(e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
486
vendor/github.com/erikgeiser/coninput/records.go
generated
vendored
Normal file
486
vendor/github.com/erikgeiser/coninput/records.go
generated
vendored
Normal file
@ -0,0 +1,486 @@
|
||||
package coninput
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
maxEventSize = 16
|
||||
wordPaddingBytes = 2
|
||||
)
|
||||
|
||||
// EventType denots the type of an event
|
||||
type EventType uint16
|
||||
|
||||
// EventUnion is the union data type that contains the data for any event.
|
||||
type EventUnion [maxEventSize]byte
|
||||
|
||||
// InputRecord corresponds to the INPUT_RECORD structure from the Windows
|
||||
// console API (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
type InputRecord struct {
|
||||
// EventType specifies the type of event that helt in Event.
|
||||
EventType EventType
|
||||
|
||||
// Padding of the 16-bit EventType to a whole 32-bit dword.
|
||||
_ [wordPaddingBytes]byte
|
||||
|
||||
// Event holds the actual event data. Use Unrap to access it as its
|
||||
// respective event type.
|
||||
Event EventUnion
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer for InputRecord.
|
||||
func (ir InputRecord) String() string {
|
||||
return ir.Unwrap().String()
|
||||
}
|
||||
|
||||
// Unwrap parses the event data into an EventRecord of the respective event
|
||||
// type. The data in the returned EventRecord does not contain any references to
|
||||
// the passed InputRecord.
|
||||
func (ir InputRecord) Unwrap() EventRecord {
|
||||
switch ir.EventType {
|
||||
case FocusEventType:
|
||||
return FocusEventRecord{SetFocus: ir.Event[0] > 0}
|
||||
case KeyEventType:
|
||||
return KeyEventRecord{
|
||||
KeyDown: binary.LittleEndian.Uint32(ir.Event[0:4]) > 0,
|
||||
RepeatCount: binary.LittleEndian.Uint16(ir.Event[4:6]),
|
||||
VirtualKeyCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[6:8])),
|
||||
VirtualScanCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[8:10])),
|
||||
Char: rune(binary.LittleEndian.Uint16(ir.Event[10:12])),
|
||||
ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[12:16])),
|
||||
}
|
||||
case MouseEventType:
|
||||
m := MouseEventRecord{
|
||||
MousePositon: Coord{
|
||||
X: binary.LittleEndian.Uint16(ir.Event[0:2]),
|
||||
Y: binary.LittleEndian.Uint16(ir.Event[2:4]),
|
||||
},
|
||||
ButtonState: ButtonState(binary.LittleEndian.Uint32(ir.Event[4:8])),
|
||||
ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[8:12])),
|
||||
EventFlags: EventFlags(binary.LittleEndian.Uint32(ir.Event[12:16])),
|
||||
}
|
||||
|
||||
if (m.EventFlags&MOUSE_WHEELED > 0) || (m.EventFlags&MOUSE_HWHEELED > 0) {
|
||||
if int16(highWord(uint32(m.ButtonState))) > 0 {
|
||||
m.WheelDirection = 1
|
||||
} else {
|
||||
m.WheelDirection = -1
|
||||
}
|
||||
}
|
||||
|
||||
return m
|
||||
case WindowBufferSizeEventType:
|
||||
return WindowBufferSizeEventRecord{
|
||||
Size: Coord{
|
||||
X: binary.LittleEndian.Uint16(ir.Event[0:2]),
|
||||
Y: binary.LittleEndian.Uint16(ir.Event[2:4]),
|
||||
},
|
||||
}
|
||||
case MenuEventType:
|
||||
return MenuEventRecord{
|
||||
CommandID: binary.LittleEndian.Uint32(ir.Event[0:4]),
|
||||
}
|
||||
default:
|
||||
return &UnknownEvent{InputRecord: ir}
|
||||
}
|
||||
}
|
||||
|
||||
// EventRecord represents one of the following event types:
|
||||
// TypeFocusEventRecord, TypeKeyEventRecord, TypeMouseEventRecord,
|
||||
// TypeWindowBufferSizeEvent, TypeMenuEventRecord and UnknownEvent.
|
||||
type EventRecord interface {
|
||||
Type() string
|
||||
fmt.Stringer
|
||||
}
|
||||
|
||||
// FocusEventType is the event type for a FocusEventRecord (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
const FocusEventType EventType = 0x0010
|
||||
|
||||
// FocusEventRecord represent the FOCUS_EVENT_RECORD structure from the Windows
|
||||
// console API (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/focus-event-record-str).
|
||||
// These events are used internally by the Windows console API and should be
|
||||
// ignored.
|
||||
type FocusEventRecord struct {
|
||||
// SetFocus is reserved and should not be used.
|
||||
SetFocus bool
|
||||
}
|
||||
|
||||
// Ensure that FocusEventRecord satisfies EventRecord interface.
|
||||
var _ EventRecord = FocusEventRecord{}
|
||||
|
||||
// Type ensures that FocusEventRecord satisfies EventRecord interface.
|
||||
func (e FocusEventRecord) Type() string { return "FocusEvent" }
|
||||
|
||||
// String ensures that FocusEventRecord satisfies EventRecord and fmt.Stringer
|
||||
// interfaces.
|
||||
func (e FocusEventRecord) String() string { return fmt.Sprintf("%s[%v]", e.Type(), e.SetFocus) }
|
||||
|
||||
// KeyEventType is the event type for a KeyEventRecord (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
const KeyEventType EventType = 0x0001
|
||||
|
||||
// KeyEventRecord represent the KEY_EVENT_RECORD structure from the Windows
|
||||
// console API (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/key-event-record-str).
|
||||
type KeyEventRecord struct {
|
||||
// KeyDown specified whether the key is pressed or released.
|
||||
KeyDown bool
|
||||
|
||||
// RepeatCount indicates that a key is being held down. For example, when a
|
||||
// key is held down, five events with RepeatCount equal to 1 may be
|
||||
// generated, one event with RepeatCount equal to 5, or multiple events
|
||||
// with RepeatCount greater than or equal to 1.
|
||||
RepeatCount uint16
|
||||
|
||||
// VirtualKeyCode identifies the given key in a device-independent manner
|
||||
// (see
|
||||
// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes).
|
||||
VirtualKeyCode VirtualKeyCode
|
||||
|
||||
// VirtualScanCode represents the device-dependent value generated by the
|
||||
// keyboard hardware.
|
||||
VirtualScanCode VirtualKeyCode
|
||||
|
||||
// Char is the character that corresponds to the pressed key. Char can be
|
||||
// zero for some keys.
|
||||
Char rune
|
||||
|
||||
//ControlKeyState holds the state of the control keys.
|
||||
ControlKeyState ControlKeyState
|
||||
}
|
||||
|
||||
// Ensure that KeyEventRecord satisfies EventRecord interface.
|
||||
var _ EventRecord = KeyEventRecord{}
|
||||
|
||||
// Type ensures that KeyEventRecord satisfies EventRecord interface.
|
||||
func (e KeyEventRecord) Type() string { return "KeyEvent" }
|
||||
|
||||
// String ensures that KeyEventRecord satisfies EventRecord and fmt.Stringer
|
||||
// interfaces.
|
||||
func (e KeyEventRecord) String() string {
|
||||
infos := []string{}
|
||||
|
||||
repeat := ""
|
||||
if e.RepeatCount > 1 {
|
||||
repeat = "x" + strconv.Itoa(int(e.RepeatCount))
|
||||
}
|
||||
|
||||
infos = append(infos, fmt.Sprintf("%q%s", e.Char, repeat))
|
||||
|
||||
direction := "up"
|
||||
if e.KeyDown {
|
||||
direction = "down"
|
||||
}
|
||||
|
||||
infos = append(infos, direction)
|
||||
|
||||
if e.ControlKeyState != NO_CONTROL_KEY {
|
||||
infos = append(infos, e.ControlKeyState.String())
|
||||
}
|
||||
|
||||
infos = append(infos, fmt.Sprintf("KeyCode: %d", e.VirtualKeyCode))
|
||||
infos = append(infos, fmt.Sprintf("ScanCode: %d", e.VirtualScanCode))
|
||||
|
||||
return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", "))
|
||||
}
|
||||
|
||||
// MenuEventType is the event type for a MenuEventRecord (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
const MenuEventType EventType = 0x0008
|
||||
|
||||
// MenuEventRecord represent the MENU_EVENT_RECORD structure from the Windows
|
||||
// console API (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/menu-event-record-str).
|
||||
// These events are deprecated by the Windows console API and should be ignored.
|
||||
type MenuEventRecord struct {
|
||||
CommandID uint32
|
||||
}
|
||||
|
||||
// Ensure that MenuEventRecord satisfies EventRecord interface.
|
||||
var _ EventRecord = MenuEventRecord{}
|
||||
|
||||
// Type ensures that MenuEventRecord satisfies EventRecord interface.
|
||||
func (e MenuEventRecord) Type() string { return "MenuEvent" }
|
||||
|
||||
// String ensures that MenuEventRecord satisfies EventRecord and fmt.Stringer
|
||||
// interfaces.
|
||||
func (e MenuEventRecord) String() string { return fmt.Sprintf("MenuEvent[%d]", e.CommandID) }
|
||||
|
||||
// MouseEventType is the event type for a MouseEventRecord (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
const MouseEventType EventType = 0x0002
|
||||
|
||||
// MouseEventRecord represent the MOUSE_EVENT_RECORD structure from the Windows
|
||||
// console API (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str).
|
||||
type MouseEventRecord struct {
|
||||
// MousePosition contains the location of the cursor, in terms of the
|
||||
// console screen buffer's character-cell coordinates.
|
||||
MousePositon Coord
|
||||
|
||||
// ButtonState holds the status of the mouse buttons.
|
||||
ButtonState ButtonState
|
||||
|
||||
// ControlKeyState holds the state of the control keys.
|
||||
ControlKeyState ControlKeyState
|
||||
|
||||
// EventFlags specify tge type of mouse event.
|
||||
EventFlags EventFlags
|
||||
|
||||
// WheelDirection specified the direction in which the mouse wheel is
|
||||
// spinning when EventFlags contains MOUSE_HWHEELED or MOUSE_WHEELED. When
|
||||
// the event flags specify MOUSE_WHEELED it is 1 if the wheel rotated
|
||||
// forward (away from the user) or -1 when it rotates backwards. When
|
||||
// MOUSE_HWHEELED is specified it is 1 when the wheel rotates right and -1
|
||||
// when it rotates left. When the EventFlags do not indicate a mouse wheel
|
||||
// event it is 0.
|
||||
WheelDirection int
|
||||
}
|
||||
|
||||
// Ensure that MouseEventRecord satisfies EventRecord interface.
|
||||
var _ EventRecord = MouseEventRecord{}
|
||||
|
||||
func (e MouseEventRecord) WheelDirectionName() string {
|
||||
if e.EventFlags&MOUSE_WHEELED > 0 {
|
||||
if e.WheelDirection > 0 {
|
||||
return "Forward"
|
||||
}
|
||||
|
||||
return "Backward"
|
||||
} else if e.EventFlags&MOUSE_HWHEELED > 0 {
|
||||
if e.WheelDirection > 0 {
|
||||
return "Right"
|
||||
}
|
||||
|
||||
return "Left"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Type ensures that MouseEventRecord satisfies EventRecord interface.
|
||||
func (e MouseEventRecord) Type() string { return "MouseEvent" }
|
||||
|
||||
// String ensures that MouseEventRecord satisfies EventRecord and fmt.Stringer
|
||||
// interfaces.
|
||||
func (e MouseEventRecord) String() string {
|
||||
infos := []string{e.MousePositon.String()}
|
||||
|
||||
if e.ButtonState&0xFF != 0 {
|
||||
infos = append(infos, e.ButtonState.String())
|
||||
}
|
||||
|
||||
eventDescription := e.EventFlags.String()
|
||||
|
||||
wheelDirection := e.WheelDirectionName()
|
||||
if wheelDirection != "" {
|
||||
eventDescription += "(" + wheelDirection + ")"
|
||||
}
|
||||
|
||||
infos = append(infos, eventDescription)
|
||||
|
||||
if e.ControlKeyState != NO_CONTROL_KEY {
|
||||
infos = append(infos, e.ControlKeyState.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", "))
|
||||
}
|
||||
|
||||
// WindowBufferSizeEventType is the event type for a WindowBufferSizeEventRecord
|
||||
// (see https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
const WindowBufferSizeEventType EventType = 0x0004
|
||||
|
||||
// WindowBufferSizeEventRecord represent the WINDOW_BUFFER_SIZE_RECORD structure
|
||||
// from the Windows console API (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str).
|
||||
type WindowBufferSizeEventRecord struct {
|
||||
// Size contains the size of the console screen buffer, in character cell columns and rows.
|
||||
Size Coord
|
||||
}
|
||||
|
||||
// Ensure that WindowBufferSizeEventRecord satisfies EventRecord interface.
|
||||
var _ EventRecord = WindowBufferSizeEventRecord{}
|
||||
|
||||
// Type ensures that WindowBufferSizeEventRecord satisfies EventRecord interface.
|
||||
func (e WindowBufferSizeEventRecord) Type() string { return "WindowBufferSizeEvent" }
|
||||
|
||||
// String ensures that WindowBufferSizeEventRecord satisfies EventRecord and fmt.Stringer
|
||||
// interfaces.
|
||||
func (e WindowBufferSizeEventRecord) String() string {
|
||||
return fmt.Sprintf("WindowBufferSizeEvent[%s]", e.Size)
|
||||
}
|
||||
|
||||
// UnknownEvent is generated when the event type does not match one of the
|
||||
// following types: TypeFocusEventRecord, TypeKeyEventRecord,
|
||||
// TypeMouseEventRecord, TypeWindowBufferSizeEvent, TypeMenuEventRecord and
|
||||
// UnknownEvent.
|
||||
type UnknownEvent struct {
|
||||
InputRecord
|
||||
}
|
||||
|
||||
// Ensure that UnknownEvent satisfies EventRecord interface.
|
||||
var _ EventRecord = UnknownEvent{}
|
||||
|
||||
// Type ensures that UnknownEvent satisfies EventRecord interface.
|
||||
func (e UnknownEvent) Type() string { return "UnknownEvent" }
|
||||
|
||||
// String ensures that UnknownEvent satisfies EventRecord and fmt.Stringer
|
||||
// interfaces.
|
||||
func (e UnknownEvent) String() string {
|
||||
return fmt.Sprintf("%s[Type: %d, Data: %v]", e.Type(), e.InputRecord.EventType, e.InputRecord.Event[:])
|
||||
}
|
||||
|
||||
// Coord represent the COORD structure from the Windows
|
||||
// console API (see https://docs.microsoft.com/en-us/windows/console/coord-str).
|
||||
type Coord struct {
|
||||
// X is the horizontal coordinate or column value. The units depend on the function call.
|
||||
X uint16
|
||||
// Y is the vertical coordinate or row value. The units depend on the function call.
|
||||
Y uint16
|
||||
}
|
||||
|
||||
// String ensures that Coord satisfies the fmt.Stringer interface.
|
||||
func (c Coord) String() string {
|
||||
return fmt.Sprintf("(%d, %d)", c.X, c.Y)
|
||||
}
|
||||
|
||||
// ButtonState holds the state of the mouse buttons (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str).
|
||||
type ButtonState uint32
|
||||
|
||||
func (bs ButtonState) Contains(state ButtonState) bool {
|
||||
return bs&state > 0
|
||||
}
|
||||
|
||||
// String ensures that ButtonState satisfies the fmt.Stringer interface.
|
||||
func (bs ButtonState) String() string {
|
||||
switch {
|
||||
case bs&FROM_LEFT_1ST_BUTTON_PRESSED > 0:
|
||||
return "Left"
|
||||
case bs&FROM_LEFT_2ND_BUTTON_PRESSED > 0:
|
||||
return "2"
|
||||
case bs&FROM_LEFT_3RD_BUTTON_PRESSED > 0:
|
||||
return "3"
|
||||
case bs&FROM_LEFT_4TH_BUTTON_PRESSED > 0:
|
||||
return "4"
|
||||
case bs&RIGHTMOST_BUTTON_PRESSED > 0:
|
||||
return "Right"
|
||||
case bs&0xFF == 0:
|
||||
return "No Button"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown(%d)", bs)
|
||||
}
|
||||
}
|
||||
|
||||
func (bs ButtonState) IsReleased() bool {
|
||||
return bs&0xff > 0
|
||||
}
|
||||
|
||||
// Valid values for ButtonState.
|
||||
const (
|
||||
FROM_LEFT_1ST_BUTTON_PRESSED ButtonState = 0x0001
|
||||
RIGHTMOST_BUTTON_PRESSED ButtonState = 0x0002
|
||||
FROM_LEFT_2ND_BUTTON_PRESSED ButtonState = 0x0004
|
||||
FROM_LEFT_3RD_BUTTON_PRESSED ButtonState = 0x0008
|
||||
FROM_LEFT_4TH_BUTTON_PRESSED ButtonState = 0x0010
|
||||
)
|
||||
|
||||
// ControlKeyState holds the state of the control keys for key and mouse events
|
||||
// (see https://docs.microsoft.com/en-us/windows/console/key-event-record-str
|
||||
// and https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str).
|
||||
type ControlKeyState uint32
|
||||
|
||||
func (cks ControlKeyState) Contains(state ControlKeyState) bool {
|
||||
return cks&state > 0
|
||||
}
|
||||
|
||||
// Valid values for ControlKeyState.
|
||||
const (
|
||||
CAPSLOCK_ON ControlKeyState = 0x0080
|
||||
ENHANCED_KEY ControlKeyState = 0x0100
|
||||
LEFT_ALT_PRESSED ControlKeyState = 0x0002
|
||||
LEFT_CTRL_PRESSED ControlKeyState = 0x0008
|
||||
NUMLOCK_ON ControlKeyState = 0x0020
|
||||
RIGHT_ALT_PRESSED ControlKeyState = 0x0001
|
||||
RIGHT_CTRL_PRESSED ControlKeyState = 0x0004
|
||||
SCROLLLOCK_ON ControlKeyState = 0x0040
|
||||
SHIFT_PRESSED ControlKeyState = 0x0010
|
||||
NO_CONTROL_KEY ControlKeyState = 0x0000
|
||||
)
|
||||
|
||||
// String ensures that ControlKeyState satisfies the fmt.Stringer interface.
|
||||
func (cks ControlKeyState) String() string {
|
||||
controlKeys := []string{}
|
||||
|
||||
switch {
|
||||
case cks&CAPSLOCK_ON > 0:
|
||||
controlKeys = append(controlKeys, "CapsLock")
|
||||
case cks&ENHANCED_KEY > 0:
|
||||
controlKeys = append(controlKeys, "Enhanced")
|
||||
case cks&LEFT_ALT_PRESSED > 0:
|
||||
controlKeys = append(controlKeys, "Alt")
|
||||
case cks&LEFT_CTRL_PRESSED > 0:
|
||||
controlKeys = append(controlKeys, "CTRL")
|
||||
case cks&NUMLOCK_ON > 0:
|
||||
controlKeys = append(controlKeys, "NumLock")
|
||||
case cks&RIGHT_ALT_PRESSED > 0:
|
||||
controlKeys = append(controlKeys, "RightAlt")
|
||||
case cks&RIGHT_CTRL_PRESSED > 0:
|
||||
controlKeys = append(controlKeys, "RightCTRL")
|
||||
case cks&SCROLLLOCK_ON > 0:
|
||||
controlKeys = append(controlKeys, "ScrollLock")
|
||||
case cks&SHIFT_PRESSED > 0:
|
||||
controlKeys = append(controlKeys, "Shift")
|
||||
case cks == NO_CONTROL_KEY:
|
||||
default:
|
||||
return fmt.Sprintf("Unknown(%d)", cks)
|
||||
}
|
||||
|
||||
return strings.Join(controlKeys, ",")
|
||||
}
|
||||
|
||||
// EventFlags specifies the type of a mouse event (see
|
||||
// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str).
|
||||
type EventFlags uint32
|
||||
|
||||
// String ensures that EventFlags satisfies the fmt.Stringer interface.
|
||||
func (ef EventFlags) String() string {
|
||||
switch {
|
||||
case ef&DOUBLE_CLICK > 0:
|
||||
return "DoubleClick"
|
||||
case ef&MOUSE_WHEELED > 0:
|
||||
return "Wheeled"
|
||||
case ef&MOUSE_MOVED > 0:
|
||||
return "Moved"
|
||||
case ef&MOUSE_HWHEELED > 0:
|
||||
return "HWheeld"
|
||||
case ef == CLICK:
|
||||
return "Click"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown(%d)", ef)
|
||||
}
|
||||
}
|
||||
|
||||
func (ef EventFlags) Contains(flag EventFlags) bool {
|
||||
return ef&flag > 0
|
||||
}
|
||||
|
||||
// Valid values for EventFlags.
|
||||
const (
|
||||
CLICK EventFlags = 0x0000
|
||||
MOUSE_MOVED EventFlags = 0x0001
|
||||
DOUBLE_CLICK EventFlags = 0x0002
|
||||
MOUSE_WHEELED EventFlags = 0x0004
|
||||
MOUSE_HWHEELED EventFlags = 0x0008
|
||||
)
|
||||
|
||||
func highWord(data uint32) uint16 {
|
||||
return uint16((data & 0xFFFF0000) >> 16)
|
||||
}
|
Reference in New Issue
Block a user