use textarea for pasting.

This commit is contained in:
Miroslav Šedivý 2022-04-28 22:48:04 +02:00
parent 4b22e55223
commit e65c10005e
2 changed files with 51 additions and 24 deletions

View File

@ -1,22 +1,25 @@
<template> <template>
<canvas <div>
ref="overlay" <canvas ref="overlay" class="neko-overlay" tabindex="0" />
class="neko-overlay" <textarea
tabindex="0" ref="textarea"
:style="{ cursor }" class="neko-overlay"
@click.stop.prevent="$emit('onAction', { action: 'click', target: $event })" :style="{ cursor }"
@contextmenu.stop.prevent="$emit('onAction', { action: 'contextmenu', target: $event })" @click.stop.prevent="$emit('onAction', { action: 'click', target: $event })"
@wheel.stop.prevent="onWheel" @contextmenu.stop.prevent="$emit('onAction', { action: 'contextmenu', target: $event })"
@mousemove.stop.prevent="onMouseMove" @input.stop.prevent="onInput"
@mousedown.stop.prevent="onMouseDown" @wheel.stop.prevent="onWheel"
@mouseup.stop.prevent="onMouseUp" @mousemove.stop.prevent="onMouseMove"
@mouseenter.stop.prevent="onMouseEnter" @mousedown.stop.prevent="onMouseDown"
@mouseleave.stop.prevent="onMouseLeave" @mouseup.stop.prevent="onMouseUp"
@dragenter.stop.prevent="onDragEnter" @mouseenter.stop.prevent="onMouseEnter"
@dragleave.stop.prevent="onDragLeave" @mouseleave.stop.prevent="onMouseLeave"
@dragover.stop.prevent="onDragOver" @dragenter.stop.prevent="onDragEnter"
@drop.stop.prevent="onDrop" @dragleave.stop.prevent="onDragLeave"
/> @dragover.stop.prevent="onDragOver"
@drop.stop.prevent="onDrop"
/>
</div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -26,7 +29,11 @@
bottom: 0; bottom: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
font-size: 0;
outline: 0; outline: 0;
border: 0;
color: transparent;
background: transparent;
} }
</style> </style>
@ -34,7 +41,7 @@
import { Vue, Component, Ref, Prop, Watch } from 'vue-property-decorator' import { Vue, Component, Ref, Prop, Watch } from 'vue-property-decorator'
import GuacamoleKeyboard from './utils/guacamole-keyboard' import GuacamoleKeyboard from './utils/guacamole-keyboard'
import { keySymsRemap } from './utils/keyboard-remapping' import { KeyTable, keySymsRemap } from './utils/keyboard-remapping'
import { getFilesFromDataTansfer } from './utils/file-upload' import { getFilesFromDataTansfer } from './utils/file-upload'
import { NekoWebRTC } from './internal/webrtc' import { NekoWebRTC } from './internal/webrtc'
import { Session, Scroll } from './types/state' import { Session, Scroll } from './types/state'
@ -53,10 +60,12 @@
}) })
export default class extends Vue { export default class extends Vue {
@Ref('overlay') readonly _overlay!: HTMLCanvasElement @Ref('overlay') readonly _overlay!: HTMLCanvasElement
@Ref('textarea') readonly _textarea!: HTMLTextAreaElement
private _ctx!: CanvasRenderingContext2D private _ctx!: CanvasRenderingContext2D
private keyboard = GuacamoleKeyboard() private keyboard = GuacamoleKeyboard()
private focused = false private focused = false
private ctrlKey = 0
@Prop() @Prop()
private readonly sessions!: Record<string, Session> private readonly sessions!: Record<string, Session>
@ -119,10 +128,20 @@
return true return true
} }
// ctrl+v is aborted
if (this.ctrlKey != 0 && key == KeyTable.XK_v) {
this.keyboard.release(this.ctrlKey)
return true
}
// save information if it is ctrl key event
const isCtrlKey = key == KeyTable.XK_Control_L || key == KeyTable.XK_Control_R
if (isCtrlKey) this.ctrlKey = key
this.webrtc.send('keydown', { this.webrtc.send('keydown', {
key: keySymsRemap(key), key: keySymsRemap(key),
}) })
return false return isCtrlKey
} }
this.keyboard.onkeyup = (key: number) => { this.keyboard.onkeyup = (key: number) => {
if (!this.focused) { if (!this.focused) {
@ -133,11 +152,14 @@
return return
} }
const isCtrlKey = key == KeyTable.XK_Control_L || key == KeyTable.XK_Control_R
if (isCtrlKey) this.ctrlKey = 0
this.webrtc.send('keyup', { this.webrtc.send('keyup', {
key: keySymsRemap(key), key: keySymsRemap(key),
}) })
} }
this.keyboard.listenTo(this._overlay) this.keyboard.listenTo(this._textarea)
this.webrtc.addListener('cursor-position', this.onCursorPosition) this.webrtc.addListener('cursor-position', this.onCursorPosition)
this.webrtc.addListener('cursor-image', this.onCursorImage) this.webrtc.addListener('cursor-image', this.onCursorImage)
@ -205,6 +227,9 @@
return x return x
} }
// TODO: Custom clipboard sharing logic.
onInput() {}
onWheel(e: WheelEvent) { onWheel(e: WheelEvent) {
if (!this.isControling) { if (!this.isControling) {
return return
@ -294,7 +319,7 @@
} }
onMouseEnter(e: MouseEvent) { onMouseEnter(e: MouseEvent) {
this._overlay.focus() this._textarea.focus()
this.focused = true this.focused = true
if (this.isControling) { if (this.isControling) {
@ -313,7 +338,7 @@
}) })
} }
this._overlay.blur() this._textarea.blur()
this.focused = false this.focused = false
} }

View File

@ -1,4 +1,6 @@
const KeyTable = { export const KeyTable = {
XK_v: 0x0076, // U+0076 LATIN SMALL LETTER V
XK_Control_L: 0xffe3, // Left control XK_Control_L: 0xffe3, // Left control
XK_Control_R: 0xffe4, // Right control XK_Control_R: 0xffe4, // Right control