fix(linux): allow dragging HUD overlay on Wayland via native OS drag

BrowserWindow.setBounds() with x/y is silently ignored on Wayland (the
compositor owns window placement), so the IPC-driven HUD drag never
moved the window \u2014 it stayed put even though pointer events fired and
the cursor changed to grabbing.

Mark the drag handle as -webkit-app-region: drag on Linux (only in the
IPC/overlay mode; webcam-preview mode still uses the in-window CSS
transform) so the OS performs a real xdg_toplevel.move. Mirror the
resulting bounds into hudUserPosition via the window 'moved' event so
commit a78f7d4's in-place resize behavior keeps working on Linux.
This commit is contained in:
Uri
2026-04-23 14:52:40 +03:00
parent 9f3e234f85
commit 8c7c57aa1c
2 changed files with 33 additions and 1 deletions
+22
View File
@@ -301,6 +301,16 @@ let hudDragFixedSize: { width: number; height: number } | null = null;
ipcMain.on("hud-overlay-drag", (_event, phase: string, screenX: number, screenY: number) => {
if (!hudOverlayWindow || hudOverlayWindow.isDestroyed()) return;
// On Linux the compositor (especially Wayland) refuses programmatic window
// placement, so BrowserWindow.setBounds() with x/y is silently ignored and
// the HUD appears "stuck". The renderer marks the drag handle as
// -webkit-app-region: drag on Linux, letting the OS move the window for us.
// The resulting position is captured by the win.on("moved", ...) listener
// below so `hudUserPosition` stays in sync for in-place resize.
if (process.platform === "linux") {
return;
}
if (phase === "start") {
const bounds = hudOverlayWindow.getBounds();
hudDragOffset = { x: screenX - bounds.x, y: screenY - bounds.y };
@@ -511,6 +521,18 @@ export function createHudOverlayWindow(): BrowserWindow {
hudOverlayWindow = win;
// On Linux the HUD is dragged by the OS via -webkit-app-region (Wayland
// forbids client-side positioning). Mirror the resulting bounds into
// hudUserPosition so subsequent expand/collapse resizes stay in place
// instead of snapping back to the default centered spot.
if (process.platform === "linux") {
win.on("moved", () => {
if (win.isDestroyed()) return;
const { x, y } = win.getBounds();
hudUserPosition = { x, y };
});
}
// Reset the user's saved HUD position when displays change so the bar
// doesn't end up stranded off-screen after a monitor is disconnected.
const screen = getScreen();
+11 -1
View File
@@ -1587,7 +1587,17 @@ export function LaunchWindow() {
className={`${styles.bar} mb-2`}
>
<div
className="flex items-center px-0.5 cursor-grab active:cursor-grabbing"
// On Linux (especially Wayland) the compositor owns window
// placement, so BrowserWindow.setBounds() is silently ignored.
// Fall back to a native OS drag via -webkit-app-region on the
// handle. We still need JS pointer handlers in webcam-preview
// mode (which translates via CSS inside the window), so only
// mark the handle as a native drag region for the IPC path.
className={`flex items-center px-0.5 cursor-grab active:cursor-grabbing ${
platform === "linux" && !showRecordingWebcamPreview
? styles.electronDrag
: ""
}`}
onPointerDown={handleHudBarPointerDown}
onPointerMove={handleHudBarPointerMove}
onPointerUp={handleHudBarPointerUp}