mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-26 01:34:51 +08:00
fix(tray): refresh DPI coordinates after cross-monitor show (#8595)
This commit is contained in:
1 parent
91ab270e2a
commit
74cf8e6f0b
2 files changed
+72
-2
No files matched your search
@@ -485,9 +485,17 @@ export function TrayPanel() {
|
||||
|
||||
useEffect(() => {
|
||||
const update = () => setPixelRatio(window.devicePixelRatio || 1);
|
||||
// 跨屏时 DPR 可能晚于显示事件更新,固定画布也不一定触发 resize。
|
||||
// 每次 DPR 变化后重新订阅,才能继续检测下一次跨屏或 WebView 缩放。
|
||||
const media = window.matchMedia?.(`(resolution: ${pixelRatio}dppx)`);
|
||||
media?.addEventListener("change", update);
|
||||
window.addEventListener("resize", update);
|
||||
return () => window.removeEventListener("resize", update);
|
||||
}, []);
|
||||
update();
|
||||
return () => {
|
||||
media?.removeEventListener("change", update);
|
||||
window.removeEventListener("resize", update);
|
||||
};
|
||||
}, [pixelRatio]);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
|
||||
@@ -153,6 +153,7 @@ describe("TrayPanel window layout", () => {
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
window.localStorage.removeItem("cc-switch-tray-tab");
|
||||
delete document.documentElement.dataset.glass;
|
||||
delete document.documentElement.dataset.layout;
|
||||
@@ -390,6 +391,67 @@ describe("TrayPanel window layout", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
[1, 1.5, 2],
|
||||
[2, 1.5, 1],
|
||||
])(
|
||||
"updates clipping without resize when DPR arrives after show (%s → %s → %s)",
|
||||
async (initialScale, secondScale, thirdScale) => {
|
||||
const ratio = vi.spyOn(window, "devicePixelRatio", "get");
|
||||
ratio.mockReturnValue(initialScale);
|
||||
const mediaQueries: Array<
|
||||
EventTarget & { media: string; matches: boolean }
|
||||
> = [];
|
||||
vi.stubGlobal("matchMedia", (query: string) => {
|
||||
const media = Object.assign(new EventTarget(), {
|
||||
media: query,
|
||||
matches: query === `(resolution: ${window.devicePixelRatio}dppx)`,
|
||||
});
|
||||
mediaQueries.push(media);
|
||||
return media as MediaQueryList;
|
||||
});
|
||||
const { container } = await openPanel({
|
||||
...windows,
|
||||
scaleFactor: initialScale,
|
||||
});
|
||||
const main = container.querySelector<HTMLElement>(".tp-card")!;
|
||||
|
||||
for (const [index, scaleFactor] of [secondScale, thirdScale].entries()) {
|
||||
const seq = index + 2;
|
||||
// 原生窗口收到布局后才跨屏:显示事件仍读到旧屏的 DPR。
|
||||
await act(async () => {
|
||||
emitTauriEvent(SHOW_EVENT, { ...windows, seq, scaleFactor });
|
||||
});
|
||||
await paint();
|
||||
const calls = vi.mocked(trayPanelApi.layout).mock.calls.length;
|
||||
|
||||
// 画布尺寸不变,没有 resize;只分发匹配状态确实改变的媒体查询事件。
|
||||
await act(async () => {
|
||||
ratio.mockReturnValue(scaleFactor);
|
||||
for (const media of [...mediaQueries]) {
|
||||
const matches = media.media === `(resolution: ${scaleFactor}dppx)`;
|
||||
if (media.matches !== matches) {
|
||||
media.matches = matches;
|
||||
media.dispatchEvent(new Event("change"));
|
||||
}
|
||||
}
|
||||
});
|
||||
await paint();
|
||||
|
||||
expect(main).toHaveStyle({ width: "320px", maxHeight: "620px" });
|
||||
expect(trayPanelApi.layout).toHaveBeenCalledTimes(calls + 1);
|
||||
expect(trayPanelApi.layout).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
seq,
|
||||
width: 620,
|
||||
height: 760,
|
||||
cards: [{ x: 300, y: 440, width: 320, height: 320 }],
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it("limits both cards to the available height on small scaled displays", async () => {
|
||||
const { container } = await openPanel({ ...windows, boundsTop: -180 });
|
||||
fireEvent.click(
|
||||
|
||||
Reference in new issue
Block a user