mirror of https://github.com/jetkvm/kvm.git
refactor: enhance keyboard auto-release functionality and key state management
This commit is contained in:
parent
e3eb8330fe
commit
60263359b9
|
@ -158,25 +158,27 @@ func (u *UsbGadget) SetOnKeysDownChange(f func(state KeysDownState)) {
|
||||||
u.onKeysDownChange = &f
|
u.onKeysDownChange = &f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) scheduleAutoRelease() {
|
func (u *UsbGadget) scheduleAutoRelease(key byte) {
|
||||||
u.kbdAutoReleaseLock.Lock()
|
u.kbdAutoReleaseLock.Lock()
|
||||||
defer unlockWithLog(&u.kbdAutoReleaseLock, u.log, "autoRelease scheduled")
|
defer unlockWithLog(&u.kbdAutoReleaseLock, u.log, "autoRelease scheduled")
|
||||||
|
|
||||||
if u.kbdAutoReleaseTimer != nil {
|
if u.kbdAutoReleaseTimers[key] != nil {
|
||||||
u.kbdAutoReleaseTimer.Stop()
|
u.kbdAutoReleaseTimers[key].Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
u.kbdAutoReleaseTimer = time.AfterFunc(autoReleaseKeyboardInterval, func() {
|
u.kbdAutoReleaseTimers[key] = time.AfterFunc(autoReleaseKeyboardInterval, func() {
|
||||||
u.performAutoRelease()
|
u.performAutoRelease(key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) cancelAutoRelease() {
|
func (u *UsbGadget) cancelAutoRelease(key byte) {
|
||||||
u.kbdAutoReleaseLock.Lock()
|
u.kbdAutoReleaseLock.Lock()
|
||||||
defer unlockWithLog(&u.kbdAutoReleaseLock, u.log, "autoRelease cancelled")
|
defer unlockWithLog(&u.kbdAutoReleaseLock, u.log, "autoRelease cancelled")
|
||||||
|
|
||||||
if u.kbdAutoReleaseTimer != nil {
|
if timer := u.kbdAutoReleaseTimers[key]; timer != nil {
|
||||||
u.kbdAutoReleaseTimer.Stop()
|
timer.Stop()
|
||||||
|
u.kbdAutoReleaseTimers[key] = nil
|
||||||
|
delete(u.kbdAutoReleaseTimers, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,27 +186,35 @@ func (u *UsbGadget) DelayAutoRelease() {
|
||||||
u.kbdAutoReleaseLock.Lock()
|
u.kbdAutoReleaseLock.Lock()
|
||||||
defer unlockWithLog(&u.kbdAutoReleaseLock, u.log, "autoRelease delayed")
|
defer unlockWithLog(&u.kbdAutoReleaseLock, u.log, "autoRelease delayed")
|
||||||
|
|
||||||
if u.kbdAutoReleaseTimer == nil {
|
if u.kbdAutoReleaseTimers == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
u.kbdAutoReleaseTimer.Reset(autoReleaseKeyboardInterval)
|
for _, timer := range u.kbdAutoReleaseTimers {
|
||||||
|
if timer != nil {
|
||||||
|
timer.Reset(autoReleaseKeyboardInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) performAutoRelease() {
|
func (u *UsbGadget) performAutoRelease(key byte) {
|
||||||
select {
|
|
||||||
case <-u.keyboardStateCtx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
u.kbdAutoReleaseLock.Lock()
|
u.kbdAutoReleaseLock.Lock()
|
||||||
|
|
||||||
key := u.kbdAutoReleaseLastKey
|
if u.kbdAutoReleaseTimers[key] == nil {
|
||||||
|
u.log.Warn().Uint8("key", key).Msg("autoRelease timer not found")
|
||||||
|
u.kbdAutoReleaseLock.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
u.kbdAutoReleaseTimers[key].Stop()
|
||||||
|
u.kbdAutoReleaseTimers[key] = nil
|
||||||
|
delete(u.kbdAutoReleaseTimers, key)
|
||||||
|
u.kbdAutoReleaseLock.Unlock()
|
||||||
|
|
||||||
// Skip if already released
|
// Skip if already released
|
||||||
state := u.GetKeysDownState()
|
state := u.GetKeysDownState()
|
||||||
alreadyReleased := true
|
alreadyReleased := true
|
||||||
|
|
||||||
for i := range state.Keys {
|
for i := range state.Keys {
|
||||||
if state.Keys[i] == key {
|
if state.Keys[i] == key {
|
||||||
alreadyReleased = false
|
alreadyReleased = false
|
||||||
|
@ -216,10 +226,7 @@ func (u *UsbGadget) performAutoRelease() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
u.kbdAutoReleaseTimer = nil
|
u.keypressReport(key, false)
|
||||||
u.kbdAutoReleaseLock.Unlock()
|
|
||||||
|
|
||||||
u.keypressReport(key, false) // autoRelease the ket
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) listenKeyboardEvents() {
|
func (u *UsbGadget) listenKeyboardEvents() {
|
||||||
|
@ -311,7 +318,7 @@ func (u *UsbGadget) keyboardWriteHidFile(modifier byte, keys []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) UpdateKeysDown(modifier byte, keys []byte) {
|
func (u *UsbGadget) UpdateKeysDown(modifier byte, keys []byte) KeysDownState {
|
||||||
// if we just reported an error roll over, we should clear the keys
|
// if we just reported an error roll over, we should clear the keys
|
||||||
if keys[0] == hidErrorRollOver {
|
if keys[0] == hidErrorRollOver {
|
||||||
for i := range keys {
|
for i := range keys {
|
||||||
|
@ -329,7 +336,7 @@ func (u *UsbGadget) UpdateKeysDown(modifier byte, keys []byte) {
|
||||||
if u.keysDownState.Modifier == state.Modifier &&
|
if u.keysDownState.Modifier == state.Modifier &&
|
||||||
bytes.Equal(u.keysDownState.Keys, state.Keys) {
|
bytes.Equal(u.keysDownState.Keys, state.Keys) {
|
||||||
u.keyboardStateLock.Unlock()
|
u.keyboardStateLock.Unlock()
|
||||||
return // No change in key down state
|
return state // No change in key down state
|
||||||
}
|
}
|
||||||
|
|
||||||
u.keysDownState = state
|
u.keysDownState = state
|
||||||
|
@ -338,7 +345,7 @@ func (u *UsbGadget) UpdateKeysDown(modifier byte, keys []byte) {
|
||||||
if u.onKeysDownChange != nil {
|
if u.onKeysDownChange != nil {
|
||||||
(*u.onKeysDownChange)(state) // this enques to the outgoing hidrpc queue via usb.go → currentSession.enqueueKeysDownState(...)
|
(*u.onKeysDownChange)(state) // this enques to the outgoing hidrpc queue via usb.go → currentSession.enqueueKeysDownState(...)
|
||||||
}
|
}
|
||||||
return
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) KeyboardReport(modifier byte, keys []byte) error {
|
func (u *UsbGadget) KeyboardReport(modifier byte, keys []byte) error {
|
||||||
|
@ -397,7 +404,7 @@ var KeyCodeToMaskMap = map[byte]byte{
|
||||||
RightSuper: ModifierMaskRightSuper,
|
RightSuper: ModifierMaskRightSuper,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) keypressReport(key byte, press bool) error {
|
func (u *UsbGadget) keypressReport(key byte, press bool) (KeysDownState, error) {
|
||||||
defer u.resetUserInputTime()
|
defer u.resetUserInputTime()
|
||||||
|
|
||||||
l := u.log.With().Uint8("key", key).Bool("press", press).Logger()
|
l := u.log.With().Uint8("key", key).Bool("press", press).Logger()
|
||||||
|
@ -466,21 +473,20 @@ func (u *UsbGadget) keypressReport(key byte, press bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
err := u.keyboardWriteHidFile(modifier, keys)
|
err := u.keyboardWriteHidFile(modifier, keys)
|
||||||
u.UpdateKeysDown(modifier, keys)
|
return u.UpdateKeysDown(modifier, keys), err
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) KeypressReport(key byte, press bool) error {
|
func (u *UsbGadget) KeypressReport(key byte, press bool) error {
|
||||||
u.kbdAutoReleaseLock.Lock()
|
state, err := u.keypressReport(key, press)
|
||||||
u.kbdAutoReleaseLastKey = key
|
isRolledOver := state.Keys[0] == hidErrorRollOver
|
||||||
u.kbdAutoReleaseLock.Unlock()
|
|
||||||
|
|
||||||
if press {
|
if isRolledOver {
|
||||||
u.scheduleAutoRelease()
|
u.cancelAutoRelease(key)
|
||||||
|
} else if press {
|
||||||
|
u.scheduleAutoRelease(key)
|
||||||
} else {
|
} else {
|
||||||
u.cancelAutoRelease()
|
u.cancelAutoRelease(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := u.keypressReport(key, press)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,7 @@ type UsbGadget struct {
|
||||||
keysDownState KeysDownState // keyboard dynamic state (modifier keys and pressed keys)
|
keysDownState KeysDownState // keyboard dynamic state (modifier keys and pressed keys)
|
||||||
|
|
||||||
kbdAutoReleaseLock sync.Mutex
|
kbdAutoReleaseLock sync.Mutex
|
||||||
kbdAutoReleaseTimer *time.Timer
|
kbdAutoReleaseTimers map[byte]*time.Timer
|
||||||
kbdAutoReleaseLastKey byte
|
|
||||||
|
|
||||||
keyboardStateLock sync.Mutex
|
keyboardStateLock sync.Mutex
|
||||||
keyboardStateCtx context.Context
|
keyboardStateCtx context.Context
|
||||||
|
@ -136,6 +135,7 @@ func newUsbGadget(name string, configMap map[string]gadgetConfigItem, enabledDev
|
||||||
keyboardStateCancel: keyboardCancel,
|
keyboardStateCancel: keyboardCancel,
|
||||||
keyboardState: 0,
|
keyboardState: 0,
|
||||||
keysDownState: KeysDownState{Modifier: 0, Keys: []byte{0, 0, 0, 0, 0, 0}}, // must be initialized to hidKeyBufferSize (6) zero bytes
|
keysDownState: KeysDownState{Modifier: 0, Keys: []byte{0, 0, 0, 0, 0, 0}}, // must be initialized to hidKeyBufferSize (6) zero bytes
|
||||||
|
kbdAutoReleaseTimers: make(map[byte]*time.Timer),
|
||||||
enabledDevices: *enabledDevices,
|
enabledDevices: *enabledDevices,
|
||||||
lastUserInput: time.Now(),
|
lastUserInput: time.Now(),
|
||||||
log: logger,
|
log: logger,
|
||||||
|
@ -163,10 +163,10 @@ func (u *UsbGadget) Close() error {
|
||||||
|
|
||||||
// Stop auto-release timer
|
// Stop auto-release timer
|
||||||
u.kbdAutoReleaseLock.Lock()
|
u.kbdAutoReleaseLock.Lock()
|
||||||
if u.kbdAutoReleaseTimer != nil {
|
for _, timer := range u.kbdAutoReleaseTimers {
|
||||||
u.kbdAutoReleaseTimer.Stop()
|
timer.Stop()
|
||||||
u.kbdAutoReleaseTimer = nil
|
|
||||||
}
|
}
|
||||||
|
u.kbdAutoReleaseTimers = make(map[byte]*time.Timer)
|
||||||
u.kbdAutoReleaseLock.Unlock()
|
u.kbdAutoReleaseLock.Unlock()
|
||||||
|
|
||||||
// Close HID files
|
// Close HID files
|
||||||
|
|
Loading…
Reference in New Issue