From c4658cff889333cbffcad6dc42522d863e556636 Mon Sep 17 00:00:00 2001 From: sgt57 <198590103+sgt57@users.noreply.github.com> Date: Sat, 4 Jul 2026 11:16:08 +0800 Subject: [PATCH] feat: add window resize handles on linux (#7319) --- src-tauri/capabilities/migrated.json | 1 + src/assets/styles/layout.scss | 86 +++++++++++++++++++++ src/components/layout/window-controller.tsx | 60 +++++++++++++- src/pages/_layout.tsx | 9 ++- 4 files changed, 153 insertions(+), 3 deletions(-) diff --git a/src-tauri/capabilities/migrated.json b/src-tauri/capabilities/migrated.json index 67dc15cf3..097c622fb 100644 --- a/src-tauri/capabilities/migrated.json +++ b/src-tauri/capabilities/migrated.json @@ -54,6 +54,7 @@ "core:window:allow-set-cursor-position", "core:window:allow-set-ignore-cursor-events", "core:window:allow-start-dragging", + "core:window:allow-start-resize-dragging", "core:window:allow-maximize", "core:window:allow-toggle-maximize", "core:window:allow-unmaximize", diff --git a/src/assets/styles/layout.scss b/src/assets/styles/layout.scss index 48a47cc99..6d077fde2 100644 --- a/src/assets/styles/layout.scss +++ b/src/assets/styles/layout.scss @@ -108,6 +108,92 @@ } } +.window-resize-handles { + --resize-edge-size: 6px; + --resize-corner-size: 12px; + + position: fixed; + inset: 0; + z-index: 10000; + pointer-events: none; + + .window-resize-handle { + position: absolute; + pointer-events: auto; + touch-action: none; + + &--north, + &--south { + right: var(--resize-corner-size); + left: var(--resize-corner-size); + height: var(--resize-edge-size); + cursor: ns-resize; + } + + &--north { + top: 0; + } + + &--south { + bottom: 0; + } + + &--east, + &--west { + top: var(--resize-corner-size); + bottom: var(--resize-corner-size); + width: var(--resize-edge-size); + cursor: ew-resize; + } + + &--east { + right: 0; + } + + &--west { + left: 0; + } + + &--north-east, + &--north-west, + &--south-east, + &--south-west { + width: var(--resize-corner-size); + height: var(--resize-corner-size); + } + + &--north-east, + &--south-west { + cursor: nesw-resize; + } + + &--north-west, + &--south-east { + cursor: nwse-resize; + } + + &--north-east, + &--north-west { + top: 0; + } + + &--south-east, + &--south-west { + bottom: 0; + } + + &--north-east, + &--south-east { + right: 0; + } + + &--north-west, + &--south-west { + left: 0; + } + } +} + .linux, .windows, .unknown { diff --git a/src/components/layout/window-controller.tsx b/src/components/layout/window-controller.tsx index 2f8b1f6b7..1df4b5f65 100644 --- a/src/components/layout/window-controller.tsx +++ b/src/components/layout/window-controller.tsx @@ -1,10 +1,68 @@ import { Close, CropSquare, FilterNone, Minimize } from '@mui/icons-material' import { Box, IconButton } from '@mui/material' -import { forwardRef, useImperativeHandle } from 'react' +import { + forwardRef, + type PointerEvent, + useCallback, + useImperativeHandle, +} from 'react' import { useWindowControls } from '@/hooks/use-window' import getSystem from '@/utils/get-system' +const RESIZE_HANDLES = [ + { direction: 'North', position: 'north' }, + { direction: 'NorthEast', position: 'north-east' }, + { direction: 'East', position: 'east' }, + { direction: 'SouthEast', position: 'south-east' }, + { direction: 'South', position: 'south' }, + { direction: 'SouthWest', position: 'south-west' }, + { direction: 'West', position: 'west' }, + { direction: 'NorthWest', position: 'north-west' }, +] as const + +export const WindowResizeHandles = () => { + const { currentWindow, maximized } = useWindowControls() + + const startResizeDragging = useCallback( + (event: PointerEvent) => { + if (event.button !== 0) return + + event.preventDefault() + const direction = event.currentTarget.dataset.resizeDirection + const handle = RESIZE_HANDLES.find((item) => item.direction === direction) + + if (handle) { + void currentWindow + .startResizeDragging(handle.direction) + .catch((error) => + console.warn('[WindowResizeHandles] 调整窗口大小失败:', error), + ) + } + }, + [currentWindow], + ) + + if (getSystem() !== 'linux' || maximized) return null + + return ( +