дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-08 19:02:17 +02:00
62 рядки
2.4 KiB
TypeScript
62 рядки
2.4 KiB
TypeScript
/** Focus routing between tool windows and the editor area. */
|
|
import { setContext, useContextKeys } from "@/platform/context";
|
|
import { maybeEditorService } from "./contributions";
|
|
|
|
export const EDITOR_AREA_SELECTOR = "[data-editor-area]";
|
|
|
|
/** Moves focus to the active editor (or the editor area when none is open). */
|
|
export function focusEditor() {
|
|
const service = maybeEditorService();
|
|
if (service?.focus) {
|
|
service.focus();
|
|
return;
|
|
}
|
|
if (typeof document === "undefined") return;
|
|
const area = document.querySelector<HTMLElement>(EDITOR_AREA_SELECTOR);
|
|
const target = area?.querySelector<HTMLElement>(".cm-content, [data-editor-focus]") ?? area;
|
|
target?.focus({ preventScroll: true });
|
|
}
|
|
|
|
/**
|
|
* Tracks which workbench part holds focus and publishes `toolWindowFocus`,
|
|
* `activeToolWindow` and `editorAreaFocus`. Returns an uninstaller.
|
|
*/
|
|
export function installFocusTracking(onToolWindowFocus: (id: string | null) => void): () => void {
|
|
const onFocusIn = (e: FocusEvent) => {
|
|
const el = e.target as Element | null;
|
|
const tw = el?.closest?.("[data-toolwindow]");
|
|
onToolWindowFocus(tw?.getAttribute("data-toolwindow") ?? null);
|
|
setContext("editorAreaFocus", !!el?.closest?.(EDITOR_AREA_SELECTOR));
|
|
};
|
|
const onFocusOut = (e: FocusEvent) => {
|
|
if (e.relatedTarget) return;
|
|
// Focus left to nowhere (window blur keeps document.activeElement).
|
|
queueMicrotask(() => {
|
|
if (document.activeElement && document.activeElement !== document.body) return;
|
|
onToolWindowFocus(null);
|
|
setContext("editorAreaFocus", false);
|
|
});
|
|
};
|
|
document.addEventListener("focusin", onFocusIn);
|
|
document.addEventListener("focusout", onFocusOut);
|
|
// IDEA: closing the last popup / menu / dialog never leaves focus nowhere.
|
|
let popupOpen = !!useContextKeys.getState().popupOpen;
|
|
let refocus: ReturnType<typeof setTimeout> | undefined;
|
|
const unsubPopups = useContextKeys.subscribe((ctx) => {
|
|
const open = !!ctx.popupOpen;
|
|
if (open === popupOpen) return;
|
|
popupOpen = open;
|
|
clearTimeout(refocus);
|
|
if (open) return;
|
|
refocus = setTimeout(() => {
|
|
if (!popupOpen && (!document.activeElement || document.activeElement === document.body)) focusEditor();
|
|
});
|
|
});
|
|
return () => {
|
|
clearTimeout(refocus);
|
|
unsubPopups();
|
|
document.removeEventListener("focusin", onFocusIn);
|
|
document.removeEventListener("focusout", onFocusOut);
|
|
};
|
|
}
|