Skip to content

Commit f4a5828

Browse files
authored
fix: Implement DPI Scaling Support (#601)
1 parent 400103c commit f4a5828

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

apps/stage-tamagotchi/src/composables/tauri.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,35 @@ export function useTauriDpi() {
216216
return new imported.LogicalPosition(x, y)
217217
}
218218

219+
async function getScaleFactor(): Promise<number> {
220+
const imported = await tauriDpiApi.value
221+
if (!imported) {
222+
throw new Error('Tauri DPI API not available')
223+
}
224+
225+
const monitor = await imported.currentMonitor()
226+
return monitor?.scaleFactor ?? 1
227+
}
228+
229+
function convertPhysicalToLogical(physicalX: number, physicalY: number, scaleFactor: number): { x: number, y: number } {
230+
return {
231+
x: physicalX / scaleFactor,
232+
y: physicalY / scaleFactor,
233+
}
234+
}
235+
236+
function convertLogicalToPhysical(logicalX: number, logicalY: number, scaleFactor: number): { x: number, y: number } {
237+
return {
238+
x: logicalX * scaleFactor,
239+
y: logicalY * scaleFactor,
240+
}
241+
}
242+
219243
return {
220244
createLogicalPosition,
245+
getScaleFactor,
246+
convertPhysicalToLogical,
247+
convertLogicalToPhysical,
221248
}
222249
}
223250

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,63 @@
11
import type { AiriTamagotchiEvents } from './tauri'
22

33
import { createSharedComposable } from '@vueuse/core'
4-
import { ref } from 'vue'
4+
import { ref, watch } from 'vue'
55

6-
import { useTauriEvent } from './tauri'
6+
import { useTauriDpi, useTauriEvent } from './tauri'
77

88
export const useRdevMouse = createSharedComposable(() => {
99
const mouseX = ref(0)
1010
const mouseY = ref(0)
11+
const logicalMouseX = ref(0)
12+
const logicalMouseY = ref(0)
13+
const scaleFactor = ref(1)
1114

1215
const { listen } = useTauriEvent<AiriTamagotchiEvents>()
16+
const { getScaleFactor } = useTauriDpi()
17+
18+
// Update scale factor when DPI changes
19+
async function updateScaleFactor() {
20+
try {
21+
const newScaleFactor = await getScaleFactor()
22+
scaleFactor.value = newScaleFactor
23+
}
24+
catch (error) {
25+
console.warn('Failed to get scale factor, using default 1.0:', error)
26+
scaleFactor.value = 1
27+
}
28+
}
29+
30+
// Convert physical coordinates to logical coordinates
31+
watch([mouseX, mouseY, scaleFactor], ([x, y, scale]) => {
32+
const logical = convertPhysicalToLogical(x, y, scale)
33+
logicalMouseX.value = logical.x
34+
logicalMouseY.value = logical.y
35+
})
1336

1437
async function setup() {
38+
await updateScaleFactor()
39+
1540
await listen('tauri-plugins:tauri-plugin-rdev:mousemove', (event) => {
1641
if (event.payload.event_type.MouseMove) {
1742
const { x, y } = event.payload.event_type.MouseMove
1843
mouseX.value = x
1944
mouseY.value = y
2045
}
2146
})
47+
48+
// Listen for scale changes (when window moves between monitors with different DPI)
49+
await listen('tauri://scale-change', () => {
50+
updateScaleFactor()
51+
})
2252
}
2353

2454
setup()
2555

2656
return {
2757
mouseX,
2858
mouseY,
59+
logicalMouseX,
60+
logicalMouseY,
61+
scaleFactor,
2962
}
3063
})

apps/stage-tamagotchi/src/pages/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const windowControlStore = useWindowControlStore()
3030
const resourcesStore = useResourcesStore()
3131
const mcpStore = useMcpStore()
3232
const { getPosition } = useTauriWindow()
33-
const { mouseX, mouseY } = useRdevMouse()
33+
const { logicalMouseX, logicalMouseY } = useRdevMouse()
3434
3535
const { listen } = useTauriEvent<AiriTamagotchiEvents>()
3636
const { invoke } = useTauriCore()
@@ -55,7 +55,7 @@ watch(shouldShowSetup, () => {
5555
}, { immediate: true })
5656
5757
// Handle mouse pass-through based on WebGL pixel alpha.
58-
watchThrottled([mouseX, mouseY], ([x, y]) => {
58+
watchThrottled([logicalMouseX, logicalMouseY], ([x, y]) => {
5959
requestAnimationFrame(() => {
6060
const canvas = widgetStageRef.value?.canvasElement()
6161
if (!canvas)

0 commit comments

Comments
 (0)