mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
do not use ref where not needed.
This commit is contained in:
parent
93125abfd7
commit
3a96d2611e
@ -38,16 +38,16 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const overlay = ref<HTMLCanvasElement | null>(null)
|
const overlay = ref<HTMLCanvasElement | null>(null)
|
||||||
const ctx = ref<CanvasRenderingContext2D | null>(null)
|
|
||||||
const canvasScale = ref(window.devicePixelRatio)
|
|
||||||
|
|
||||||
|
let ctx: CanvasRenderingContext2D | null = null
|
||||||
|
let canvasScale = window.devicePixelRatio
|
||||||
let unsubscribePixelRatioChange = null as (() => void) | null
|
let unsubscribePixelRatioChange = null as (() => void) | null
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// get canvas overlay context
|
// get canvas overlay context
|
||||||
const canvas = overlay.value
|
const canvas = overlay.value
|
||||||
if (canvas != null) {
|
if (canvas != null) {
|
||||||
ctx.value = canvas.getContext('2d')
|
ctx = canvas.getContext('2d')
|
||||||
|
|
||||||
// synchronize intrinsic with extrinsic dimensions
|
// synchronize intrinsic with extrinsic dimensions
|
||||||
const { width, height } = canvas.getBoundingClientRect()
|
const { width, height } = canvas.getBoundingClientRect()
|
||||||
@ -58,7 +58,7 @@ onMounted(() => {
|
|||||||
onPixelRatioChange()
|
onPixelRatioChange()
|
||||||
|
|
||||||
// store last drawing points
|
// store last drawing points
|
||||||
last_points.value = {}
|
last_points = {}
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@ -79,7 +79,7 @@ function onPixelRatioChange() {
|
|||||||
media.removeEventListener('change', onPixelRatioChange)
|
media.removeEventListener('change', onPixelRatioChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasScale.value = window.devicePixelRatio
|
canvasScale = window.devicePixelRatio
|
||||||
onCanvasSizeChange(props.canvasSize)
|
onCanvasSizeChange(props.canvasSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,42 +91,42 @@ function onCanvasSizeChange({ width, height }: Dimension) {
|
|||||||
watch(() => props.canvasSize, onCanvasSizeChange)
|
watch(() => props.canvasSize, onCanvasSizeChange)
|
||||||
|
|
||||||
function canvasResize({ width, height }: Dimension) {
|
function canvasResize({ width, height }: Dimension) {
|
||||||
overlay.value!.width = width * canvasScale.value
|
overlay.value!.width = width * canvasScale
|
||||||
overlay.value!.height = height * canvasScale.value
|
overlay.value!.height = height * canvasScale
|
||||||
ctx.value?.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
|
ctx?.setTransform(canvasScale, 0, 0, canvasScale, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start as undefined to prevent jumping
|
// start as undefined to prevent jumping
|
||||||
const last_animation_time = ref<number>(0)
|
let last_animation_time = 0
|
||||||
// current animation progress (0-1)
|
// current animation progress (0-1)
|
||||||
const percent = ref<number>(0)
|
let percent = 0
|
||||||
// points to be animated for each session
|
// points to be animated for each session
|
||||||
const points = ref<SessionCursors[]>([])
|
let points: SessionCursors[] = []
|
||||||
// last points coordinates for each session
|
// last points coordinates for each session
|
||||||
const last_points = ref<Record<string, Cursor>>({})
|
let last_points: Record<string, Cursor> = {}
|
||||||
|
|
||||||
function canvasAnimateFrame(now: number = NaN) {
|
function canvasAnimateFrame(now: number = NaN) {
|
||||||
// request another frame
|
// request another frame
|
||||||
if (percent.value <= 1) window.requestAnimationFrame(canvasAnimateFrame)
|
if (percent <= 1) window.requestAnimationFrame(canvasAnimateFrame)
|
||||||
|
|
||||||
// calc elapsed time since last loop
|
// calc elapsed time since last loop
|
||||||
const elapsed = now - last_animation_time.value
|
const elapsed = now - last_animation_time
|
||||||
|
|
||||||
// skip if fps is set and elapsed time is less than fps
|
// skip if fps is set and elapsed time is less than fps
|
||||||
if (props.fps > 0 && elapsed < 1000 / props.fps) return
|
if (props.fps > 0 && elapsed < 1000 / props.fps) return
|
||||||
|
|
||||||
// calc current animation progress
|
// calc current animation progress
|
||||||
const delta = elapsed / POS_INTERVAL_MS
|
const delta = elapsed / POS_INTERVAL_MS
|
||||||
last_animation_time.value = now
|
last_animation_time = now
|
||||||
|
|
||||||
// skip very first delta to prevent jumping
|
// skip very first delta to prevent jumping
|
||||||
if (isNaN(delta)) return
|
if (isNaN(delta)) return
|
||||||
|
|
||||||
// set the animation position
|
// set the animation position
|
||||||
percent.value += delta
|
percent += delta
|
||||||
|
|
||||||
// draw points for current frame
|
// draw points for current frame
|
||||||
canvasDrawPoints(percent.value)
|
canvasDrawPoints(percent)
|
||||||
}
|
}
|
||||||
|
|
||||||
function canvasDrawPoints(percent: number = 1) {
|
function canvasDrawPoints(percent: number = 1) {
|
||||||
@ -134,7 +134,7 @@ function canvasDrawPoints(percent: number = 1) {
|
|||||||
canvasClear()
|
canvasClear()
|
||||||
|
|
||||||
// draw current position
|
// draw current position
|
||||||
for (const p of points.value) {
|
for (const p of points) {
|
||||||
const { x, y } = getMovementXYatPercent(p.cursors, percent)
|
const { x, y } = getMovementXYatPercent(p.cursors, percent)
|
||||||
canvasDrawCursor(x, y, p.id)
|
canvasDrawCursor(x, y, p.id)
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ function canvasUpdateCursors() {
|
|||||||
let unchanged = 0
|
let unchanged = 0
|
||||||
|
|
||||||
// create points for animation
|
// create points for animation
|
||||||
points.value = []
|
points = []
|
||||||
for (const { id, cursors } of props.cursors) {
|
for (const { id, cursors } of props.cursors) {
|
||||||
if (
|
if (
|
||||||
// if there are no positions
|
// if there are no positions
|
||||||
@ -166,8 +166,8 @@ function canvasUpdateCursors() {
|
|||||||
|
|
||||||
// add last cursor position to cursors (if available)
|
// add last cursor position to cursors (if available)
|
||||||
let pos = { id } as SessionCursors
|
let pos = { id } as SessionCursors
|
||||||
if (id in last_points.value) {
|
if (id in last_points) {
|
||||||
const last_point = last_points.value[id]
|
const last_point = last_points[id]
|
||||||
|
|
||||||
// if cursor did not move considerably
|
// if cursor did not move considerably
|
||||||
if (
|
if (
|
||||||
@ -191,14 +191,14 @@ function canvasUpdateCursors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
new_last_points[id] = new_last_point
|
new_last_points[id] = new_last_point
|
||||||
points.value.push(pos)
|
points.push(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply new last points
|
// apply new last points
|
||||||
last_points.value = new_last_points
|
last_points = new_last_points
|
||||||
|
|
||||||
// no cursors to animate
|
// no cursors to animate
|
||||||
if (points.value.length == 0) {
|
if (points.length == 0) {
|
||||||
canvasClear()
|
canvasClear()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -211,8 +211,8 @@ function canvasUpdateCursors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start animation if not running
|
// start animation if not running
|
||||||
const p = percent.value
|
const p = percent
|
||||||
percent.value = 0
|
percent = 0
|
||||||
if (p > 1 || !p) {
|
if (p > 1 || !p) {
|
||||||
canvasAnimateFrame()
|
canvasAnimateFrame()
|
||||||
}
|
}
|
||||||
@ -222,17 +222,19 @@ watch(() => props.hostId, canvasUpdateCursors)
|
|||||||
watch(() => props.cursors, canvasUpdateCursors)
|
watch(() => props.cursors, canvasUpdateCursors)
|
||||||
|
|
||||||
function canvasDrawCursor(x: number, y: number, id: string) {
|
function canvasDrawCursor(x: number, y: number, id: string) {
|
||||||
|
if (!ctx) return
|
||||||
|
|
||||||
// get intrinsic dimensions
|
// get intrinsic dimensions
|
||||||
const { width, height } = props.canvasSize
|
const { width, height } = props.canvasSize
|
||||||
x = Math.round((x / props.screenSize.width) * width)
|
x = Math.round((x / props.screenSize.width) * width)
|
||||||
y = Math.round((y / props.screenSize.height) * height)
|
y = Math.round((y / props.screenSize.height) * height)
|
||||||
|
|
||||||
// reset transformation, X and Y will be 0 again
|
// reset transformation, X and Y will be 0 again
|
||||||
ctx.value!.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
|
ctx.setTransform(canvasScale, 0, 0, canvasScale, 0, 0)
|
||||||
|
|
||||||
// use custom draw function, if available
|
// use custom draw function, if available
|
||||||
if (props.cursorDraw) {
|
if (props.cursorDraw) {
|
||||||
props.cursorDraw(ctx.value!, x, y, id)
|
props.cursorDraw(ctx, x, y, id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,23 +242,25 @@ function canvasDrawCursor(x: number, y: number, id: string) {
|
|||||||
const cursorTag = props.sessions[id]?.profile.name || ''
|
const cursorTag = props.sessions[id]?.profile.name || ''
|
||||||
|
|
||||||
// draw inactive cursor tag
|
// draw inactive cursor tag
|
||||||
ctx.value!.font = '14px Arial, sans-serif'
|
ctx.font = '14px Arial, sans-serif'
|
||||||
ctx.value!.textBaseline = 'top'
|
ctx.textBaseline = 'top'
|
||||||
ctx.value!.shadowColor = 'black'
|
ctx.shadowColor = 'black'
|
||||||
ctx.value!.shadowBlur = 2
|
ctx.shadowBlur = 2
|
||||||
ctx.value!.lineWidth = 2
|
ctx.lineWidth = 2
|
||||||
ctx.value!.fillStyle = 'black'
|
ctx.fillStyle = 'black'
|
||||||
ctx.value!.strokeText(cursorTag, x, y)
|
ctx.strokeText(cursorTag, x, y)
|
||||||
ctx.value!.shadowBlur = 0
|
ctx.shadowBlur = 0
|
||||||
ctx.value!.fillStyle = 'white'
|
ctx.fillStyle = 'white'
|
||||||
ctx.value!.fillText(cursorTag, x, y)
|
ctx.fillText(cursorTag, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
function canvasClear() {
|
function canvasClear() {
|
||||||
|
if (!ctx) return
|
||||||
|
|
||||||
// reset transformation, X and Y will be 0 again
|
// reset transformation, X and Y will be 0 again
|
||||||
ctx.value?.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
|
ctx.setTransform(canvasScale, 0, 0, canvasScale, 0, 0)
|
||||||
|
|
||||||
const { width, height } = props.canvasSize
|
const { width, height } = props.canvasSize
|
||||||
ctx.value?.clearRect(0, 0, width, height)
|
ctx.clearRect(0, 0, width, height)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -266,7 +266,7 @@ const events = new NekoMessages(connection, state)
|
|||||||
// Public methods
|
// Public methods
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
||||||
function setUrl(url: string) {
|
function setUrl(url?: string) {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
url = location.href
|
url = location.href
|
||||||
}
|
}
|
||||||
@ -302,7 +302,7 @@ function setUrl(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.server, (url) => {
|
watch(() => props.server, (url) => {
|
||||||
url && setUrl(url)
|
setUrl(url)
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
async function authenticate(token?: string) {
|
async function authenticate(token?: string) {
|
||||||
@ -641,15 +641,15 @@ function onScreenSyncChange() {
|
|||||||
|
|
||||||
watch(() => state.screen.sync.enabled, onScreenSyncChange)
|
watch(() => state.screen.sync.enabled, onScreenSyncChange)
|
||||||
|
|
||||||
const syncScreenSizeTimeout = ref(0)
|
let syncScreenSizeTimeout = 0
|
||||||
|
|
||||||
function syncScreenSize() {
|
function syncScreenSize() {
|
||||||
if (syncScreenSizeTimeout.value) {
|
if (syncScreenSizeTimeout) {
|
||||||
window.clearTimeout(syncScreenSizeTimeout.value)
|
window.clearTimeout(syncScreenSizeTimeout)
|
||||||
}
|
}
|
||||||
syncScreenSizeTimeout.value = window.setTimeout(() => {
|
syncScreenSizeTimeout = window.setTimeout(() => {
|
||||||
const multiplier = state.screen.sync.multiplier || window.devicePixelRatio
|
const multiplier = state.screen.sync.multiplier || window.devicePixelRatio
|
||||||
syncScreenSizeTimeout.value = 0
|
syncScreenSizeTimeout = 0
|
||||||
const { offsetWidth, offsetHeight } = component.value!
|
const { offsetWidth, offsetHeight } = component.value!
|
||||||
setScreenSize(
|
setScreenSize(
|
||||||
Math.round(offsetWidth * multiplier),
|
Math.round(offsetWidth * multiplier),
|
||||||
|
@ -76,15 +76,15 @@ const INACTIVE_CURSOR_INTERVAL = 1000 / 4 // in ms, 4fps
|
|||||||
|
|
||||||
const overlay = ref<HTMLCanvasElement | null>(null)
|
const overlay = ref<HTMLCanvasElement | null>(null)
|
||||||
const textarea = ref<HTMLTextAreaElement | null>(null)
|
const textarea = ref<HTMLTextAreaElement | null>(null)
|
||||||
const ctx = ref<CanvasRenderingContext2D | null>(null)
|
|
||||||
|
|
||||||
const canvasScale = ref(window.devicePixelRatio)
|
let ctx: CanvasRenderingContext2D | null = null
|
||||||
|
let canvasScale = window.devicePixelRatio
|
||||||
|
|
||||||
const keyboard = ref<KeyboardInterface | null>(null)
|
let keyboard: KeyboardInterface = NewKeyboard()
|
||||||
const gestureHandler = ref<GestureHandler | null>(null)
|
let gestureHandler: GestureHandler = new GestureHandlerInit()
|
||||||
const textInput = ref('')
|
|
||||||
|
|
||||||
const focused = ref(false)
|
const focused = ref(false)
|
||||||
|
const textInput = ref('')
|
||||||
|
|
||||||
// props and emits
|
// props and emits
|
||||||
|
|
||||||
@ -124,10 +124,7 @@ onMounted(() => {
|
|||||||
window.addEventListener('mouseup', onMouseUp, true)
|
window.addEventListener('mouseup', onMouseUp, true)
|
||||||
|
|
||||||
// get canvas overlay context
|
// get canvas overlay context
|
||||||
const _ctx = overlay.value?.getContext('2d')
|
ctx = overlay.value!.getContext('2d')
|
||||||
if (_ctx != null) {
|
|
||||||
ctx.value = _ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
// synchronize intrinsic with extrinsic dimensions
|
// synchronize intrinsic with extrinsic dimensions
|
||||||
const { width, height } = overlay.value?.getBoundingClientRect() || { width: 0, height: 0 }
|
const { width, height } = overlay.value?.getBoundingClientRect() || { width: 0, height: 0 }
|
||||||
@ -140,8 +137,7 @@ onMounted(() => {
|
|||||||
let noKeyUp = {} as Record<number, boolean>
|
let noKeyUp = {} as Record<number, boolean>
|
||||||
|
|
||||||
// Initialize Keyboard
|
// Initialize Keyboard
|
||||||
keyboard.value = NewKeyboard()
|
keyboard.onkeydown = (key: number) => {
|
||||||
keyboard.value.onkeydown = (key: number) => {
|
|
||||||
key = keySymsRemap(key)
|
key = keySymsRemap(key)
|
||||||
|
|
||||||
if (!props.isControling) {
|
if (!props.isControling) {
|
||||||
@ -151,7 +147,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// ctrl+v is aborted
|
// ctrl+v is aborted
|
||||||
if (ctrlKey != 0 && key == KeyTable.XK_v) {
|
if (ctrlKey != 0 && key == KeyTable.XK_v) {
|
||||||
keyboard.value!.release(ctrlKey)
|
keyboard!.release(ctrlKey)
|
||||||
noKeyUp[key] = true
|
noKeyUp[key] = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -163,7 +159,7 @@ onMounted(() => {
|
|||||||
props.control.keyDown(key)
|
props.control.keyDown(key)
|
||||||
return isCtrlKey
|
return isCtrlKey
|
||||||
}
|
}
|
||||||
keyboard.value.onkeyup = (key: number) => {
|
keyboard.onkeyup = (key: number) => {
|
||||||
key = keySymsRemap(key)
|
key = keySymsRemap(key)
|
||||||
|
|
||||||
if (key in noKeyUp) {
|
if (key in noKeyUp) {
|
||||||
@ -176,10 +172,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
props.control.keyUp(key)
|
props.control.keyUp(key)
|
||||||
}
|
}
|
||||||
keyboard.value.listenTo(textarea.value!)
|
keyboard.listenTo(textarea.value!)
|
||||||
|
|
||||||
// Initialize GestureHandler
|
|
||||||
gestureHandler.value = new GestureHandlerInit()
|
|
||||||
|
|
||||||
// bind touch handler using @Watch on supportedTouchEvents
|
// bind touch handler using @Watch on supportedTouchEvents
|
||||||
// because we need to know if touch events are supported
|
// because we need to know if touch events are supported
|
||||||
@ -196,10 +189,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('mouseup', onMouseUp, true)
|
window.removeEventListener('mouseup', onMouseUp, true)
|
||||||
|
keyboard.removeListener()
|
||||||
if (keyboard.value) {
|
|
||||||
keyboard.value.removeListener()
|
|
||||||
}
|
|
||||||
|
|
||||||
// unbind touch handler
|
// unbind touch handler
|
||||||
unbindTouchHandler()
|
unbindTouchHandler()
|
||||||
@ -216,8 +206,8 @@ onBeforeUnmount(() => {
|
|||||||
clearInactiveCursorInterval()
|
clearInactiveCursorInterval()
|
||||||
|
|
||||||
// stop pixel ratio change listener
|
// stop pixel ratio change listener
|
||||||
if (unsubscribePixelRatioChange.value) {
|
if (unsubscribePixelRatioChange) {
|
||||||
unsubscribePixelRatioChange.value()
|
unsubscribePixelRatioChange()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -280,23 +270,23 @@ function onTouchHandler(ev: TouchEvent) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
function bindGestureHandler() {
|
function bindGestureHandler() {
|
||||||
gestureHandler.value?.attach(textarea.value!)
|
gestureHandler.attach(textarea.value!)
|
||||||
textarea.value?.addEventListener('gesturestart', onGestureHandler)
|
textarea.value?.addEventListener('gesturestart', onGestureHandler)
|
||||||
textarea.value?.addEventListener('gesturemove', onGestureHandler)
|
textarea.value?.addEventListener('gesturemove', onGestureHandler)
|
||||||
textarea.value?.addEventListener('gestureend', onGestureHandler)
|
textarea.value?.addEventListener('gestureend', onGestureHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
function unbindGestureHandler() {
|
function unbindGestureHandler() {
|
||||||
gestureHandler.value?.detach()
|
gestureHandler.detach()
|
||||||
textarea.value?.removeEventListener('gesturestart', onGestureHandler)
|
textarea.value?.removeEventListener('gesturestart', onGestureHandler)
|
||||||
textarea.value?.removeEventListener('gesturemove', onGestureHandler)
|
textarea.value?.removeEventListener('gesturemove', onGestureHandler)
|
||||||
textarea.value?.removeEventListener('gestureend', onGestureHandler)
|
textarea.value?.removeEventListener('gestureend', onGestureHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
const gestureLastTapTime = ref<number | null>(null)
|
let gestureLastTapTime: number | null = null
|
||||||
const gestureFirstDoubleTapEv = ref<any | null>(null)
|
let gestureFirstDoubleTapEv: any | null = null
|
||||||
const gestureLastMagnitudeX = ref(0)
|
let gestureLastMagnitudeX = 0
|
||||||
const gestureLastMagnitudeY = ref(0)
|
let gestureLastMagnitudeY = 0
|
||||||
|
|
||||||
function _handleTapEvent(ev: any, code: number) {
|
function _handleTapEvent(ev: any, code: number) {
|
||||||
let pos = getMousePos(ev.detail.clientX, ev.detail.clientY)
|
let pos = getMousePos(ev.detail.clientX, ev.detail.clientY)
|
||||||
@ -305,23 +295,23 @@ function _handleTapEvent(ev: any, code: number) {
|
|||||||
// hit the same spot, so slightly adjust coordinates
|
// hit the same spot, so slightly adjust coordinates
|
||||||
|
|
||||||
if (
|
if (
|
||||||
gestureLastTapTime.value !== null &&
|
gestureLastTapTime !== null &&
|
||||||
Date.now() - gestureLastTapTime.value < DOUBLE_TAP_TIMEOUT &&
|
Date.now() - gestureLastTapTime < DOUBLE_TAP_TIMEOUT &&
|
||||||
gestureFirstDoubleTapEv.value?.detail.type === ev.detail.type
|
gestureFirstDoubleTapEv?.detail.type === ev.detail.type
|
||||||
) {
|
) {
|
||||||
const dx = gestureFirstDoubleTapEv.value.detail.clientX - ev.detail.clientX
|
const dx = gestureFirstDoubleTapEv.detail.clientX - ev.detail.clientX
|
||||||
const dy = gestureFirstDoubleTapEv.value.detail.clientY - ev.detail.clientY
|
const dy = gestureFirstDoubleTapEv.detail.clientY - ev.detail.clientY
|
||||||
const distance = Math.hypot(dx, dy)
|
const distance = Math.hypot(dx, dy)
|
||||||
|
|
||||||
if (distance < DOUBLE_TAP_THRESHOLD) {
|
if (distance < DOUBLE_TAP_THRESHOLD) {
|
||||||
pos = getMousePos(gestureFirstDoubleTapEv.value.detail.clientX, gestureFirstDoubleTapEv.value.detail.clientY)
|
pos = getMousePos(gestureFirstDoubleTapEv.detail.clientX, gestureFirstDoubleTapEv.detail.clientY)
|
||||||
} else {
|
} else {
|
||||||
gestureFirstDoubleTapEv.value = ev
|
gestureFirstDoubleTapEv = ev
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gestureFirstDoubleTapEv.value = ev
|
gestureFirstDoubleTapEv = ev
|
||||||
}
|
}
|
||||||
gestureLastTapTime.value = Date.now()
|
gestureLastTapTime = Date.now()
|
||||||
|
|
||||||
props.control.buttonDown(code, pos)
|
props.control.buttonDown(code, pos)
|
||||||
props.control.buttonUp(code, pos)
|
props.control.buttonUp(code, pos)
|
||||||
@ -361,12 +351,12 @@ function onGestureHandler(ev: any) {
|
|||||||
break
|
break
|
||||||
|
|
||||||
case 'twodrag':
|
case 'twodrag':
|
||||||
gestureLastMagnitudeX.value = ev.detail.magnitudeX
|
gestureLastMagnitudeX = ev.detail.magnitudeX
|
||||||
gestureLastMagnitudeY.value = ev.detail.magnitudeY
|
gestureLastMagnitudeY = ev.detail.magnitudeY
|
||||||
props.control.move(pos)
|
props.control.move(pos)
|
||||||
break
|
break
|
||||||
case 'pinch':
|
case 'pinch':
|
||||||
gestureLastMagnitudeX.value = Math.hypot(ev.detail.magnitudeX, ev.detail.magnitudeY)
|
gestureLastMagnitudeX = Math.hypot(ev.detail.magnitudeX, ev.detail.magnitudeY)
|
||||||
props.control.move(pos)
|
props.control.move(pos)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -387,21 +377,21 @@ function onGestureHandler(ev: any) {
|
|||||||
// We don't know if the mouse was moved so we need to move it
|
// We don't know if the mouse was moved so we need to move it
|
||||||
// every update.
|
// every update.
|
||||||
props.control.move(pos)
|
props.control.move(pos)
|
||||||
while (ev.detail.magnitudeY - gestureLastMagnitudeY.value > GESTURE_SCRLSENS) {
|
while (ev.detail.magnitudeY - gestureLastMagnitudeY > GESTURE_SCRLSENS) {
|
||||||
props.control.scroll({ delta_x: 0, delta_y: 1 })
|
props.control.scroll({ delta_x: 0, delta_y: 1 })
|
||||||
gestureLastMagnitudeY.value += GESTURE_SCRLSENS
|
gestureLastMagnitudeY += GESTURE_SCRLSENS
|
||||||
}
|
}
|
||||||
while (ev.detail.magnitudeY - gestureLastMagnitudeY.value < -GESTURE_SCRLSENS) {
|
while (ev.detail.magnitudeY - gestureLastMagnitudeY < -GESTURE_SCRLSENS) {
|
||||||
props.control.scroll({ delta_x: 0, delta_y: -1 })
|
props.control.scroll({ delta_x: 0, delta_y: -1 })
|
||||||
gestureLastMagnitudeY.value -= GESTURE_SCRLSENS
|
gestureLastMagnitudeY -= GESTURE_SCRLSENS
|
||||||
}
|
}
|
||||||
while (ev.detail.magnitudeX - gestureLastMagnitudeX.value > GESTURE_SCRLSENS) {
|
while (ev.detail.magnitudeX - gestureLastMagnitudeX > GESTURE_SCRLSENS) {
|
||||||
props.control.scroll({ delta_x: 1, delta_y: 0 })
|
props.control.scroll({ delta_x: 1, delta_y: 0 })
|
||||||
gestureLastMagnitudeX.value += GESTURE_SCRLSENS
|
gestureLastMagnitudeX+= GESTURE_SCRLSENS
|
||||||
}
|
}
|
||||||
while (ev.detail.magnitudeX - gestureLastMagnitudeX.value < -GESTURE_SCRLSENS) {
|
while (ev.detail.magnitudeX - gestureLastMagnitudeX < -GESTURE_SCRLSENS) {
|
||||||
props.control.scroll({ delta_x: -1, delta_y: 0 })
|
props.control.scroll({ delta_x: -1, delta_y: 0 })
|
||||||
gestureLastMagnitudeX.value -= GESTURE_SCRLSENS
|
gestureLastMagnitudeX-= GESTURE_SCRLSENS
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'pinch':
|
case 'pinch':
|
||||||
@ -410,14 +400,14 @@ function onGestureHandler(ev: any) {
|
|||||||
// every update.
|
// every update.
|
||||||
props.control.move(pos)
|
props.control.move(pos)
|
||||||
magnitude = Math.hypot(ev.detail.magnitudeX, ev.detail.magnitudeY)
|
magnitude = Math.hypot(ev.detail.magnitudeX, ev.detail.magnitudeY)
|
||||||
if (Math.abs(magnitude - gestureLastMagnitudeX.value) > GESTURE_ZOOMSENS) {
|
if (Math.abs(magnitude - gestureLastMagnitudeX) > GESTURE_ZOOMSENS) {
|
||||||
while (magnitude - gestureLastMagnitudeX.value > GESTURE_ZOOMSENS) {
|
while (magnitude - gestureLastMagnitudeX > GESTURE_ZOOMSENS) {
|
||||||
props.control.scroll({ delta_x: 0, delta_y: 1, control_key: true })
|
props.control.scroll({ delta_x: 0, delta_y: 1, control_key: true })
|
||||||
gestureLastMagnitudeX.value += GESTURE_ZOOMSENS
|
gestureLastMagnitudeX+= GESTURE_ZOOMSENS
|
||||||
}
|
}
|
||||||
while (magnitude - gestureLastMagnitudeX.value < -GESTURE_ZOOMSENS) {
|
while (magnitude - gestureLastMagnitudeX < -GESTURE_ZOOMSENS) {
|
||||||
props.control.scroll({ delta_x: 0, delta_y: -1, control_key: true })
|
props.control.scroll({ delta_x: 0, delta_y: -1, control_key: true })
|
||||||
gestureLastMagnitudeX.value -= GESTURE_ZOOMSENS
|
gestureLastMagnitudeX-= GESTURE_ZOOMSENS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -500,12 +490,12 @@ function sendMousePos(e: MouseEvent) {
|
|||||||
if (props.webrtc.connected) {
|
if (props.webrtc.connected) {
|
||||||
props.webrtc.send('mousemove', pos)
|
props.webrtc.send('mousemove', pos)
|
||||||
} // otherwise, no events are sent
|
} // otherwise, no events are sent
|
||||||
cursorPosition.value = pos
|
cursorPosition = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
const wheelX = ref(0)
|
let wheelX = 0
|
||||||
const wheelY = ref(0)
|
let wheelY = 0
|
||||||
const wheelTimeStamp = ref(0)
|
let wheelTimeStamp = 0
|
||||||
|
|
||||||
// negative sensitivity can be acheived using increased step value
|
// negative sensitivity can be acheived using increased step value
|
||||||
const wheelStep = computed(() => {
|
const wheelStep = computed(() => {
|
||||||
@ -550,12 +540,12 @@ function onWheel(e: WheelEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when the last scroll was more than 250ms ago
|
// when the last scroll was more than 250ms ago
|
||||||
const firstScroll = e.timeStamp - wheelTimeStamp.value > 250
|
const firstScroll = e.timeStamp - wheelTimeStamp > 250
|
||||||
|
|
||||||
if (firstScroll) {
|
if (firstScroll) {
|
||||||
wheelX.value = 0
|
wheelX = 0
|
||||||
wheelY.value = 0
|
wheelY = 0
|
||||||
wheelTimeStamp.value = e.timeStamp
|
wheelTimeStamp = e.timeStamp
|
||||||
}
|
}
|
||||||
|
|
||||||
let dx = e.deltaX
|
let dx = e.deltaX
|
||||||
@ -566,32 +556,32 @@ function onWheel(e: WheelEvent) {
|
|||||||
dy *= WHEEL_LINE_HEIGHT
|
dy *= WHEEL_LINE_HEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
wheelX.value += dx
|
wheelX += dx
|
||||||
wheelY.value += dy
|
wheelY += dy
|
||||||
|
|
||||||
let x = 0
|
let x = 0
|
||||||
if (Math.abs(wheelX.value) >= wheelStep.value || firstScroll) {
|
if (Math.abs(wheelX) >= wheelStep.value || firstScroll) {
|
||||||
if (wheelX.value < 0) {
|
if (wheelX < 0) {
|
||||||
x = wheelSensitivity.value * -1
|
x = wheelSensitivity.value * -1
|
||||||
} else if (wheelX.value > 0) {
|
} else if (wheelX > 0) {
|
||||||
x = wheelSensitivity.value
|
x = wheelSensitivity.value
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!firstScroll) {
|
if (!firstScroll) {
|
||||||
wheelX.value = 0
|
wheelX = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let y = 0
|
let y = 0
|
||||||
if (Math.abs(wheelY.value) >= wheelStep.value || firstScroll) {
|
if (Math.abs(wheelY) >= wheelStep.value || firstScroll) {
|
||||||
if (wheelY.value < 0) {
|
if (wheelY < 0) {
|
||||||
y = wheelSensitivity.value * -1
|
y = wheelSensitivity.value * -1
|
||||||
} else if (wheelY.value > 0) {
|
} else if (wheelY > 0) {
|
||||||
y = wheelSensitivity.value
|
y = wheelSensitivity.value
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!firstScroll) {
|
if (!firstScroll) {
|
||||||
wheelY.value = 0
|
wheelY = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,12 +596,12 @@ function onWheel(e: WheelEvent) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastMouseMove = ref(0)
|
let lastMouseMove = 0
|
||||||
|
|
||||||
function onMouseMove(e: MouseEvent) {
|
function onMouseMove(e: MouseEvent) {
|
||||||
// throttle mousemove events
|
// throttle mousemove events
|
||||||
if (e.timeStamp - lastMouseMove.value < MOUSE_MOVE_THROTTLE) return
|
if (e.timeStamp - lastMouseMove < MOUSE_MOVE_THROTTLE) return
|
||||||
lastMouseMove.value = e.timeStamp
|
lastMouseMove = e.timeStamp
|
||||||
|
|
||||||
if (props.isControling) {
|
if (props.isControling) {
|
||||||
sendMousePos(e)
|
sendMousePos(e)
|
||||||
@ -622,10 +612,10 @@ function onMouseMove(e: MouseEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMouseDown = ref(false)
|
let isMouseDown = false
|
||||||
|
|
||||||
function onMouseDown(e: MouseEvent) {
|
function onMouseDown(e: MouseEvent) {
|
||||||
isMouseDown.value = true
|
isMouseDown = true
|
||||||
|
|
||||||
if (!props.isControling) {
|
if (!props.isControling) {
|
||||||
implicitControlRequest(e)
|
implicitControlRequest(e)
|
||||||
@ -639,8 +629,8 @@ function onMouseDown(e: MouseEvent) {
|
|||||||
|
|
||||||
function onMouseUp(e: MouseEvent) {
|
function onMouseUp(e: MouseEvent) {
|
||||||
// only if we are the one who started the mouse down
|
// only if we are the one who started the mouse down
|
||||||
if (!isMouseDown.value) return
|
if (!isMouseDown) return
|
||||||
isMouseDown.value = false
|
isMouseDown = false
|
||||||
|
|
||||||
if (!props.isControling) {
|
if (!props.isControling) {
|
||||||
implicitControlRequest(e)
|
implicitControlRequest(e)
|
||||||
@ -668,7 +658,7 @@ function onMouseEnter(e: MouseEvent) {
|
|||||||
function onMouseLeave(e: MouseEvent) {
|
function onMouseLeave(e: MouseEvent) {
|
||||||
if (props.isControling) {
|
if (props.isControling) {
|
||||||
// save current keyboard modifiers state
|
// save current keyboard modifiers state
|
||||||
keyboardModifiers.value = getModifierState(e)
|
keyboardModifiers = getModifierState(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
focused.value = false
|
focused.value = false
|
||||||
@ -703,13 +693,13 @@ async function onDrop(e: DragEvent) {
|
|||||||
// inactive cursor position
|
// inactive cursor position
|
||||||
//
|
//
|
||||||
|
|
||||||
const inactiveCursorInterval = ref<number | null>(null)
|
let inactiveCursorInterval: number | null = null
|
||||||
const inactiveCursorPosition = ref<CursorPosition | null>(null)
|
let inactiveCursorPosition: CursorPosition | null = null
|
||||||
|
|
||||||
function clearInactiveCursorInterval() {
|
function clearInactiveCursorInterval() {
|
||||||
if (inactiveCursorInterval.value) {
|
if (inactiveCursorInterval) {
|
||||||
window.clearInterval(inactiveCursorInterval.value)
|
window.clearInterval(inactiveCursorInterval)
|
||||||
inactiveCursorInterval.value = null
|
inactiveCursorInterval = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +708,7 @@ function restartInactiveCursorInterval() {
|
|||||||
clearInactiveCursorInterval()
|
clearInactiveCursorInterval()
|
||||||
|
|
||||||
if (props.inactiveCursors && focused.value && !props.isControling) {
|
if (props.inactiveCursors && focused.value && !props.isControling) {
|
||||||
inactiveCursorInterval.value = window.setInterval(sendInactiveMousePos, INACTIVE_CURSOR_INTERVAL)
|
inactiveCursorInterval = window.setInterval(sendInactiveMousePos, INACTIVE_CURSOR_INTERVAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,14 +718,14 @@ watch(() => props.isControling, restartInactiveCursorInterval)
|
|||||||
|
|
||||||
function saveInactiveMousePos(e: MouseEvent) {
|
function saveInactiveMousePos(e: MouseEvent) {
|
||||||
const pos = getMousePos(e.clientX, e.clientY)
|
const pos = getMousePos(e.clientX, e.clientY)
|
||||||
inactiveCursorPosition.value = pos
|
inactiveCursorPosition = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendInactiveMousePos() {
|
function sendInactiveMousePos() {
|
||||||
if (inactiveCursorPosition.value && props.webrtc.connected) {
|
if (inactiveCursorPosition && props.webrtc.connected) {
|
||||||
// not using NekoControl here, because inactive cursors are
|
// not using NekoControl here, because inactive cursors are
|
||||||
// treated differently than moving the mouse while controling
|
// treated differently than moving the mouse while controling
|
||||||
props.webrtc.send('mousemove', inactiveCursorPosition.value)
|
props.webrtc.send('mousemove', inactiveCursorPosition)
|
||||||
} // if webrtc is not connected, we don't need to send anything
|
} // if webrtc is not connected, we don't need to send anything
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,12 +733,12 @@ function sendInactiveMousePos() {
|
|||||||
// keyboard modifiers
|
// keyboard modifiers
|
||||||
//
|
//
|
||||||
|
|
||||||
const keyboardModifiers = ref<KeyboardModifiers | null>(null)
|
let keyboardModifiers: KeyboardModifiers | null = null
|
||||||
|
|
||||||
function updateKeyboardModifiers(e: MouseEvent) {
|
function updateKeyboardModifiers(e: MouseEvent) {
|
||||||
const mods = getModifierState(e)
|
const mods = getModifierState(e)
|
||||||
const newMods = Object.values(mods).join()
|
const newMods = Object.values(mods).join()
|
||||||
const oldMods = Object.values(keyboardModifiers.value || {}).join()
|
const oldMods = Object.values(keyboardModifiers || {}).join()
|
||||||
|
|
||||||
// update keyboard modifiers only if they changed
|
// update keyboard modifiers only if they changed
|
||||||
if (newMods !== oldMods) {
|
if (newMods !== oldMods) {
|
||||||
@ -762,25 +752,26 @@ function updateKeyboardModifiers(e: MouseEvent) {
|
|||||||
|
|
||||||
const cursorImage = ref<CursorImage | null>(null)
|
const cursorImage = ref<CursorImage | null>(null)
|
||||||
const cursorElement = new Image()
|
const cursorElement = new Image()
|
||||||
const cursorPosition = ref<CursorPosition | null>(null)
|
|
||||||
const cursorLastTime = ref(0)
|
|
||||||
const canvasRequestedFrame = ref(false)
|
|
||||||
const canvasRenderTimeout = ref<number | null>(null)
|
|
||||||
|
|
||||||
const unsubscribePixelRatioChange = ref<(() => void) | null>(null)
|
let cursorPosition: CursorPosition | null = null
|
||||||
|
let cursorLastTime = 0
|
||||||
|
let canvasRequestedFrame = false
|
||||||
|
let canvasRenderTimeout: number | null = null
|
||||||
|
|
||||||
|
let unsubscribePixelRatioChange: (() => void) | null = null
|
||||||
|
|
||||||
function onPixelRatioChange() {
|
function onPixelRatioChange() {
|
||||||
if (unsubscribePixelRatioChange.value) {
|
if (unsubscribePixelRatioChange) {
|
||||||
unsubscribePixelRatioChange.value()
|
unsubscribePixelRatioChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
const media = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
|
const media = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
|
||||||
media.addEventListener('change', onPixelRatioChange)
|
media.addEventListener('change', onPixelRatioChange)
|
||||||
unsubscribePixelRatioChange.value = () => {
|
unsubscribePixelRatioChange = () => {
|
||||||
media.removeEventListener('change', onPixelRatioChange)
|
media.removeEventListener('change', onPixelRatioChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasScale.value = window.devicePixelRatio
|
canvasScale = window.devicePixelRatio
|
||||||
onCanvasSizeChange(props.canvasSize)
|
onCanvasSizeChange(props.canvasSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,7 +784,7 @@ watch(() => props.canvasSize, onCanvasSizeChange)
|
|||||||
|
|
||||||
function onCursorPosition(data: CursorPosition) {
|
function onCursorPosition(data: CursorPosition) {
|
||||||
if (!props.isControling) {
|
if (!props.isControling) {
|
||||||
cursorPosition.value = data
|
cursorPosition = data
|
||||||
canvasRequestRedraw()
|
canvasRequestRedraw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -807,30 +798,32 @@ function onCursorImage(data: CursorImage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function canvasResize({ width, height }: Dimension) {
|
function canvasResize({ width, height }: Dimension) {
|
||||||
overlay.value!.width = width * canvasScale.value
|
if (!ctx || !overlay.value) return
|
||||||
overlay.value!.height = height * canvasScale.value
|
|
||||||
ctx.value!.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
|
overlay.value.width = width * canvasScale
|
||||||
|
overlay.value.height = height * canvasScale
|
||||||
|
ctx.setTransform(canvasScale, 0, 0, canvasScale, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function canvasRequestRedraw() {
|
function canvasRequestRedraw() {
|
||||||
if (canvasRequestedFrame.value) return
|
if (canvasRequestedFrame) return
|
||||||
|
|
||||||
if (props.fps > 0) {
|
if (props.fps > 0) {
|
||||||
if (canvasRenderTimeout.value) {
|
if (canvasRenderTimeout) {
|
||||||
window.clearTimeout(canvasRenderTimeout.value)
|
window.clearTimeout(canvasRenderTimeout)
|
||||||
canvasRenderTimeout.value = null
|
canvasRenderTimeout = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
if (now - cursorLastTime.value < 1000 / props.fps) {
|
if (now - cursorLastTime < 1000 / props.fps) {
|
||||||
canvasRenderTimeout.value = window.setTimeout(canvasRequestRedraw, 1000 / props.fps)
|
canvasRenderTimeout = window.setTimeout(canvasRequestRedraw, 1000 / props.fps)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cursorLastTime.value = now
|
cursorLastTime = now
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasRequestedFrame.value = true
|
canvasRequestedFrame = true
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
if (props.isControling) {
|
if (props.isControling) {
|
||||||
canvasClear()
|
canvasClear()
|
||||||
@ -838,7 +831,7 @@ function canvasRequestRedraw() {
|
|||||||
canvasRedraw()
|
canvasRedraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasRequestedFrame.value = false
|
canvasRequestedFrame = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,7 +839,7 @@ watch(() => props.hostId, canvasRequestRedraw)
|
|||||||
watch(() => props.cursorDraw, canvasRequestRedraw)
|
watch(() => props.cursorDraw, canvasRequestRedraw)
|
||||||
|
|
||||||
function canvasRedraw() {
|
function canvasRedraw() {
|
||||||
if (!cursorPosition.value || !props.screenSize || !cursorImage.value) return
|
if (!ctx || !cursorPosition || !props.screenSize || !cursorImage.value) return
|
||||||
|
|
||||||
// clear drawings
|
// clear drawings
|
||||||
canvasClear()
|
canvasClear()
|
||||||
@ -858,20 +851,20 @@ function canvasRedraw() {
|
|||||||
const { width, height } = props.canvasSize
|
const { width, height } = props.canvasSize
|
||||||
|
|
||||||
// reset transformation, X and Y will be 0 again
|
// reset transformation, X and Y will be 0 again
|
||||||
ctx.value!.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
|
ctx.setTransform(canvasScale, 0, 0, canvasScale, 0, 0)
|
||||||
|
|
||||||
// get cursor position
|
// get cursor position
|
||||||
let x = Math.round((cursorPosition.value.x / props.screenSize.width) * width)
|
let x = Math.round((cursorPosition.x / props.screenSize.width) * width)
|
||||||
let y = Math.round((cursorPosition.value.y / props.screenSize.height) * height)
|
let y = Math.round((cursorPosition.y / props.screenSize.height) * height)
|
||||||
|
|
||||||
// use custom draw function, if available
|
// use custom draw function, if available
|
||||||
if (props.cursorDraw) {
|
if (props.cursorDraw) {
|
||||||
props.cursorDraw(ctx.value!, x, y, cursorElement, cursorImage.value, props.hostId)
|
props.cursorDraw(ctx, x, y, cursorElement, cursorImage.value, props.hostId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw cursor image
|
// draw cursor image
|
||||||
ctx.value!.drawImage(
|
ctx.drawImage(
|
||||||
cursorElement,
|
cursorElement,
|
||||||
x - cursorImage.value.x,
|
x - cursorImage.value.x,
|
||||||
y - cursorImage.value.y,
|
y - cursorImage.value.y,
|
||||||
@ -885,63 +878,65 @@ function canvasRedraw() {
|
|||||||
x += cursorImage.value.width
|
x += cursorImage.value.width
|
||||||
y += cursorImage.value.height
|
y += cursorImage.value.height
|
||||||
|
|
||||||
ctx.value!.font = '14px Arial, sans-serif'
|
ctx.font = '14px Arial, sans-serif'
|
||||||
ctx.value!.textBaseline = 'top'
|
ctx.textBaseline = 'top'
|
||||||
ctx.value!.shadowColor = 'black'
|
ctx.shadowColor = 'black'
|
||||||
ctx.value!.shadowBlur = 2
|
ctx.shadowBlur = 2
|
||||||
ctx.value!.lineWidth = 2
|
ctx.lineWidth = 2
|
||||||
ctx.value!.fillStyle = 'black'
|
ctx.fillStyle = 'black'
|
||||||
ctx.value!.strokeText(cursorTag, x, y)
|
ctx.strokeText(cursorTag, x, y)
|
||||||
ctx.value!.shadowBlur = 0
|
ctx.shadowBlur = 0
|
||||||
ctx.value!.fillStyle = 'white'
|
ctx.fillStyle = 'white'
|
||||||
ctx.value!.fillText(cursorTag, x, y)
|
ctx.fillText(cursorTag, x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function canvasClear() {
|
function canvasClear() {
|
||||||
|
if (!ctx) return
|
||||||
|
|
||||||
// reset transformation, X and Y will be 0 again
|
// reset transformation, X and Y will be 0 again
|
||||||
ctx.value!.setTransform(canvasScale.value, 0, 0, canvasScale.value, 0, 0)
|
ctx.setTransform(canvasScale, 0, 0, canvasScale, 0, 0)
|
||||||
|
|
||||||
const { width, height } = props.canvasSize
|
const { width, height } = props.canvasSize
|
||||||
ctx.value!.clearRect(0, 0, width, height)
|
ctx.clearRect(0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// implicit hosting
|
// implicit hosting
|
||||||
//
|
//
|
||||||
|
|
||||||
const reqMouseDown = ref<MouseEvent | null>(null)
|
let reqMouseDown: MouseEvent | null = null
|
||||||
const reqMouseUp = ref<MouseEvent | null>(null)
|
let reqMouseUp: MouseEvent | null = null
|
||||||
|
|
||||||
function onControlChange(isControling: boolean) {
|
function onControlChange(isControling: boolean) {
|
||||||
keyboardModifiers.value = null
|
keyboardModifiers = null
|
||||||
|
|
||||||
if (isControling && reqMouseDown.value) {
|
if (isControling && reqMouseDown) {
|
||||||
updateKeyboardModifiers(reqMouseDown.value)
|
updateKeyboardModifiers(reqMouseDown)
|
||||||
onMouseDown(reqMouseDown.value)
|
onMouseDown(reqMouseDown)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isControling && reqMouseUp.value) {
|
if (isControling && reqMouseUp) {
|
||||||
onMouseUp(reqMouseUp.value)
|
onMouseUp(reqMouseUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasRequestRedraw()
|
canvasRequestRedraw()
|
||||||
|
|
||||||
reqMouseDown.value = null
|
reqMouseDown = null
|
||||||
reqMouseUp.value = null
|
reqMouseUp = null
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.isControling, onControlChange)
|
watch(() => props.isControling, onControlChange)
|
||||||
|
|
||||||
function implicitControlRequest(e: MouseEvent) {
|
function implicitControlRequest(e: MouseEvent) {
|
||||||
if (props.implicitControl && e.type === 'mousedown') {
|
if (props.implicitControl && e.type === 'mousedown') {
|
||||||
reqMouseDown.value = e
|
reqMouseDown = e
|
||||||
reqMouseUp.value = null
|
reqMouseUp = null
|
||||||
props.control.request()
|
props.control.request()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.implicitControl && e.type === 'mouseup') {
|
if (props.implicitControl && e.type === 'mouseup') {
|
||||||
reqMouseUp.value = e
|
reqMouseUp = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -956,15 +951,15 @@ function implicitControlRelease() {
|
|||||||
// mobile keyboard
|
// mobile keyboard
|
||||||
//
|
//
|
||||||
|
|
||||||
const kbdShow = ref(false)
|
let kbdShow = false
|
||||||
const kbdOpen = ref(false)
|
let kbdOpen = false
|
||||||
|
|
||||||
function mobileKeyboardShow() {
|
function mobileKeyboardShow() {
|
||||||
// skip if not a touch device
|
// skip if not a touch device
|
||||||
if (!props.hasMobileKeyboard) return
|
if (!props.hasMobileKeyboard) return
|
||||||
|
|
||||||
kbdShow.value = true
|
kbdShow = true
|
||||||
kbdOpen.value = false
|
kbdOpen = false
|
||||||
|
|
||||||
textarea.value!.focus()
|
textarea.value!.focus()
|
||||||
window.visualViewport?.addEventListener('resize', onVisualViewportResize)
|
window.visualViewport?.addEventListener('resize', onVisualViewportResize)
|
||||||
@ -975,8 +970,8 @@ function mobileKeyboardHide() {
|
|||||||
// skip if not a touch device
|
// skip if not a touch device
|
||||||
if (!props.hasMobileKeyboard) return
|
if (!props.hasMobileKeyboard) return
|
||||||
|
|
||||||
kbdShow.value = false
|
kbdShow = false
|
||||||
kbdOpen.value = false
|
kbdOpen = false
|
||||||
|
|
||||||
emit('mobileKeyboardOpen', false)
|
emit('mobileKeyboardOpen', false)
|
||||||
window.visualViewport?.removeEventListener('resize', onVisualViewportResize)
|
window.visualViewport?.removeEventListener('resize', onVisualViewportResize)
|
||||||
@ -986,10 +981,10 @@ function mobileKeyboardHide() {
|
|||||||
// visual viewport resize event is fired when keyboard is opened or closed
|
// visual viewport resize event is fired when keyboard is opened or closed
|
||||||
// android does not blur textarea when keyboard is closed, so we need to do it manually
|
// android does not blur textarea when keyboard is closed, so we need to do it manually
|
||||||
function onVisualViewportResize() {
|
function onVisualViewportResize() {
|
||||||
if (!kbdShow.value) return
|
if (!kbdShow) return
|
||||||
|
|
||||||
if (!kbdOpen.value) {
|
if (!kbdOpen) {
|
||||||
kbdOpen.value = true
|
kbdOpen = true
|
||||||
} else {
|
} else {
|
||||||
mobileKeyboardHide()
|
mobileKeyboardHide()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user