返回 DeepSeek-Reasonix
pageInput.ts
根目录 / desktop / electron / src / main / browser / pageInput.ts
1 /// <reference lib="dom" />
2
3 // DOM geometry can already reflect a resize while Chromium is still routing
4 // input using the preceding compositor frame. Observe two animation frames
5 // before dispatch, and reject rather than silently retarget a moving point.
6 export function pageInputReady(input: { x: number; y: number }): Promise<boolean> {
7 const target = document.elementFromPoint(input.x, input.y);
8 const sample = () => {
9 const rect = target?.getBoundingClientRect();
10 return JSON.stringify([innerWidth, innerHeight, scrollX, scrollY, rect?.x, rect?.y, rect?.width, rect?.height]);
11 };
12 const initial = sample();
13 return new Promise(resolve => {
14 let frame = 0, remaining = 2, finished = false;
15 const finish = (ready: boolean) => {
16 if (finished) return;
17 finished = true;
18 clearTimeout(timer);
19 cancelAnimationFrame(frame);
20 resolve(ready);
21 };
22 const timer = setTimeout(() => finish(false), 500);
23 const observe = () => {
24 if (sample() !== initial || document.elementFromPoint(input.x, input.y) !== target || target && !target.isConnected) { finish(false); return; }
25 if (--remaining === 0) { finish(true); return; }
26 frame = requestAnimationFrame(observe);
27 };
28 frame = requestAnimationFrame(observe);
29 });
30 }
31
32 export function pageInputFrame(input: { x: number; y: number }) {
33 let hit = document.elementFromPoint(input.x, input.y);
34 while (hit?.shadowRoot) {
35 const nested = hit.shadowRoot.elementFromPoint(input.x, input.y);
36 if (!nested || nested === hit) break;
37 hit = nested;
38 }
39 if (!(hit instanceof HTMLIFrameElement || hit instanceof HTMLFrameElement)) return null;
40 const transform = getComputedStyle(hit).transform;
41 if (transform && transform !== "none") {
42 const matrix = new DOMMatrixReadOnly(transform);
43 if (matrix.b !== 0 || matrix.c !== 0 || matrix.a <= 0 || matrix.d <= 0) return { unsupported: true };
44 }
45 const rect = hit.getBoundingClientRect();
46 const index = Array.from({ length: window.length }, (_, i) => i).find(i => window.frames[i] === hit.contentWindow);
47 if (index === undefined || !rect.width || !rect.height) return null;
48 const x = (input.x - rect.x) * hit.offsetWidth / rect.width - hit.clientLeft;
49 const y = (input.y - rect.y) * hit.offsetHeight / rect.height - hit.clientTop;
50 if (x < 0 || y < 0 || x >= hit.clientWidth || y >= hit.clientHeight) return null;
51 return { index, x, y };
52 }
53
53 lines TYPESCRIPT