diff --git a/nix/package.nix b/nix/package.nix index 9634978..6e1600d 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -27,10 +27,13 @@ stdenvNoCC.mkDerivation { mkdir -p $out/share/nova-shell cp -r shell/shell.qml shell/modules shell/services shell/applets shell/lock shell/assets $out/share/nova-shell/ - # Compile fragment shader to Qt RHI format + # Compile fragment shaders to Qt RHI format qsb --qt6 \ -o $out/share/nova-shell/modules/hex_wave.frag.qsb \ shell/modules/hex_wave.frag + qsb --qt6 \ + -o $out/share/nova-shell/modules/reveal_mask.frag.qsb \ + shell/modules/reveal_mask.frag mkdir -p $out/bin makeWrapper ${lib.getExe quickshell} $out/bin/nova-shell \ diff --git a/shell/lock/LockSurface.qml b/shell/lock/LockSurface.qml index ff22f7b..d77b7c8 100644 --- a/shell/lock/LockSurface.qml +++ b/shell/lock/LockSurface.qml @@ -13,9 +13,7 @@ WlSessionLockSurface { color: S.Theme.base00 - // Wave progress drives blur/dim/hex overlay reveal property real _unlockFade: 1 - readonly property real _waveProgress: (root.width > 0 ? Math.max(0, Math.min(1, _hexWave.wavePhase / root.width)) : 0) * _unlockFade // Clear desktop screenshot - visible immediately ScreencopyView { @@ -25,35 +23,46 @@ WlSessionLockSurface { opacity: _unlockFade } - // Blurred screenshot - fades in as wave passes - ScreencopyView { + // Overlay group: blur + dim + hexes, revealed per-pixel by wave position + Item { anchors.fill: parent - captureSource: root.screen - visible: S.Modules.lock.screenshot ?? true - opacity: root._waveProgress + opacity: _unlockFade layer.enabled: true - layer.effect: MultiEffect { - autoPaddingEnabled: false - blurEnabled: true - blur: 1 - blurMax: 64 + layer.effect: ShaderEffect { + property real uPhase: _hexWave.wavePhase + property real uWidth: root.width + fragmentShader: Quickshell.shellPath("modules/reveal_mask.frag.qsb") } - } - // Dim overlay - fades in with wave - Rectangle { - anchors.fill: parent - color: Qt.rgba(S.Theme.base00.r, S.Theme.base00.g, S.Theme.base00.b, 0.4) - opacity: root._waveProgress - } + // Blurred screenshot + ScreencopyView { + anchors.fill: parent + captureSource: root.screen + visible: S.Modules.lock.screenshot ?? true - // Hex wave - fades in with wave progress - C.HexWaveBackground { - id: _hexWave - anchors.fill: parent - running: root.lock.secure - opacity: root._waveProgress * 0.4 + layer.enabled: true + layer.effect: MultiEffect { + autoPaddingEnabled: false + blurEnabled: true + blur: 1 + blurMax: 64 + } + } + + // Dim overlay + Rectangle { + anchors.fill: parent + color: Qt.rgba(S.Theme.base00.r, S.Theme.base00.g, S.Theme.base00.b, 0.4) + } + + // Hex wave + C.HexWaveBackground { + id: _hexWave + anchors.fill: parent + running: root.lock.secure + opacity: 0.4 + } } // Keyboard input via TextInput - engages Qt's full input pipeline including @@ -242,13 +251,6 @@ WlSessionLockSurface { duration: 300 easing.type: Easing.InCubic } - NumberAnimation { - target: _hexWave - property: "opacity" - to: 0 - duration: 300 - easing.type: Easing.InCubic - } } PropertyAction { diff --git a/shell/modules/reveal_mask.frag b/shell/modules/reveal_mask.frag new file mode 100644 index 0000000..a2fee8e --- /dev/null +++ b/shell/modules/reveal_mask.frag @@ -0,0 +1,21 @@ +#version 440 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + float uPhase; + float uWidth; +}; + +layout(binding = 1) uniform sampler2D source; + +void main() { + vec4 tex = texture(source, qt_TexCoord0); + float x = qt_TexCoord0.x * uWidth; + // Soft reveal edge: fully visible 200px behind wave, fades out 50px ahead + float mask = 1.0 - smoothstep(uPhase - 200.0, uPhase + 50.0, x); + fragColor = tex * mask * qt_Opacity; +}