From 71d0823f67f618da5990321699f8fe2ea20dc16d Mon Sep 17 00:00:00 2001 From: Guoguo Date: Mon, 1 Dec 2025 19:15:01 +0800 Subject: [PATCH] fix: mouse position wrong after scaling --- browser/src/components/mouse/absolute.tsx | 44 +++++++++++++++-- .../src/components/mouse/absolute.tsx | 49 ++++++++++++++++--- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/browser/src/components/mouse/absolute.tsx b/browser/src/components/mouse/absolute.tsx index 7f4ab4b..320ef62 100644 --- a/browser/src/components/mouse/absolute.tsx +++ b/browser/src/components/mouse/absolute.tsx @@ -106,11 +106,47 @@ export const Absolute = () => { } async function send(event: MouseEvent, scroll: number = 0) { - const rect = canvas!.getBoundingClientRect(); - const x = Math.abs(event.clientX - rect.left); - const y = Math.abs(event.clientY - rect.top); + const {x, y} = getCorrectedCoords(event.clientX, event.clientY); + await device.sendMouseAbsoluteData(keyRef.current, 1, 1, x, y, scroll); + } - await device.sendMouseAbsoluteData(keyRef.current, rect.width, rect.height, x, y, scroll); + function getCorrectedCoords(clientX: number, clientY: number) { + if (!canvas) { + return { x: 0, y: 0 }; + } + + const rect = canvas.getBoundingClientRect(); + const videoElement = canvas as HTMLVideoElement; + + if (!videoElement.videoWidth || !videoElement.videoHeight) { + const x = (clientX - rect.left) / rect.width; + const y = (clientY - rect.top) / rect.height; + return { x, y }; + } + + const videoRatio = videoElement.videoWidth / videoElement.videoHeight; + const elementRatio = rect.width / rect.height; + + let renderedWidth = rect.width; + let renderedHeight = rect.height; + let offsetX = 0; + let offsetY = 0; + + if (videoRatio > elementRatio) { + renderedHeight = rect.width / videoRatio; + offsetY = (rect.height - renderedHeight) / 2; + } else { + renderedWidth = rect.height * videoRatio; + offsetX = (rect.width - renderedWidth) / 2; + } + + const x = (clientX - rect.left - offsetX) / renderedWidth; + const y = (clientY - rect.top - offsetY) / renderedHeight; + + const finalX = Math.max(0, Math.min(1, x)); + const finalY = Math.max(0, Math.min(1, y)); + + return { x: finalX, y: finalY }; } return () => { diff --git a/desktop/src/renderer/src/components/mouse/absolute.tsx b/desktop/src/renderer/src/components/mouse/absolute.tsx index 525035d..53f8dae 100644 --- a/desktop/src/renderer/src/components/mouse/absolute.tsx +++ b/desktop/src/renderer/src/components/mouse/absolute.tsx @@ -105,21 +105,54 @@ export const Absolute = (): ReactElement => { (keyRef.current.right ? 2 : 0) | (keyRef.current.mid ? 4 : 0) - const rect = canvas!.getBoundingClientRect() - const x = Math.abs(event.clientX - rect.left) - const y = Math.abs(event.clientY - rect.top) + const {x, y} = getCorrectedCoords(event.clientX, event.clientY); await window.electron.ipcRenderer.invoke( IpcEvents.SEND_MOUSE_ABSOLUTE, key, - rect.width, - rect.height, - x, - y, - scroll + 1, 1, x, y, scroll ) } + function getCorrectedCoords(clientX: number, clientY: number) { + if (!canvas) { + return { x: 0, y: 0 }; + } + + const rect = canvas.getBoundingClientRect(); + const videoElement = canvas as HTMLVideoElement; + + if (!videoElement.videoWidth || !videoElement.videoHeight) { + const x = (clientX - rect.left) / rect.width; + const y = (clientY - rect.top) / rect.height; + return { x, y }; + } + + const videoRatio = videoElement.videoWidth / videoElement.videoHeight; + const elementRatio = rect.width / rect.height; + + let renderedWidth = rect.width; + let renderedHeight = rect.height; + let offsetX = 0; + let offsetY = 0; + + if (videoRatio > elementRatio) { + renderedHeight = rect.width / videoRatio; + offsetY = (rect.height - renderedHeight) / 2; + } else { + renderedWidth = rect.height * videoRatio; + offsetX = (rect.width - renderedWidth) / 2; + } + + const x = (clientX - rect.left - offsetX) / renderedWidth; + const y = (clientY - rect.top - offsetY) / renderedHeight; + + const finalX = Math.max(0, Math.min(1, x)); + const finalY = Math.max(0, Math.min(1, y)); + + return { x: finalX, y: finalY }; + } + return (): void => { canvas.removeEventListener('mousemove', handleMouseMove) canvas.removeEventListener('mousedown', handleMouseDown)