diff --git a/client/src/components/video.vue b/client/src/components/video.vue index cec547c4..b6350646 100644 --- a/client/src/components/video.vue +++ b/client/src/components/video.vue @@ -498,16 +498,33 @@ if (!this.hosting || this.locked) { return } + this.onMousePos(e) } onMouseEnter(e: MouseEvent) { + if(this.hosting) { + this.$accessor.remote.syncKeyboardModifierState({ + capsLock: e.getModifierState("CapsLock"), + numLock: e.getModifierState("NumLock"), + scrollLock: e.getModifierState("ScrollLock"), + }) + } + this._overlay.focus() this.onFocus() this.focused = true } onMouseLeave(e: MouseEvent) { + if(this.hosting) { + this.$accessor.remote.setKeyboardModifierState({ + capsLock: e.getModifierState("CapsLock"), + numLock: e.getModifierState("NumLock"), + scrollLock: e.getModifierState("ScrollLock"), + }) + } + this.focused = false } diff --git a/client/src/neko/events.ts b/client/src/neko/events.ts index 725e675e..92987513 100644 --- a/client/src/neko/events.ts +++ b/client/src/neko/events.ts @@ -27,7 +27,7 @@ export const EVENT = { REQUESTING: 'control/requesting', CLIPBOARD: 'control/clipboard', GIVE: 'control/give', - KEYBOARD: 'control/keyboard' + KEYBOARD: 'control/keyboard', }, CHAT: { MESSAGE: 'chat/message', diff --git a/client/src/neko/messages.ts b/client/src/neko/messages.ts index 5192b549..27c737bd 100644 --- a/client/src/neko/messages.ts +++ b/client/src/neko/messages.ts @@ -122,7 +122,10 @@ export interface ControlClipboardPayload { } export interface ControlKeyboardPayload { - layout: string + layout?: string + capsLock?: boolean + numLock?: boolean + scrollLock?: boolean } /* diff --git a/client/src/store/remote.ts b/client/src/store/remote.ts index 991ccc63..f7e63ab9 100644 --- a/client/src/store/remote.ts +++ b/client/src/store/remote.ts @@ -3,12 +3,18 @@ import { Member } from '~/neko/types' import { EVENT } from '~/neko/events' import { accessor } from '~/store' +const keyboardModifierState = + (capsLock: boolean, numLock: boolean, scrollLock: boolean) => + Number(capsLock) + 2*Number(numLock) + 4*Number(scrollLock) + export const namespaced = true export const state = () => ({ id: '', clipboard: '', locked: false, + + keyboardModifierState: -1, }) export const getters = getterTree(state, { @@ -36,6 +42,10 @@ export const mutations = mutationTree(state, { state.clipboard = clipboard }, + setKeyboardModifierState(state, { capsLock, numLock, scrollLock }) { + state.keyboardModifierState = keyboardModifierState(capsLock, numLock, scrollLock) + }, + setLocked(state, locked: boolean) { state.locked = locked }, @@ -44,6 +54,7 @@ export const mutations = mutationTree(state, { state.id = '' state.clipboard = '' state.locked = false + state.keyboardModifierState = -1 }, }) @@ -140,6 +151,15 @@ export const actions = actionTree( } $client.sendMessage(EVENT.CONTROL.KEYBOARD, { layout: accessor.settings.keyboard_layout }) + }, + + syncKeyboardModifierState({ state, getters }, { capsLock, numLock, scrollLock }) { + if (state.keyboardModifierState === keyboardModifierState(capsLock, numLock, scrollLock)) { + return ; + } + + accessor.remote.setKeyboardModifierState({ capsLock, numLock, scrollLock }) + $client.sendMessage(EVENT.CONTROL.KEYBOARD, { capsLock, numLock, scrollLock }) } }, ) diff --git a/server/internal/types/message/messages.go b/server/internal/types/message/messages.go index 9d994810..8113e332 100644 --- a/server/internal/types/message/messages.go +++ b/server/internal/types/message/messages.go @@ -47,8 +47,11 @@ type Clipboard struct { } type Keyboard struct { - Event string `json:"event"` - Layout string `json:"layout"` + Event string `json:"event"` + Layout *string `json:"layout,omitempty"` + CapsLock *bool `json:"capsLock,omitempty"` + NumLock *bool `json:"numLock,omitempty"` + ScrollLock *bool `json:"scrollLock,omitempty"` } type Control struct { diff --git a/server/internal/websocket/control.go b/server/internal/websocket/control.go index 234c5d06..447f4cf1 100644 --- a/server/internal/websocket/control.go +++ b/server/internal/websocket/control.go @@ -116,6 +116,11 @@ func (h *MessageHandler) controlClipboard(id string, session types.Session, payl return nil } +// TODO: Refactor +var CapsLock = false +var NumLock = false +var ScrollLock = false + func (h *MessageHandler) controlKeyboard(id string, session types.Session, payload *message.Keyboard) error { // check if session is host if !h.sessions.IsHost(id) { @@ -123,6 +128,34 @@ func (h *MessageHandler) controlKeyboard(id string, session types.Session, paylo return nil } - h.remote.SetKeyboard(payload.Layout) + // change layout + if payload.Layout != nil { + h.remote.SetKeyboard(*payload.Layout) + } + + // set caps lock + if payload.CapsLock != nil && *payload.CapsLock != CapsLock { + h.remote.KeyDown(0xffe5) + h.remote.KeyUp(0xffe5) + + CapsLock = *payload.CapsLock + } + + // set num lock + if payload.NumLock != nil && *payload.NumLock != NumLock { + h.remote.KeyDown(0xff7f) + h.remote.KeyUp(0xff7f) + + NumLock = *payload.NumLock + } + + // set scroll lock + if payload.ScrollLock != nil && *payload.ScrollLock != ScrollLock { + h.remote.KeyDown(0xff14) + h.remote.KeyUp(0xff14) + + ScrollLock = *payload.ScrollLock + } + return nil }