@@ -9,13 +9,20 @@ import qs.Services.Compositor
99import qs.Services.Hardware
1010import qs.Services.Keyboard
1111import qs.Services.Media
12+ import qs.Services.Power
1213import qs.Services.UI
1314import qs.Widgets
1415
1516Loader {
1617 id: root
18+
19+ // Starts the lock screen when activated
1720 active: false
1821
22+ // Only controls the state of the session lock
23+ // Decoupled because we need to capture the screen first
24+ property bool locked: false
25+
1926 // Track if the visualizer should be shown (lockscreen active + media playing + non-compact mode)
2027 readonly property bool needsSpectrum: root .active && ! Settings .data .general .compactLockScreen && Settings .data .audio .visualizerType !== " " && Settings .data .audio .visualizerType !== " none"
2128
@@ -31,6 +38,10 @@ Loader {
3138 } else {
3239 LockKeysService .unregisterComponent (" lockscreen" );
3340 }
41+
42+ // Trigger locksreen when loader is active
43+ if (root .active )
44+ startLockScreen ();
3445 }
3546
3647 onNeedsSpectrumChanged: {
@@ -51,24 +62,82 @@ Loader {
5162 LockKeysService .unregisterComponent (" lockscreen" );
5263 }
5364
65+ // Dictionary of screen name to ItemGrabResult of screen captures
66+ property var screenCaptures: ({})
67+
68+ // Wait until all screens are captured before locking
69+ onScreenCapturesChanged: {
70+ let captureCount = Object .keys (screenCaptures).length ;
71+ if (captureCount > 0 && captureCount === Quickshell .screens .length ) {
72+ root .locked = true ;
73+ }
74+ }
75+
76+ // When lock is requested, clear previous captures and activate SCVs
77+ function startLockScreen () {
78+ screenCaptures = {};
79+ screenCopies .active = true ;
80+ }
81+
5482 Timer {
5583 id: unloadAfterUnlockTimer
5684 interval: 250
5785 repeat: false
5886 onTriggered: root .active = false
5987 }
6088
61- function scheduleUnloadAfterUnlock () {
89+ function unlockAndUnload () {
90+ locked = false ;
91+ screenCopies .active = false ;
6292 unloadAfterUnlockTimer .start ();
6393 }
6494
95+ // Image grabber for each connected screen
96+ Loader {
97+ id: screenCopies
98+ active: false
99+
100+ sourceComponent: Instantiator {
101+ model: Quickshell .screens
102+
103+ delegate: PanelWindow {
104+ anchors {
105+ top: true
106+ left: true
107+ right: true
108+ bottom: true
109+ }
110+ exclusionMode: ExclusionMode .Ignore
111+ screen : modelData
112+ color: " transparent"
113+
114+ ScreencopyView {
115+ anchors .fill : parent
116+ captureSource: screen
117+
118+ // Only grab an image when content is ready
119+ onHasContentChanged: {
120+ if (hasContent) {
121+ grabToImage (function (result ) {
122+ // Store a ref to the result to avoid GC
123+ root .screenCaptures [screen .name ] = result;
124+ // Manually call changed to trigger mutation signal
125+ root .screenCapturesChanged ();
126+ });
127+ }
128+ }
129+ }
130+ }
131+ }
132+ }
133+
65134 sourceComponent: Component {
66135 Item {
67136 id: lockContainer
68137
69- readonly property bool transitionsEnabled : Settings .data .general .lockScreenAnimations
138+ readonly property bool canTransition : Settings .data .general .lockScreenAnimations && ! PowerProfileService . noctaliaPerformanceMode
70139
71- property real transitionProgress: transitionsEnabled ? 0.0 : 1.0
140+ property real transitionProgress: canTransition ? 0.0 : 1.0
72141
73142 NumberAnimation {
74143 id: lockEnter
@@ -77,12 +146,11 @@ Loader {
77146 to: 1.0
78147 duration: Style .animationNormal
79148 easing .type : Easing .OutCubic
80- running: transitionsEnabled
149+ running: root . locked && canTransition
81150 }
82151
83152 function unlockScreen () {
84- lockSession .locked = false ;
85- root .scheduleUnloadAfterUnlock ();
153+ root .unlockAndUnload ();
86154 lockContext .currentText = " " ;
87155 }
88156
@@ -99,7 +167,7 @@ Loader {
99167 LockContext {
100168 id: lockContext
101169 onUnlocked: {
102- if (transitionsEnabled ) {
170+ if (canTransition ) {
103171 lockEnter .stop ();
104172 lockExit .start ();
105173 return ;
@@ -121,10 +189,11 @@ Loader {
121189
122190 WlSessionLock {
123191 id: lockSession
124- locked: root .active
192+ locked: root .locked
125193
126194 WlSessionLockSurface {
127195 id: lockSurface
196+ color: " black"
128197
129198 Loader {
130199 anchors .fill : parent
@@ -156,6 +225,7 @@ Loader {
156225 LockScreenBackground {
157226 id: backgroundComponent
158227 screen : lockSurface .screen
228+ screenGrab: lockSurface .screen ? (root .screenCaptures [lockSurface .screen .name ] || null ) : null
159229 transitionProgress: lockContainer .transitionProgress
160230 }
161231
0 commit comments