Add back red circle to windows
This commit is contained in:
+22
-10
@@ -1706,20 +1706,32 @@ public static class SFHook {
|
|||||||
* scaled away from 100% and on secondary monitors.
|
* scaled away from 100% and on secondary monitors.
|
||||||
*/
|
*/
|
||||||
osPointToDip(osPoint) {
|
osPointToDip(osPoint) {
|
||||||
if (this.screen && typeof this.screen.screenToDipPoint === 'function') {
|
let geometryDip = null;
|
||||||
try {
|
|
||||||
const dip = this.screen.screenToDipPoint(osPoint);
|
|
||||||
if (dip && Number.isFinite(dip.x) && Number.isFinite(dip.y)) return dip;
|
|
||||||
} catch { /* fall through to manual conversion */ }
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const displays = this.screen && typeof this.screen.getAllDisplays === 'function'
|
const displays = this.screen && typeof this.screen.getAllDisplays === 'function'
|
||||||
? this.screen.getAllDisplays()
|
? this.screen.getAllDisplays()
|
||||||
: [];
|
: [];
|
||||||
const dip = physicalToDip(osPoint, displays);
|
geometryDip = physicalToDip(osPoint, displays);
|
||||||
if (dip) return dip;
|
} catch {
|
||||||
} catch { /* no display geometry available */ }
|
geometryDip = null;
|
||||||
return osPoint;
|
}
|
||||||
|
if (this.screen && typeof this.screen.screenToDipPoint === 'function') {
|
||||||
|
try {
|
||||||
|
const dip = this.screen.screenToDipPoint(osPoint);
|
||||||
|
if (dip && Number.isFinite(dip.x) && Number.isFinite(dip.y)) {
|
||||||
|
if (!geometryDip) return dip;
|
||||||
|
const offByX = Math.abs(dip.x - geometryDip.x);
|
||||||
|
const offByY = Math.abs(dip.y - geometryDip.y);
|
||||||
|
// Some Windows/Electron combinations have been observed to return a
|
||||||
|
// raw physical point here. That keeps the click marker off-screen on
|
||||||
|
// scaled displays, so trust the geometry path when the two disagree
|
||||||
|
// by more than a tiny rounding margin.
|
||||||
|
if (offByX <= 1 && offByY <= 1) return dip;
|
||||||
|
return geometryDip;
|
||||||
|
}
|
||||||
|
} catch { /* fall through to manual conversion */ }
|
||||||
|
}
|
||||||
|
return geometryDip || osPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -736,6 +736,27 @@ test('hook coordinates are converted physical → DIP via screenToDipPoint when
|
|||||||
assert.deepEqual(seen, [{ x: 640, y: 320 }]);
|
assert.deepEqual(seen, [{ x: 640, y: 320 }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('bogus Windows screenToDipPoint results fall back to display geometry', () => {
|
||||||
|
const service = makeService({
|
||||||
|
screenApi: {
|
||||||
|
screenToDipPoint: (p) => ({ x: p.x, y: p.y }), // raw physical point: wrong on scaled displays
|
||||||
|
getAllDisplays: () => [
|
||||||
|
{ id: 1, scaleFactor: 2, bounds: { x: 0, y: 0, width: 1440, height: 900 } },
|
||||||
|
],
|
||||||
|
getCursorScreenPoint: () => { throw new Error('must not fall back to a cursor read'); },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
service.session = { guideId: 'guide-dip-fallback', paused: false, count: 0, intervalSec: 0 };
|
||||||
|
const seen = [];
|
||||||
|
service.enqueueClickCapture = (clickPos) => {
|
||||||
|
seen.push(clickPos);
|
||||||
|
};
|
||||||
|
|
||||||
|
service.onOsClick(1770000000000, { x: 1500, y: 900 }, 'left');
|
||||||
|
|
||||||
|
assert.deepEqual(seen, [{ x: 750, y: 450 }]);
|
||||||
|
});
|
||||||
|
|
||||||
test('without screenToDipPoint, coordinates convert via display geometry (Linux/X11)', () => {
|
test('without screenToDipPoint, coordinates convert via display geometry (Linux/X11)', () => {
|
||||||
const service = makeService({
|
const service = makeService({
|
||||||
screenApi: {
|
screenApi: {
|
||||||
|
|||||||
Reference in New Issue
Block a user