fix(electrobun): X11 XMoveResizeWindow bypass for resize (no GTK involvement)
begin_resize_drag + XUngrabPointer still fails because GTK's layout cycle re-asserts WebView preferred size, fighting the WM resize. New approach: JS mousemove → XMoveResizeWindow via libX11.so.6 FFI. Completely bypasses GTK size negotiation. GTK only receives ConfigureNotify after the X server has already resized the window. Added: x11SetFrame() using gdk_x11_display_get_xdisplay + gdk_x11_window_get_xid + XMoveResizeWindow.
This commit is contained in:
parent
058ae563d5
commit
0e6408a447
3 changed files with 98 additions and 10 deletions
|
|
@ -27,6 +27,7 @@ function getX11() {
|
|||
x11 = dlopen("libX11.so.6", {
|
||||
XUngrabPointer: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i32 },
|
||||
XFlush: { args: [FFIType.ptr], returns: FFIType.i32 },
|
||||
XMoveResizeWindow: { args: [FFIType.ptr, FFIType.u64, FFIType.i32, FFIType.i32, FFIType.u32, FFIType.u32], returns: FFIType.i32 },
|
||||
});
|
||||
return x11;
|
||||
} catch { return null; }
|
||||
|
|
@ -38,6 +39,7 @@ function getGdk() {
|
|||
gdk3 = dlopen("libgdk-3.so.0", {
|
||||
gdk_display_get_default: { args: [], returns: FFIType.ptr },
|
||||
gdk_x11_display_get_xdisplay: { args: [FFIType.ptr], returns: FFIType.ptr },
|
||||
gdk_x11_window_get_xid: { args: [FFIType.ptr], returns: FFIType.u64 },
|
||||
});
|
||||
return gdk3;
|
||||
} catch { return null; }
|
||||
|
|
@ -151,6 +153,11 @@ function getGtk() {
|
|||
args: [FFIType.ptr],
|
||||
returns: FFIType.void,
|
||||
},
|
||||
// Get GdkWindow from GtkWidget (needed for X11 window ID)
|
||||
gtk_widget_get_window: {
|
||||
args: [FFIType.ptr],
|
||||
returns: FFIType.ptr,
|
||||
},
|
||||
// Sensitivity (disable input processing on widget)
|
||||
gtk_widget_set_sensitive: {
|
||||
args: [FFIType.ptr, FFIType.bool],
|
||||
|
|
@ -266,6 +273,42 @@ function forceSmallMinSize(lib: NonNullable<typeof gtk3>, windowPtr: any) {
|
|||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Set window frame directly via X11, BYPASSING GTK's size negotiation.
|
||||
* GTK receives ConfigureNotify after the fact and adjusts.
|
||||
* This prevents the WebView's preferred size from fighting the resize.
|
||||
*/
|
||||
export function x11SetFrame(
|
||||
windowPtr: number | bigint,
|
||||
x: number, y: number, width: number, height: number,
|
||||
): boolean {
|
||||
const gtkLib = getGtk();
|
||||
const gdkLib = getGdk();
|
||||
const x11Lib = getX11();
|
||||
if (!gtkLib || !gdkLib || !x11Lib) return false;
|
||||
try {
|
||||
const gdkDisplay = gdkLib.symbols.gdk_display_get_default();
|
||||
if (!gdkDisplay) return false;
|
||||
const xDisplay = gdkLib.symbols.gdk_x11_display_get_xdisplay(gdkDisplay);
|
||||
if (!xDisplay) return false;
|
||||
const gdkWindow = gtkLib.symbols.gtk_widget_get_window(windowPtr as any);
|
||||
if (!gdkWindow) return false;
|
||||
const xid = gdkLib.symbols.gdk_x11_window_get_xid(gdkWindow);
|
||||
if (!xid) return false;
|
||||
x11Lib.symbols.XMoveResizeWindow(
|
||||
xDisplay, xid,
|
||||
Math.round(x), Math.round(y),
|
||||
Math.max(400, Math.round(width)),
|
||||
Math.max(300, Math.round(height)),
|
||||
);
|
||||
x11Lib.symbols.XFlush(xDisplay);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error("[gtk-window] x11SetFrame failed:", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate resize to the window manager.
|
||||
* Releases X11 grabs first (SDL2 pattern) so WM can take the pointer.
|
||||
|
|
|
|||
|
|
@ -161,6 +161,13 @@ const rpc = BrowserView.defineRPC<PtyRPCSchema>({
|
|||
return { ok };
|
||||
} catch (err) { console.error("[window.gtkSetFrame]", err); return { ok: false }; }
|
||||
},
|
||||
"window.x11SetFrame": ({ x, y, width, height }: { x: number; y: number; width: number; height: number }) => {
|
||||
try {
|
||||
const { x11SetFrame } = require("./gtk-window.ts");
|
||||
const ok = x11SetFrame((mainWindow as any).ptr, x, y, width, height);
|
||||
return { ok };
|
||||
} catch (err) { console.error("[window.x11SetFrame]", err); return { ok: false }; }
|
||||
},
|
||||
},
|
||||
messages: {},
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue