дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-08 19:02:17 +02:00
fix(workbench): resize handles for the frameless Windows window (#414)
The frameless Windows window has no native resize borders, so it couldn't be resized from its edges. Invisible hit areas along the edges and corners start a native resize drag (minimum size and snapping handled by the system); they're omitted while the window is maximized or full screen. Not verified on a real Windows machine. Refs #410 Co-authored-by: a-rookie-of-C-language <[email protected]>
Цей коміт міститься в:
1 джерело
19b96b60a4
коміт
ce981e4fd6
3 files changed
+145
No files matched your search
@@ -0,0 +1,68 @@
|
||||
/* Invisible resize hit areas hugging the frameless window's edges. */
|
||||
.n,
|
||||
.s,
|
||||
.e,
|
||||
.w,
|
||||
.ne,
|
||||
.nw,
|
||||
.se,
|
||||
.sw {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.n,
|
||||
.s {
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
height: 6px;
|
||||
}
|
||||
.e,
|
||||
.w {
|
||||
top: 8px;
|
||||
bottom: 8px;
|
||||
width: 6px;
|
||||
}
|
||||
.ne,
|
||||
.nw,
|
||||
.se,
|
||||
.sw {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
.n {
|
||||
top: 0;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.s {
|
||||
bottom: 0;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.e {
|
||||
right: 0;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.w {
|
||||
left: 0;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.ne {
|
||||
top: 0;
|
||||
right: 0;
|
||||
cursor: nesw-resize;
|
||||
}
|
||||
.nw {
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
.se {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
.sw {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
cursor: nesw-resize;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Frameless-window resize handles: Windows gives undecorated windows no
|
||||
* resize borders, so the title bar's frameless look leaves the window
|
||||
* stuck at its launch size. Eight invisible hit areas along the edges
|
||||
* start a native resize drag, like any other desktop app.
|
||||
*
|
||||
* macOS renders its own overlay title bar but still provides resize
|
||||
* handles, so nothing is added there.
|
||||
*/
|
||||
import { useEffect, useState } from "react";
|
||||
import { usePlatform } from "@/platform/platformInfo";
|
||||
import { isTauri } from "@/platform/ipc";
|
||||
import styles from "./WindowResizeHandles.module.css";
|
||||
|
||||
type Dir = "East" | "North" | "NorthEast" | "NorthWest" | "South" | "SouthEast" | "SouthWest" | "West";
|
||||
|
||||
const EDGES: { dir: Dir; cls: string }[] = [
|
||||
{ dir: "North", cls: styles.n! },
|
||||
{ dir: "South", cls: styles.s! },
|
||||
{ dir: "East", cls: styles.e! },
|
||||
{ dir: "West", cls: styles.w! },
|
||||
{ dir: "NorthEast", cls: styles.ne! },
|
||||
{ dir: "NorthWest", cls: styles.nw! },
|
||||
{ dir: "SouthEast", cls: styles.se! },
|
||||
{ dir: "SouthWest", cls: styles.sw! },
|
||||
];
|
||||
|
||||
async function start(dir: Dir) {
|
||||
const { getCurrentWindow } = await import("@tauri-apps/api/window");
|
||||
await getCurrentWindow().startResizeDragging(dir);
|
||||
}
|
||||
|
||||
export function WindowResizeHandles() {
|
||||
// A frameless window needs them; a decorated one already has native borders.
|
||||
const frameless = usePlatform((s) => s.framelessTitleBar);
|
||||
const enabled = isTauri() && frameless;
|
||||
// A maximized or full-screen window has nothing to resize; the edges belong to the content.
|
||||
const [sized, setSized] = useState(false);
|
||||
useEffect(() => {
|
||||
if (!enabled) return;
|
||||
let disposed = false;
|
||||
let unlisten: (() => void) | undefined;
|
||||
void import("@tauri-apps/api/window").then(async ({ getCurrentWindow }) => {
|
||||
const w = getCurrentWindow();
|
||||
const sync = () =>
|
||||
void Promise.all([w.isMaximized(), w.isFullscreen()]).then(([m, f]) => !disposed && setSized(m || f));
|
||||
sync();
|
||||
const off = await w.onResized(sync);
|
||||
if (disposed) off();
|
||||
else unlisten = off;
|
||||
});
|
||||
return () => {
|
||||
disposed = true;
|
||||
unlisten?.();
|
||||
};
|
||||
}, [enabled]);
|
||||
if (!enabled || sized) return null;
|
||||
return (
|
||||
<>
|
||||
{EDGES.map(({ dir, cls }) => (
|
||||
<div
|
||||
key={dir}
|
||||
className={cls}
|
||||
aria-hidden="true"
|
||||
onMouseDown={(e) => {
|
||||
// Left button only, and not on something interactive that bubbled up.
|
||||
if (e.button !== 0) return;
|
||||
e.preventDefault();
|
||||
void start(dir);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import { TitleBar } from "./TitleBar";
|
||||
import { useApplyTheme } from "./theme";
|
||||
import { ToolWindowLayout } from "./toolwindows/ToolWindows";
|
||||
import { Welcome } from "./Welcome";
|
||||
import { WindowResizeHandles } from "./WindowResizeHandles";
|
||||
import styles from "./Workbench.module.css";
|
||||
|
||||
/** LightEdit: editor tabs only; no tool windows, toolbar widgets or project status items. */
|
||||
@@ -60,6 +61,7 @@ export function Workbench() {
|
||||
<Welcome />
|
||||
)}
|
||||
<OverlayHost />
|
||||
<WindowResizeHandles />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Заблокувати користувача