From 64fc68cc3ac73254652f51273b3ee27b63e8b5df Mon Sep 17 00:00:00 2001 From: Zacharias-Brohn Date: Fri, 5 Dec 2025 19:45:15 +0100 Subject: [PATCH] lockscreen background --- Bar.qml | 10 -- Config/LockConf.qml | 1 + Helpers/Hypr.qml | 4 + Modules/Lock/LockSurface.qml | 31 ++-- Modules/NotifBell.qml | 3 +- Modules/NotificationCenter.qml | 279 +++++++++++++++++--------------- Modules/Time.qml | 16 +- Modules/TrackedNotification.qml | 6 +- assets/shaders/blurshader.glsl | 22 +++ scripts/LockScreenBg.py | 3 + shell.qml | 4 + 11 files changed, 211 insertions(+), 168 deletions(-) create mode 100644 assets/shaders/blurshader.glsl diff --git a/Bar.qml b/Bar.qml index f8a7337..9527ab5 100644 --- a/Bar.qml +++ b/Bar.qml @@ -40,16 +40,6 @@ Scope { implicitHeight: 34 } - NotificationCenter { - bar: bar - } - - Process { - id: ncProcess - command: ["sh", "-c", `qs -p ${bar.root}/shell.qml ipc call root showCenter`] - running: false - } - anchors { top: true left: true diff --git a/Config/LockConf.qml b/Config/LockConf.qml index 52bc5be..af451b8 100644 --- a/Config/LockConf.qml +++ b/Config/LockConf.qml @@ -2,4 +2,5 @@ import Quickshell.Io JsonObject { property bool fixLockScreen: false + property bool useWallpaper: true } diff --git a/Helpers/Hypr.qml b/Helpers/Hypr.qml index 8d733fe..2d2c0e3 100644 --- a/Helpers/Hypr.qml +++ b/Helpers/Hypr.qml @@ -39,6 +39,10 @@ Singleton { signal configReloaded + function getActiveScreen(): ShellScreen { + return Quickshell.screens.find(screen => root.monitorFor(screen) === root.focusedMonitor) + } + function dispatch(request: string): void { Hyprland.dispatch(request); } diff --git a/Modules/Lock/LockSurface.qml b/Modules/Lock/LockSurface.qml index 37c479a..28391fb 100644 --- a/Modules/Lock/LockSurface.qml +++ b/Modules/Lock/LockSurface.qml @@ -21,7 +21,7 @@ WlSessionLockSurface { property string buffer - color: overlay.visible ? "black" : "transparent" + color: "transparent" Connections { target: root.pam @@ -38,7 +38,7 @@ WlSessionLockSurface { } Timer { - interval: 100 + interval: 5 running: true repeat: false onTriggered: { @@ -62,6 +62,7 @@ WlSessionLockSurface { onTextChanged: text = "" } + ScreencopyView { id: background @@ -70,23 +71,31 @@ WlSessionLockSurface { anchors.fill: parent captureSource: root.screen opacity: 1 + visible: !Config.lock.useWallpaper layer.enabled: true layer.effect: MultiEffect { autoPaddingEnabled: false blurEnabled: true - blur: 2 - blurMax: 32 - blurMultiplier: 0 + blur: 0.8 + blurMax: 64 + blurMultiplier: 1 + brightness: 0 } } - // Image { - // id: backgroundImage - // anchors.fill: parent - // asynchronous: true - // source: root.backgroundImage - // } + Image { + id: backgroundImage + anchors.fill: parent + asynchronous: false + cache: false + source: WallpaperPath.lockscreenBg + visible: Config.lock.useWallpaper + + Component.onCompleted: { + console.log(source); + } + } Rectangle { id: overlay diff --git a/Modules/NotifBell.qml b/Modules/NotifBell.qml index 2003e2a..f1e4df1 100644 --- a/Modules/NotifBell.qml +++ b/Modules/NotifBell.qml @@ -1,3 +1,4 @@ +import Quickshell.Hyprland import QtQuick import qs.Config import qs.Helpers @@ -32,7 +33,7 @@ Item { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - ncProcess.running = true + Hyprland.dispatch("global zshell-nc:toggle-nc"); } } } diff --git a/Modules/NotificationCenter.qml b/Modules/NotificationCenter.qml index abe1889..ac5936a 100644 --- a/Modules/NotificationCenter.qml +++ b/Modules/NotificationCenter.qml @@ -12,163 +12,174 @@ import qs.Daemons import qs.Effects PanelWindow { - id: root - color: "transparent" - anchors { - top: true - right: true - left: true - bottom: true - } + id: root + color: "transparent" + anchors { + top: true + right: true + left: true + bottom: true + } WlrLayershell.namespace: "ZShell-Notifs" - WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand - required property PanelWindow bar - property bool centerShown: false - property alias posX: backgroundRect.x - visible: false + WlrLayershell.layer: WlrLayer.Overlay + WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand + property bool centerShown: false + property alias posX: backgroundRect.x + visible: false - mask: Region { item: backgroundRect } + mask: Region { item: backgroundRect } - IpcHandler { - id: ipcHandler - target: "root" + Connections { + target: Hypr - function showCenter(): void { root.centerShown = !root.centerShown; } - } + function onFocusedMonitorChanged(): void { + if ( !root.centerShown ) { + root.screen = Hypr.getActiveScreen(); + } + } + } - onVisibleChanged: { - if ( root.visible ) { - showAnimation.start(); - } - } + GlobalShortcut { + appid: "zshell-nc" + name: "toggle-nc" + onPressed: { + root.screen = Hypr.getActiveScreen(); + root.centerShown = !root.centerShown; + } + } - onCenterShownChanged: { - if ( !root.centerShown ) { - closeAnimation.start(); - closeTimer.start(); - } else { - root.visible = true; - } - } + onVisibleChanged: { + if ( root.visible ) { + showAnimation.start(); + } + } - Keys.onPressed: { - if ( event.key === Qt.Key_Escape ) { - root.centerShown = false; - event.accepted = true; - } - } + onCenterShownChanged: { + if ( !root.centerShown ) { + closeAnimation.start(); + closeTimer.start(); + } else { + root.visible = true; + } + } - Timer { - id: closeTimer - interval: 300 - onTriggered: { - root.visible = false; - } - } + Keys.onPressed: { + if ( event.key === Qt.Key_Escape ) { + root.centerShown = false; + event.accepted = true; + } + } - NumberAnimation { - id: showAnimation - target: backgroundRect - property: "x" - to: Math.round(root.bar.screen.width - backgroundRect.implicitWidth - 10) - from: root.bar.screen.width - duration: MaterialEasing.expressiveEffectsTime - easing.bezierCurve: MaterialEasing.expressiveEffects - onStopped: { - focusGrab.active = true; - } - } + Timer { + id: closeTimer + interval: 300 + onTriggered: { + root.visible = false; + } + } - NumberAnimation { - id: closeAnimation - target: backgroundRect - property: "x" - from: root.bar.screen.width - backgroundRect.implicitWidth - 10 - to: root.bar.screen.width - duration: MaterialEasing.expressiveEffectsTime - easing.bezierCurve: MaterialEasing.expressiveEffects - } + NumberAnimation { + id: showAnimation + target: backgroundRect + property: "x" + to: Math.round(root.screen.width - backgroundRect.implicitWidth - 10) + from: root.screen.width + duration: MaterialEasing.expressiveEffectsTime + easing.bezierCurve: MaterialEasing.expressiveEffects + onStopped: { + focusGrab.active = true; + } + } - HyprlandFocusGrab { - id: focusGrab - active: false - windows: [ root ] - onCleared: { - root.centerShown = false; - } - } + NumberAnimation { + id: closeAnimation + target: backgroundRect + property: "x" + from: root.screen.width - backgroundRect.implicitWidth - 10 + to: root.screen.width + duration: MaterialEasing.expressiveEffectsTime + easing.bezierCurve: MaterialEasing.expressiveEffects + } - TrackedNotification { - centerShown: root.centerShown - bar: root.bar - } + HyprlandFocusGrab { + id: focusGrab + active: false + windows: [ root ] + onCleared: { + root.centerShown = false; + } + } - ShadowRect { - anchors.fill: backgroundRect - radius: backgroundRect.radius - } + TrackedNotification { + centerShown: root.centerShown + screen: root.screen + } - Rectangle { - id: backgroundRect - y: 10 - x: Screen.width - z: 1 + ShadowRect { + anchors.fill: backgroundRect + radius: backgroundRect.radius + } - property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor + Rectangle { + id: backgroundRect + y: 10 + x: Screen.width + z: 1 - implicitWidth: 400 - implicitHeight: root.height - 20 - color: backgroundColor - radius: 8 - border.color: "#555555" - border.width: Config.useDynamicColors ? 0 : 1 - ColumnLayout { - anchors.fill: parent - anchors.margins: 10 - spacing: 10 + property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor - NotificationCenterHeader { } + implicitWidth: 400 + implicitHeight: root.height - 20 + color: backgroundColor + radius: 8 + border.color: "#555555" + border.width: Config.useDynamicColors ? 0 : 1 + ColumnLayout { + anchors.fill: parent + anchors.margins: 10 + spacing: 10 - Rectangle { - color: "#333333" - Layout.preferredHeight: Config.useDynamicColors ? 0 : 1 - Layout.fillWidth: true - } + NotificationCenterHeader { } - Flickable { - Layout.fillWidth: true - Layout.fillHeight: true - pixelAligned: true - contentHeight: notificationColumn.implicitHeight - clip: true + Rectangle { + color: "#333333" + Layout.preferredHeight: Config.useDynamicColors ? 0 : 1 + Layout.fillWidth: true + } - Column { - id: notificationColumn - width: parent.width - spacing: 10 + Flickable { + Layout.fillWidth: true + Layout.fillHeight: true + pixelAligned: true + contentHeight: notificationColumn.implicitHeight + clip: true - add: Transition { - NumberAnimation { - properties: "x"; - duration: 300; - easing.type: Easing.OutCubic - } - } + Column { + id: notificationColumn + width: parent.width + spacing: 10 - move: Transition { - NumberAnimation { - properties: "x"; - duration: 200; - easing.type: Easing.OutCubic - } - } + add: Transition { + NumberAnimation { + properties: "x"; + duration: 300; + easing.type: Easing.OutCubic + } + } - GroupListView { } + move: Transition { + NumberAnimation { + properties: "x"; + duration: 200; + easing.type: Easing.OutCubic + } + } - } - } - } - } + GroupListView { } + + } + } + } + } } diff --git a/Modules/Time.qml b/Modules/Time.qml index 4da6649..876a034 100644 --- a/Modules/Time.qml +++ b/Modules/Time.qml @@ -4,10 +4,10 @@ import Quickshell import QtQuick Singleton { - id: root - readonly property string time: { - Qt.formatDateTime(clock.date, "ddd d MMM - hh:mm:ss") - } + id: root + readonly property string time: { + Qt.formatDateTime(clock.date, "ddd d MMM - hh:mm:ss") + } readonly property string shortTime: { Qt.formatDateTime(clock.date, "hh:mm") @@ -17,8 +17,8 @@ Singleton { Qt.formatDateTime(clock.date, "hh:mm:ss") } - SystemClock { - id: clock - precision: SystemClock.Seconds - } + SystemClock { + id: clock + precision: SystemClock.Seconds + } } diff --git a/Modules/TrackedNotification.qml b/Modules/TrackedNotification.qml index f596b60..689cf1a 100644 --- a/Modules/TrackedNotification.qml +++ b/Modules/TrackedNotification.qml @@ -12,7 +12,6 @@ import qs.Effects PanelWindow { id: root color: "transparent" - screen: root.bar.screen anchors { top: true @@ -28,10 +27,9 @@ PanelWindow { exclusionMode: ExclusionMode.Ignore property list notifRegions: [] required property bool centerShown - required property PanelWindow bar property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "white" property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor - visible: Hyprland.monitorFor(screen).focused + // visible: Hyprland.monitorFor(screen).focused ListView { id: notifListView @@ -44,7 +42,7 @@ PanelWindow { } anchors.top: parent.top anchors.bottom: parent.bottom - x: root.centerShown ? root.bar.width - width - 420 : root.bar.width - width - 20 + x: root.centerShown ? root.screen.width - width - 420 : root.screen.width - width - 20 z: 0 anchors.topMargin: 54 width: 400 diff --git a/assets/shaders/blurshader.glsl b/assets/shaders/blurshader.glsl new file mode 100644 index 0000000..f59d20c --- /dev/null +++ b/assets/shaders/blurshader.glsl @@ -0,0 +1,22 @@ +uniform sampler2D image; + +out vec4 FragmentColor; + +uniform float offset[3] = float[](0.0, 1.3846153846, 3.2307692308); +uniform float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703); + +void main(void) { + + FragmentColor = texture2D(image, vec2(gl_FragCoord) / 1024.0) * weight[0]; + + for (int i=1; i<3; i++) { + + FragmentColor += + texture2D(image, (vec2(gl_FragCoord) + vec2(0.0, offset[i])) / 1024.0) + * weight[i]; + + FragmentColor += + texture2D(image, (vec2(gl_FragCoord) - vec2(0.0, offset[i])) / 1024.0) + * weight[i]; + } +} diff --git a/scripts/LockScreenBg.py b/scripts/LockScreenBg.py index 5ccc5b1..ef26103 100644 --- a/scripts/LockScreenBg.py +++ b/scripts/LockScreenBg.py @@ -3,8 +3,11 @@ import argparse def gen_blurred_image(input_image, output_path): img = Image.open(input_image) + size = img.size + img = img.resize((size[0] // 2, size[1] // 2), Image.NEAREST) img = img.filter(ImageFilter.GaussianBlur(40)) + # img = img.resize(size, Image.LANCZOS) img.save(output_path, "PNG") diff --git a/shell.qml b/shell.qml index 05aaf97..6b28ebf 100644 --- a/shell.qml +++ b/shell.qml @@ -17,4 +17,8 @@ Scope { IdleInhibitor { lock: lock } + + NotificationCenter { + + } }