From 2c88b7abcb28160520d7b3c3b37f804e463b544c Mon Sep 17 00:00:00 2001 From: zach Date: Sun, 4 Oct 2026 18:20:10 +0200 Subject: [PATCH] move picker to main panelwindow to reduce vram usage --- Components/ScreenState.qml | 3 + Drawers/Windows.qml | 21 ++++++- Helpers/AreaPicker.qml | 88 --------------------------- Helpers/Picker.qml | 93 +++++++++++++++++++++-------- Helpers/Picker/AnnotationCanvas.qml | 12 ++-- Helpers/Picker/SelectionHandles.qml | 16 ++++- Modules/Shortcuts.qml | 17 ++++++ Services/ShellState.qml | 7 ++- shell.qml | 4 -- 9 files changed, 133 insertions(+), 128 deletions(-) delete mode 100644 Helpers/AreaPicker.qml diff --git a/Components/ScreenState.qml b/Components/ScreenState.qml index 663dfe1..9885c51 100644 --- a/Components/ScreenState.qml +++ b/Components/ScreenState.qml @@ -34,4 +34,7 @@ PersistentProperties { // Drawing state property color penColor: "white" property int penWidth: 4 + + // Screenshot state + property bool screenshot } diff --git a/Drawers/Windows.qml b/Drawers/Windows.qml index 84b53e5..d4f03ef 100644 --- a/Drawers/Windows.qml +++ b/Drawers/Windows.qml @@ -56,11 +56,10 @@ CustomWindow { property color surfaceColor: Colors.tPalette.m3surface WlrLayershell.exclusionMode: ExclusionMode.Ignore - WlrLayershell.keyboardFocus: screenState.launcher || screenState.settings || screenState.sidebar ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None + WlrLayershell.keyboardFocus: screenState.screenshot ? WlrKeyboardFocus.Exclusive : screenState.launcher || screenState.settings || screenState.sidebar ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top color: "transparent" - contentItem.focus: true - mask: screenState.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions) + mask: screenState.isDrawing || screenState.screenshot ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions) name: "Bar" Behavior on fsTransitionProg { @@ -430,6 +429,22 @@ CustomWindow { } } + LazyLoader { + id: loader + + property bool closing: !root.screenState.screenshot + + onClosingChanged: if (!closing) + activeAsync = true + + Picker { + loader: loader + parent: root.contentItem + screen: root.screen + screenState: root.screenState + } + } + component PanelBg: BlobRect2 { property real deformAmount: 0.15 required property Item panel diff --git a/Helpers/AreaPicker.qml b/Helpers/AreaPicker.qml deleted file mode 100644 index ce15fab..0000000 --- a/Helpers/AreaPicker.qml +++ /dev/null @@ -1,88 +0,0 @@ -pragma ComponentBehavior: Bound - -import Quickshell -import Quickshell.Wayland -import Quickshell.Io -import Quickshell.Hyprland -import ZShell -import qs.Components - -Scope { - LazyLoader { - id: root - - property bool closing - property bool freeze - - Variants { - model: Quickshell.screens - - PanelWindow { - id: win - - required property ShellScreen modelData - - WlrLayershell.exclusionMode: ExclusionMode.Ignore - WlrLayershell.keyboardFocus: root.closing ? WlrKeyboardFocus.None : WlrKeyboardFocus.Exclusive - WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.namespace: "areapicker" - color: "transparent" - mask: root.closing ? empty : null - screen: modelData - - anchors { - bottom: true - left: true - right: true - top: true - } - - Region { - id: empty - - } - - Picker { - loader: root - screen: win.modelData - } - } - } - } - - IpcHandler { - function open(): void { - root.freeze = false; - root.closing = false; - root.activeAsync = true; - } - - function openFreeze(): void { - root.freeze = true; - root.closing = false; - root.activeAsync = true; - } - - target: "picker" - } - - CustomShortcut { - name: "screenshot" - - onPressed: { - root.freeze = false; - root.closing = false; - root.activeAsync = true; - } - } - - CustomShortcut { - name: "screenshotFreeze" - - onPressed: { - root.freeze = true; - root.closing = false; - root.activeAsync = true; - } - } -} diff --git a/Helpers/Picker.qml b/Helpers/Picker.qml index a7683c7..5c3a08d 100755 --- a/Helpers/Picker.qml +++ b/Helpers/Picker.qml @@ -41,6 +41,7 @@ Item { property real rsy: Math.min(sy, ey) readonly property real scaleRatio: Hypr.monitorFor(screen).scale required property ShellScreen screen + required property ScreenState screenState property real sh: Math.abs(sy - ey) readonly property color shadowColor: Hypr.options.decoration.shadow?.color ?? "black" readonly property bool shadowEnabled: Hypr.options.decoration.shadow.enabled @@ -97,10 +98,6 @@ Item { const args = Config.screenshot.mode === "auto" ? ["--rounding", `${rounding}`, "--radius", root.cornerRadius, "--shadow", root.shadowEnabled, "--shadow-blur", `${shadow_blur}`, "--shadow-color", `${r},${g},${b},${a}`, "--shadow-offset-x", root.shadowOffset[0], "--shadow-offset-y", root.shadowOffset[1]] : []; const postCmd = Config.screenshot.enable_pp ? ["zshell-img-tools", "--scale", root.scaleRatio, ...args, "--image"] : null; - overlay.visible = border.visible = false; - handles.visible = false; - toolbar.visible = false; - ZShellIo.saveItem(captureLayer, tmpfile, Qt.rect(Math.ceil(rsx), Math.ceil(rsy), Math.floor(sw), Math.floor(sh)), path => { const finalize = finalPath => { if (copyToClipboard) { @@ -158,7 +155,7 @@ Item { Component.onCompleted: { Hypr.extras.refreshOptions(); - screencopy.active = true; + root.forceActiveFocus(); opacity = 1; @@ -223,13 +220,63 @@ Item { onReleased: root.enterEditMode() } + Connections { + function onClosingChanged(): void { + if (root.loader.closing) + closeAnim.start(); + else { + closeAnim.stop(); + returnAnim.start(); + } + } + + target: root.loader + } + + ParallelAnimation { + id: returnAnim + + Anim { + duration: 300 + property: "opacity" + target: root + to: 1 + } + + Anim { + property: "rsx" + target: root + to: Math.min(root.sx, root.ex) + } + + Anim { + property: "rsy" + target: root + to: Math.min(root.sy, root.ey) + } + + Anim { + property: "sw" + target: root + to: Math.abs(root.sx - root.ex) + } + + Anim { + property: "sh" + target: root + to: Math.abs(root.sy - root.ey) + } + } + SequentialAnimation { id: closeAnim - PropertyAction { - property: "closing" - target: root.loader - value: true + ScriptAction { + script: { + const states = ShellState.allStates(); + for (const s of states) + s.screenshot = false; + } } ParallelAnimation { @@ -271,17 +318,12 @@ Item { anchors.fill: parent - Loader { + ScreencopyView { id: screencopy - active: false anchors.fill: parent - asynchronous: true - - sourceComponent: ScreencopyView { - captureSource: root.screen - paintCursor: false - } + captureSource: root.screen + paintCursor: false } AnnotationCanvas { @@ -309,8 +351,7 @@ Item { color: "white" layer.enabled: true opacity: 0.3 - radius: root.realRounding - visible: screencopy.item?.hasContent ?? false + visible: screencopy.hasContent layer.effect: MultiEffect { maskEnabled: true @@ -347,7 +388,7 @@ Item { implicitHeight: selectionRect.implicitHeight + root.realBorderWidth * 2 implicitWidth: selectionRect.implicitWidth + root.realBorderWidth * 2 radius: root.realRounding > 0 ? root.realRounding + root.realBorderWidth : 0 - visible: screencopy.item?.hasContent ?? false + visible: screencopy.hasContent x: selectionRect.x - root.realBorderWidth y: selectionRect.y - root.realBorderWidth @@ -370,10 +411,14 @@ Item { visible: root.mode === "edit" && root.tool === "move" onBoundsChanged: (x, y, w, h) => { - root.sx = x; - root.sy = y; - root.ex = x + w; - root.ey = y + h; + let nx = Math.max(0, x); + let ny = Math.max(0, y); + let nw = Math.min(w, root.screen.width - nx); + let nh = Math.min(h, root.screen.height - ny); + root.sx = nx; + root.sy = ny; + root.ex = nx + nw; + root.ey = ny + nh; } onMoveBy: (dx, dy) => { const w = root.sw, h = root.sh; diff --git a/Helpers/Picker/AnnotationCanvas.qml b/Helpers/Picker/AnnotationCanvas.qml index 32e251f..4116eaf 100755 --- a/Helpers/Picker/AnnotationCanvas.qml +++ b/Helpers/Picker/AnnotationCanvas.qml @@ -59,6 +59,7 @@ Item { } anchors.fill: parent + enabled: tool !== "none" StrokeCanvas { id: canvas @@ -77,15 +78,12 @@ Item { acceptedButtons: Qt.LeftButton | Qt.RightButton anchors.fill: parent cursorShape: undefined - enabled: root.tool !== "none" - hoverEnabled: true + enabled: root.enabled onPositionChanged: e => { const x = e.x; const y = e.y; - canvas.hoverPoint = Qt.point(x, y); - if (!pressed) return; @@ -125,12 +123,16 @@ Item { const withinYHeight = y > root.selection.y && y < root.selection.y + root.selection.implicitHeight; if (withinXWidth && withinYHeight) { - canvas.showHover(x, y); + if (!drawHandler.pressed) + canvas.showHover(x, y); + else + canvas.showHover(drawHandler.mouseX, drawHandler.mouseY); return Qt.BlankCursor; } else { canvas.hideHover(); return undefined; } } + enabled: root.enabled } } diff --git a/Helpers/Picker/SelectionHandles.qml b/Helpers/Picker/SelectionHandles.qml index d79ae71..3359220 100755 --- a/Helpers/Picker/SelectionHandles.qml +++ b/Helpers/Picker/SelectionHandles.qml @@ -1,13 +1,15 @@ pragma ComponentBehavior: Bound import QtQuick +import ZShell.Internal +import qs.Services Item { id: root required property int border - property color handleBorder: "#3584e4" - property color handleFill: "white" + property color handleBorder: Colors.palette.m3primary + property color handleFill: Colors.palette.m3onPrimary property real hs: 12 property real minSize: 24 required property real selH @@ -26,6 +28,8 @@ Item { x: selX y: selY + Component.onDestruction: Cursor.clearOverride() + DragHandler { id: moveHandler @@ -33,6 +37,7 @@ Item { property real accumY: 0 cursorShape: undefined + dragThreshold: 0 target: null onActiveChanged: { @@ -54,7 +59,7 @@ Item { if (root.tool !== "move") return undefined; - if (moveHandler.centroid.pressedButtons & Qt.LeftButton) + if ((moveHandler.centroid.pressedButtons & Qt.LeftButton) && moveHandler.active) return Qt.ClosedHandCursor; else return Qt.OpenHandCursor; @@ -123,6 +128,8 @@ Item { z: 10 HoverHandler { + id: hover + cursorShape: { switch (handle.edge) { case "tl": @@ -148,6 +155,7 @@ Item { property real startX property real startY + dragThreshold: 0 grabPermissions: PointerHandler.CanTakeOverFromAnything | PointerHandler.TakeOverForbidden target: null @@ -157,8 +165,10 @@ Item { startY = root.y; startW = root.width; startH = root.height; + Cursor.setOverride(hover.cursorShape); } else { root.dragFinished(); + Cursor.clearOverride(); } } onTranslationChanged: { diff --git a/Modules/Shortcuts.qml b/Modules/Shortcuts.qml index ca227ca..1d11eb9 100644 --- a/Modules/Shortcuts.qml +++ b/Modules/Shortcuts.qml @@ -11,6 +11,18 @@ Scope { readonly property bool hasFullscreen: Hypr.focusedWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) ?? false property bool launcherInterrupted + CustomShortcut { + description: "Open screenshot" + name: "screenshot" + + onPressed: { + const states = ShellState.allStates(); + for (const s of states) { + s.screenshot = true; + } + } + } + CustomShortcut { description: "Toggle launcher" name: "toggle-launcher" @@ -26,6 +38,7 @@ Scope { } CustomShortcut { + description: "Toggle drawing" name: "toggle-drawing" onPressed: { @@ -35,6 +48,7 @@ Scope { } CustomShortcut { + description: "Toggle sidebar" name: "toggle-nc" onPressed: { @@ -44,6 +58,7 @@ Scope { } CustomShortcut { + description: "Show On-Screen-Display" name: "show-osd" onPressed: { @@ -53,6 +68,7 @@ Scope { } CustomShortcut { + description: "Toggle settings" name: "toggle-settings" onPressed: { @@ -62,6 +78,7 @@ Scope { } CustomShortcut { + description: "Toggle clipboard" name: "toggle-clipboard" onPressed: { diff --git a/Services/ShellState.qml b/Services/ShellState.qml index b806f4d..7d48f4b 100644 --- a/Services/ShellState.qml +++ b/Services/ShellState.qml @@ -6,6 +6,10 @@ import qs.Components import qs.Helpers Singleton { + function allStates(): list { + return [...states.instances]; + } + function anySidebarOpen(): bool { return states.instances.some(s => s.sidebar); } @@ -30,6 +34,7 @@ Singleton { model: Quickshell.screens - ScreenState {} + ScreenState { + } } } diff --git a/shell.qml b/shell.qml index f602e71..75bde5a 100644 --- a/shell.qml +++ b/shell.qml @@ -12,7 +12,6 @@ import qs.Modules import qs.Modules.Wallpaper import qs.Modules.Lock import qs.Drawers -import qs.Helpers import qs.Modules.Polkit import qs.Daemons @@ -29,9 +28,6 @@ ShellRoot { Wallpaper { } - AreaPicker { - } - Lock { id: lock }