fix: Implement DPI Scaling Support (#601)

This commit is contained in:
Sline
2025-09-21 13:46:42 +08:00
committed by GitHub
parent 400103c488
commit f4a5828ea7
3 changed files with 64 additions and 4 deletions
@@ -216,8 +216,35 @@ export function useTauriDpi() {
return new imported.LogicalPosition(x, y)
}
async function getScaleFactor(): Promise<number> {
const imported = await tauriDpiApi.value
if (!imported) {
throw new Error('Tauri DPI API not available')
}
const monitor = await imported.currentMonitor()
return monitor?.scaleFactor ?? 1
}
function convertPhysicalToLogical(physicalX: number, physicalY: number, scaleFactor: number): { x: number, y: number } {
return {
x: physicalX / scaleFactor,
y: physicalY / scaleFactor,
}
}
function convertLogicalToPhysical(logicalX: number, logicalY: number, scaleFactor: number): { x: number, y: number } {
return {
x: logicalX * scaleFactor,
y: logicalY * scaleFactor,
}
}
return {
createLogicalPosition,
getScaleFactor,
convertPhysicalToLogical,
convertLogicalToPhysical,
}
}
@@ -1,17 +1,42 @@
import type { AiriTamagotchiEvents } from './tauri'
import { createSharedComposable } from '@vueuse/core'
import { ref } from 'vue'
import { ref, watch } from 'vue'
import { useTauriEvent } from './tauri'
import { useTauriDpi, useTauriEvent } from './tauri'
export const useRdevMouse = createSharedComposable(() => {
const mouseX = ref(0)
const mouseY = ref(0)
const logicalMouseX = ref(0)
const logicalMouseY = ref(0)
const scaleFactor = ref(1)
const { listen } = useTauriEvent<AiriTamagotchiEvents>()
const { getScaleFactor } = useTauriDpi()
// Update scale factor when DPI changes
async function updateScaleFactor() {
try {
const newScaleFactor = await getScaleFactor()
scaleFactor.value = newScaleFactor
}
catch (error) {
console.warn('Failed to get scale factor, using default 1.0:', error)
scaleFactor.value = 1
}
}
// Convert physical coordinates to logical coordinates
watch([mouseX, mouseY, scaleFactor], ([x, y, scale]) => {
const logical = convertPhysicalToLogical(x, y, scale)
logicalMouseX.value = logical.x
logicalMouseY.value = logical.y
})
async function setup() {
await updateScaleFactor()
await listen('tauri-plugins:tauri-plugin-rdev:mousemove', (event) => {
if (event.payload.event_type.MouseMove) {
const { x, y } = event.payload.event_type.MouseMove
@@ -19,6 +44,11 @@ export const useRdevMouse = createSharedComposable(() => {
mouseY.value = y
}
})
// Listen for scale changes (when window moves between monitors with different DPI)
await listen('tauri://scale-change', () => {
updateScaleFactor()
})
}
setup()
@@ -26,5 +56,8 @@ export const useRdevMouse = createSharedComposable(() => {
return {
mouseX,
mouseY,
logicalMouseX,
logicalMouseY,
scaleFactor,
}
})
+2 -2
View File
@@ -30,7 +30,7 @@ const windowControlStore = useWindowControlStore()
const resourcesStore = useResourcesStore()
const mcpStore = useMcpStore()
const { getPosition } = useTauriWindow()
const { mouseX, mouseY } = useRdevMouse()
const { logicalMouseX, logicalMouseY } = useRdevMouse()
const { listen } = useTauriEvent<AiriTamagotchiEvents>()
const { invoke } = useTauriCore()
@@ -55,7 +55,7 @@ watch(shouldShowSetup, () => {
}, { immediate: true })
// Handle mouse pass-through based on WebGL pixel alpha.
watchThrottled([mouseX, mouseY], ([x, y]) => {
watchThrottled([logicalMouseX, logicalMouseY], ([x, y]) => {
requestAnimationFrame(() => {
const canvas = widgetStageRef.value?.canvasElement()
if (!canvas)