diff --git a/ui-electrobun/src/bun/gtk-window.ts b/ui-electrobun/src/bun/gtk-window.ts index b418542..7a4b989 100644 --- a/ui-electrobun/src/bun/gtk-window.ts +++ b/ui-electrobun/src/bun/gtk-window.ts @@ -49,6 +49,14 @@ function getGtk() { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.i32], returns: FFIType.void, }, + gtk_window_resize: { + args: [FFIType.ptr, FFIType.i32, FFIType.i32], + returns: FFIType.void, + }, + gtk_window_move: { + args: [FFIType.ptr, FFIType.i32, FFIType.i32], + returns: FFIType.void, + }, // Container traversal gtk_bin_get_child: { args: [FFIType.ptr], @@ -247,6 +255,28 @@ export function beginMoveDrag( } } +/** + * Direct GTK resize — bypasses Electrobun's setSize which respects WebView min-size. + * Clears min-size tree first, then calls gtk_window_resize + gtk_window_move. + */ +export function gtkSetFrame( + windowPtr: number | bigint, + x: number, y: number, width: number, height: number, +) { + const lib = getGtk(); + if (!lib) return false; + try { + // Clear min-size on every frame update during resize + clearMinSizeTree(lib, windowPtr as any); + lib.symbols.gtk_window_resize(windowPtr as any, Math.max(400, Math.round(width)), Math.max(300, Math.round(height))); + lib.symbols.gtk_window_move(windowPtr as any, Math.round(x), Math.round(y)); + return true; + } catch (err) { + console.error("[gtk-window] gtkSetFrame failed:", err); + return false; + } +} + // Edge string → GDK_EDGE mapping const EDGE_MAP: Record = { n: GDK_EDGE.N, s: GDK_EDGE.S, e: GDK_EDGE.E, w: GDK_EDGE.W, diff --git a/ui-electrobun/src/bun/index.ts b/ui-electrobun/src/bun/index.ts index 441e4e3..c8ff6bd 100644 --- a/ui-electrobun/src/bun/index.ts +++ b/ui-electrobun/src/bun/index.ts @@ -154,6 +154,13 @@ const rpc = BrowserView.defineRPC({ return { ok: true }; } catch (err) { console.error("[window.clearMinSize]", err); return { ok: false }; } }, + "window.gtkSetFrame": ({ x, y, width, height }: { x: number; y: number; width: number; height: number }) => { + try { + const { gtkSetFrame } = require("./gtk-window.ts"); + const ok = gtkSetFrame((mainWindow as any).ptr, x, y, width, height); + return { ok }; + } catch (err) { console.error("[window.gtkSetFrame]", err); return { ok: false }; } + }, }, messages: {}, }, diff --git a/ui-electrobun/src/mainview/App.svelte b/ui-electrobun/src/mainview/App.svelte index daba3f5..787b36b 100644 --- a/ui-electrobun/src/mainview/App.svelte +++ b/ui-electrobun/src/mainview/App.svelte @@ -148,7 +148,8 @@ if (resizeEdge.includes('s')) height = Math.max(MIN_H, height + dy); if (resizeEdge.includes('n')) { const nh = Math.max(MIN_H, height - dy); y += height - nh; height = nh; } - appRpc.request['window.setFrame']({ x: Math.round(x), y: Math.round(y), width: Math.round(width), height: Math.round(height) }).catch(() => {}); + // Use GTK FFI directly — bypasses Electrobun's setSize which respects WebView min-size + appRpc.request['window.gtkSetFrame']({ x: Math.round(x), y: Math.round(y), width: Math.round(width), height: Math.round(height) }).catch(() => {}); } function onResizeEnd() {