Fix unreliable window resize on Linux with custom resize handles (#77)

This commit is contained in:
Yuri Karamian
2026-06-05 18:27:08 +02:00
parent 71a0b9c0a0
commit 59677577ec
5 changed files with 84 additions and 0 deletions
+5
View File
@@ -1,5 +1,10 @@
node_modules node_modules
# Foreign lockfiles - this project uses pnpm (pnpm-lock.yaml is the only lockfile)
package-lock.json
yarn.lock
bun.lockb
# Output # Output
.output .output
.vercel .vercel
+1
View File
@@ -7,6 +7,7 @@
"core:default", "core:default",
"core:window:default", "core:window:default",
"core:window:allow-start-dragging", "core:window:allow-start-dragging",
"core:window:allow-start-resize-dragging",
"core:window:allow-minimize", "core:window:allow-minimize",
"core:window:allow-toggle-maximize", "core:window:allow-toggle-maximize",
"core:window:allow-close", "core:window:allow-close",
+6
View File
@@ -6075,6 +6075,12 @@
position: relative; position: relative;
} }
/* Inset the scrollbar off the window's right edge so the window resize handle
(ResizeHandles in +layout) has clean space and doesn't swallow the scrollbar. */
.editor-container:not(.mobile) .editor-body {
margin-right: 8px;
}
.editor-body::-webkit-scrollbar { .editor-body::-webkit-scrollbar {
width: 8px; width: 8px;
} }
+69
View File
@@ -0,0 +1,69 @@
<script lang="ts">
import { onMount } from 'svelte';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { isMobile } from '$lib/platform';
type Dir =
| 'North' | 'South' | 'East' | 'West'
| 'NorthEast' | 'NorthWest' | 'SouthEast' | 'SouthWest';
// Resolved only on the client (onMount), so SSR/prerender never calls Tauri APIs.
let appWindow = $state<ReturnType<typeof getCurrentWindow> | null>(null);
let maximized = $state(false);
onMount(() => {
if (isMobile) return;
const win = getCurrentWindow();
appWindow = win;
const refresh = () => win.isMaximized().then((m) => (maximized = m)).catch(() => {});
refresh();
const unlisten = win.onResized(() => refresh());
return () => { unlisten.then((fn) => fn()); };
});
function start(e: MouseEvent, dir: Dir) {
if (e.button !== 0 || !appWindow) return;
e.preventDefault();
appWindow.startResizeDragging(dir);
}
</script>
{#if appWindow && !maximized}
<div class="resize-layer" aria-hidden="true">
<div class="rz rz-n" onmousedown={(e) => start(e, 'North')}></div>
<div class="rz rz-s" onmousedown={(e) => start(e, 'South')}></div>
<div class="rz rz-w" onmousedown={(e) => start(e, 'West')}></div>
<div class="rz rz-e" onmousedown={(e) => start(e, 'East')}></div>
<div class="rz rz-nw" onmousedown={(e) => start(e, 'NorthWest')}></div>
<div class="rz rz-ne" onmousedown={(e) => start(e, 'NorthEast')}></div>
<div class="rz rz-sw" onmousedown={(e) => start(e, 'SouthWest')}></div>
<div class="rz rz-se" onmousedown={(e) => start(e, 'SouthEast')}></div>
</div>
{/if}
<style>
/* Transparent overlay; only the strips capture events, the rest passes through. */
.resize-layer {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 99999;
}
.rz {
position: fixed;
pointer-events: auto;
}
/* Edges, inset by the corner size so corners win at the corners. */
.rz-n { top: 0; left: 14px; right: 14px; height: 6px; cursor: ns-resize; }
.rz-s { bottom: 0; left: 14px; right: 14px; height: 6px; cursor: ns-resize; }
.rz-w { left: 0; top: 14px; bottom: 14px; width: 6px; cursor: ew-resize; }
.rz-e { right: 0; top: 14px; bottom: 14px; width: 6px; cursor: ew-resize; }
/* Corners: larger, reliable grab targets. */
.rz-nw { top: 0; left: 0; width: 14px; height: 14px; cursor: nwse-resize; }
.rz-ne { top: 0; right: 0; width: 14px; height: 14px; cursor: nesw-resize; }
.rz-sw { bottom: 0; left: 0; width: 14px; height: 14px; cursor: nesw-resize; }
.rz-se { bottom: 0; right: 0; width: 14px; height: 14px; cursor: nwse-resize; }
</style>
+3
View File
@@ -4,6 +4,7 @@
import { theme, appConfig, activeNote, activeNotePath, installType, checkForUpdate, checkForUpdateMobile } from '$lib/stores/app'; import { theme, appConfig, activeNote, activeNotePath, installType, checkForUpdate, checkForUpdateMobile } from '$lib/stores/app';
import { openFile, openUrl, readNote, getInstallType } from '$lib/api'; import { openFile, openUrl, readNote, getInstallType } from '$lib/api';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import ResizeHandles from '$lib/components/ResizeHandles.svelte';
let { children } = $props(); let { children } = $props();
@@ -194,3 +195,5 @@
</svelte:head> </svelte:head>
{@render children()} {@render children()}
<ResizeHandles />