From a64b477deaba210102bae11bcf054d973803d3f3 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 18 Jun 2024 17:14:51 -0700 Subject: [PATCH] lockscreen: replace lockscreen example The new one uses the pam module and looks much nicer. --- lockscreen/AuthContext.qml | 43 --------------- lockscreen/LockContext.qml | 54 ++++++++++++++++++ lockscreen/LockSurface.qml | 104 +++++++++++++++++++++++++++++++++++ lockscreen/Lockscreen.qml | 52 ------------------ lockscreen/README.md | 4 +- lockscreen/image.png | Bin 22081 -> 21411 bytes lockscreen/pam/password.conf | 1 + lockscreen/shell.qml | 37 +++++-------- lockscreen/test.qml | 21 ++++--- 9 files changed, 190 insertions(+), 126 deletions(-) delete mode 100644 lockscreen/AuthContext.qml create mode 100644 lockscreen/LockContext.qml create mode 100644 lockscreen/LockSurface.qml delete mode 100644 lockscreen/Lockscreen.qml create mode 100644 lockscreen/pam/password.conf diff --git a/lockscreen/AuthContext.qml b/lockscreen/AuthContext.qml deleted file mode 100644 index f5c5745..0000000 --- a/lockscreen/AuthContext.qml +++ /dev/null @@ -1,43 +0,0 @@ -import QtQuick -import Quickshell -import Quickshell.Io - -QtObject { - property int status: AuthContext.Status.FirstLogin - signal unlocked(); - - enum Status { - FirstLogin, - Authenticating, - LoginFailed - } - - property string password - - property var pamtester: Process { - property bool failed: true - - command: ["pamtester", "login", Quickshell.env("USER"), "authenticate"] - - onStarted: this.write(`${password}\n`) - - stdout: SplitParser { - // fails go to stderr - onRead: pamtester.failed = false - } - - onExited: { - if (failed) { - status = AuthContext.Status.LoginFailed; - } else { - unlocked(); - } - } - } - - function tryLogin(password: string) { - this.password = password - status = AuthContext.Status.Authenticating; - pamtester.running = true; - } -} diff --git a/lockscreen/LockContext.qml b/lockscreen/LockContext.qml new file mode 100644 index 0000000..73cdb5b --- /dev/null +++ b/lockscreen/LockContext.qml @@ -0,0 +1,54 @@ +import QtQuick +import Quickshell +import Quickshell.Services.Pam + +Scope { + id: root + signal unlocked() + signal failed() + + // These properties are in the context and not individual lock surfaces + // so all surfaces can share the same state. + property string currentText: "" + property bool unlockInProgress: false + property bool showFailure: false + + // Clear the failure text once the user starts typing. + onCurrentTextChanged: showFailure = false; + + function tryUnlock() { + if (currentText === "") return; + + root.unlockInProgress = true; + pam.start(); + } + + PamContext { + id: pam + + // Its best to have a custom pam config for quickshell, as the system one + // might not be what your interface expects, and break in some way. + // This particular example only supports passwords. + configDirectory: "pam" + config: "password.conf" + + // pam_unix will ask for a response for the password prompt + onPamMessage: { + if (this.responseRequired) { + this.respond(root.currentText); + } + } + + // pam_unix won't send any important messages so all we need is the completion status. + onCompleted: result => { + if (result == PamResult.Success) { + root.unlocked(); + } else { + root.currentText = ""; + root.showFailure = true; + } + + root.unlockInProgress = false; + } + } +} diff --git a/lockscreen/LockSurface.qml b/lockscreen/LockSurface.qml new file mode 100644 index 0000000..08d107b --- /dev/null +++ b/lockscreen/LockSurface.qml @@ -0,0 +1,104 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls.Fusion +import Quickshell.Wayland + +Rectangle { + id: root + required property LockContext context + readonly property ColorGroup colors: Window.active ? palette.active : palette.inactive + + color: colors.window + + Button { + text: "Its not working, let me out" + onClicked: context.unlocked(); + } + + Label { + id: clock + property var date: new Date() + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: 100 + } + + // The native font renderer tends to look nicer at large sizes. + renderType: Text.NativeRendering + font.pointSize: 80 + + // updates the clock every second + Timer { + running: true + repeat: true + interval: 1000 + + onTriggered: clock.date = new Date(); + } + + // updated when the date changes + text: { + const hours = this.date.getHours().toString().padStart(2, '0'); + const minutes = this.date.getMinutes().toString().padStart(2, '0'); + return `${hours}:${minutes}`; + } + } + + ColumnLayout { + // Uncommenting this will make the password entry invisible except on the active monitor. + // visible: Window.active + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.verticalCenter + } + + RowLayout { + TextField { + id: passwordBox + + implicitWidth: 400 + padding: 10 + + focus: true + enabled: !root.context.unlockInProgress + echoMode: TextInput.Password + inputMethodHints: Qt.ImhSensitiveData + + // Update the text in the context when the text in the box changes. + onTextChanged: root.context.currentText = this.text; + + // Try to unlock when enter is pressed. + onAccepted: root.context.tryUnlock(); + + // Update the text in the box to match the text in the context. + // This makes sure multiple monitors have the same text. + Connections { + target: root.context + + function onCurrentTextChanged() { + passwordBox.text = root.context.currentText; + } + } + } + + Button { + text: "Unlock" + padding: 10 + + // don't steal focus from the text box + focusPolicy: Qt.NoFocus + + enabled: !root.context.unlockInProgress && root.context.currentText !== ""; + onClicked: root.context.tryUnlock(); + } + } + + Label { + visible: root.context.showFailure + text: "Incorrect password" + } + } +} diff --git a/lockscreen/Lockscreen.qml b/lockscreen/Lockscreen.qml deleted file mode 100644 index 83f58b2..0000000 --- a/lockscreen/Lockscreen.qml +++ /dev/null @@ -1,52 +0,0 @@ -import QtQuick -import QtQuick.Controls.Basic - -Item { - required property AuthContext context - - Item { - anchors.centerIn: parent - - TextField { - id: entryBox - anchors.centerIn: parent - width: 600 - font.pointSize: 24 - - enabled: context.status != AuthContext.Status.Authenticating - focus: true - horizontalAlignment: TextInput.AlignHCenter - echoMode: TextInput.Password - inputMethodHints: Qt.ImhSensitiveData - placeholderText: "Enter password" - - onAccepted: { - if (text != "") context.tryLogin(text) - } - - onEnabledChanged: { - if (enabled) text = "" - } - } - - Text { - id: status - color: "white" - font.pointSize: 24 - - anchors { - horizontalCenter: entryBox.horizontalCenter - top: entryBox.bottom - topMargin: 40 - } - - text: { - switch (context.status) { - case AuthContext.Status.FirstLogin: return "" - case AuthContext.Status.Authenticating: return "Authenticating" - case AuthContext.Status.LoginFailed: return "Login Failed" - } - } - } - } -} diff --git a/lockscreen/README.md b/lockscreen/README.md index 9a1f1b0..1926b9b 100644 --- a/lockscreen/README.md +++ b/lockscreen/README.md @@ -1,7 +1,7 @@ # Lockscreen -This is a barebones lockscreen with a password input box. -Note that you MUST have `pamtester` installed or you won't be able to log in. +This is a simple but functional lockscreen that follows the system color scheme. +The only authentication method it supports is a password. You can run the lockscreen with `quickshell -p shell.qml`. diff --git a/lockscreen/image.png b/lockscreen/image.png index 956c8aac5bc2bfd1af34a1fc74d45ea3dd008fc2..f9d25d3a579825277cf0efd160802abe4edd8148 100644 GIT binary patch literal 21411 zcmeHu2UJr_)GmsOihx%H1O%>E0TltI*91jDq^SrfElQOxgq}c91TIBTdIzORm);W< z=_R3eLWfWiN=P7(@Dk+~@BhEG{(rso-g~jC zj*gB=?e6V|baV{9baY2#jvuDpu`1R(OGl?;qjvk|Bae}lu^sp5t(V*DJL*~4WH&iQ z9jn{|dwW||wHA2MwG%Io+#0e#-yY_8aP8{JtHCA5KTHQ7KKc9azu!MSY!UdH|I($m zbCy$qt@W>ck2=(&gH1^_3tJ7|706O(%38zj3oL@%EQ;H1Mf$AcfMnUdNgvYY{@xsq zJ7sWx?--REy5|g(RYBnHokw;LeV#epM4s6`H0L5*wd@Yt+YyD$ARrBkdMaA_2e%A;yKoQACq~^237zh4Pzk%- z0{@a#)kPl=$|arlakBs(kl~;l5XLnsFS-j_oyxXiMA1m0D2H8$(?j3zZ$q&#GQK6q z9=vOLlp~UnK_fxdQv=aAP=JoiNMX@R0f288jSb<5b;6aP?UfW#8xyPi_)}Xb?r1Ij z!hl9gZGY@Lv5oPbEVH6hZIottE0%MLuJhl%_&cGAek3b?;(2%S*=#Gi@siWpvMP7GUg*l%O>#=*90BtB zF#ffc^bi+FVrwU}-IAppLGAVYNtF6Ai~X5odCmQgAAAPE)P3hCIJy(Rq z<*_P>rjg(tgC;dnQ`_u&p)jeKddb|)O3pn)wKlERrHBaU-aIA~6-$R(re3zbU2mSR zJiOj9vQS3hRyZRTxi`Oq@9tSofMR)1cL@z~sN0UvX=7j&yu1igh_DX`^64TBu}HgOfs_4#Dvh&SkZ&tfT9&1WjmVm2~6fX;#gz z``(uA4bUZb->_I?l-JfDkdidYmjM&(LdZhA_cZTn@?3WupUSOK@-}YIhF46Z0wWn8 z7M=IeHA+1yFQi>34gNazMo{Dk7gr*e==mq|r80T;fpJN{AfeEVtEkh*B_#TyaZp=J zV%a1qs@svTu+YA$@3GF43Fn>-@Gghq+pW$o;J|D0FD!9Ahu)Lr1qcb{82nC~F|ynU z{KD1?Y2_ZpxBJx2;koTSq*D=AMwj*Zj>HiW-d(%ywL(n6jElDm86%zwkhUi*DK9K@ zbBSW(#ue*#OKX>ffGKZBNfJGQA`^OUHpt!5n(VA5c3@@w^elwMoymS_XE8fd72svl z!D`ErQe-PzQ(S?MtoG9x5fLjM{p3H|X2Z?3v~1JGXCet9F^+bf_jG@#@|7v2AFal< zu60?-%7pW(<76o}v);hb!&@%{NZ?()&c$S&8cOp(tZu)A)S!N=9!WHMzXXgUtT zCk)%mH4~H;JqLtry=)taSw8iM2Wn-5tSSSDPdIXlNr(mxY6y2!dEIUDRh<}xR7km0 zC~ZwKA&E#hCR5<7mLYsbqusbdVVtxylUjFOPUuFtJ$u)ALs_}yrF`6Y)Ou! zzjutC$kUgXrfx@y8w_LUvNx8<%D9}Z{;V?MMlXkGve8?&xwSk~b@o+98TaS=?+euV zIEV5w28WKOrZ{{YmPK5?Ql`B0*{VWc+IVPpDeBAkNfHxmKC(wiXE-58_C$`8Y-7D3 z98y+nH&=F{ewW!s*3n0cgl0;SeP--Ap5j@5Ygrz-SM{N01KQ6~3TZr2$=*3;q+4yR zmpw@=yf`5@f%0(c-CI|zLYmO05#5w5<-<<&LfRlKqGz5z1fY5sU0 zTd#sNG30tKv(ZLB{JtRGAGuP6GTNFG(h1&#xNvXuF)+XC#gEJUOt9>- z8)wt}LXwY($lf>9uX#rKHgVM7lbj_y{Df1c-r-hkUzqhcISqdo6Pn-HD?kWQJqO?Rb97t&^&e_qnM?5YiufLi!9r4T4l1w#}uO5vimy+t8FW*NHt0%r}HUZa0 zx|>R*1FX<4dwau)qDDgsd7tJWOG7ML(J;bDplbVoR=dq`l)SzDopF66At*>2GvwXH z!9mXu%dB1F{B$5Ayj@hcFqKQrF}7Js50tyJf^V^k|w~2%Pdij3F4nt zhr;Sjjvrm@df)ir$*71_>ZlCAX!+KVNI2Apb7+8QG_aB4wjDNDP_Alh9Z3{NxU}GpQ_SkUxE(Y;;bT zm(`tE77{fcqTGH!nv-_tk{EevD)f;V32N?@Bzy+p^*_sgFd_>3m>73U!(&Kse!EoMU_?gVmo!Q`rY z`^hs5BEX(UWX#2*UvPf64tYH$bRJ_de%v`MsUtRBLK2mIMA=EA=m14TA+Xyj_u4)Z z?{U8Zrj3;tlD5m|GzCp~l3cewCt2GHC1~ZJOYYmK-!$XS0N#-~hG`eyX;u(9H`>SR|*Ln{tr zMaQL&gIW^F#^P5Lv02*rn$w@|`|`f+-cSU$2}U!45CDsnw^QkXr})IpZ--!tRtjZH zZA=Z?yN2J>DHdsWXsWg+ekv4u@$`XHPqbvRrO(6uPy3lK?JHvxy>)a~y98^pRhlhW zd}hp*F*Q%pRY8Dp)GuZMfU?QWO^!+h6AyCB%%JWOX5r;TsH+8`OdBc910pE3(`yTP zT{xR2K2kA%3L<|tO<6zUy3E5i*z9U!7%5>h zmlL2Yx}_N&+|ElPgaPZuH;Yp<^+(N#C=lN z+m09^h5i0bvgu~(cHL4-#LeVg5!tgcZgwktamOe-fKYd zxca!5xvmZfo-E>&$~3&L#5VyGxL>@rGhvOEv39wvROGe2!NUfq*fO0H3^y-deT)D6 zq2VQ~kcwave>2{A&(*9kkhRuGQQieNl?yKBNg`VThe#`d;_Y@M@NZ1zJY`g>|n^efqx7?AMrV!_t|AcYgYmf!6s_AwE0L+d0&5?PF*~ z!51}_^F}@LSE|kdx8KaX5sYDJt#j*`4Ndwubo(G8)~80qzpy2qjW~ZTXU;0L%rG7W#1; z0CrDB?|kj^lov@d1PTk4X^%A6wkNhvoKK;eQ^yIuBzw7H(?_Q5L@la1*RCZzi>&P& zHwIPvw7nISPAV)Kf~SE<{o*Pdoh-)|14Yme!ka5hjvrgBFk=;ESe$I>9-p_%%NYe^ zTe*x5lodNhOQsrw(*-?~2k6ETb2s@dG{-&QQ_D}w5mQ}HB9#x-xHl(;4Or}r1V0rB zt1S^&xaSKm(YE!)rkrO>l*D)TH0e-PZ+|8vG?*!CwaKiAMWeb#%zK&y{<424nF``V z85k&SFP))uq{5AtI8`0s7XlGH#$ia0pA5Ba*3d$R1s}xq-bWX;b`<5l3HX;$<6B5} z06Ros!&A30fHS_puqbkUt*w-afkW{$WISt8=unNlrs-uR(Z$4p3vuB02}F(#@BQWv_~FbEDXn1s42Oo-?5aPbDS+-QA7nNP(r1ri@nJ zj}1Uu{ShyzjHMSIS!~yyclL#o%+K&WK6esz;tP&EznaTLsd0I@Jb(`b%Jo8X_8Qc3 zV%@b`?zMNe-_;JU=`LstJdFQ9`NF`~@7*;J@{+#jlzQEi@?Gvty(dri)#*(gNNF_+ z)CG#Clm5W028iP%%063*<>;bdjbJ4d8TYBMZU@i6;(CHOYnVBU+$qUgAIeiMEzHMA zSu5Y!91iF0U>2EIAbGm3>VtzH8dh2YwwsCrJ`aWjv-*Yb_yK?MAtiUq4u-`?rHsEf zd-bP#T5!dkjyxC9x7A8DLah_Rmdpk|5-)rPm$kL{h^TKjSnzkR`B?UkScHdiy&dES z$|LrN{6~cnyP($#d!rkQY?x4H;E{n#VNlU?X}cN6I9TtcjOq2eJVS5f_|>xEc>wNa zPn69tyR2d&xFpFbzh0*7%4^;(JsAvq2{OL|w@B;q-v~+dQ(_EQCFyyP!A z^Xjo&aG&A~`~9Q~MSLeDVqk=?4T`nIt0|vcns>57YE4AcnC&~0IZvV#3pu5(z_5ii z!CNd=M>)(kvWpZ94C@#A-#<|k4te0Of7s;(^1koH^^2veL$7aAElKP`S)7#R+-(lJfs6Ix>{hJ zJ5&sv_x*~MH4Y9A(C{V|XivmNag1^4+hjE4oioi8hKT=K_$*e*t1r7oyE+zD}C_g; zUo;jgP4;DjRf(O;>z}{r6CX)~_BN_1PO%{0SF+R)Cwa8uxm{|+*PFfU4ilBTPdz6m zr>9@H$KLSl91hS)1jTbEOjF)p(Yn{Zgt}qkOWTa_bz@5d*SaAPW~O%^QX{J97+lhz z(A-7>Glt%(aN895uB3O)iXg%l+2cKL2$MJPd0&y0RWS#i>X>lnTa86|tw`S{CLqWi z@7TWMZpl!lV@}4=Wz<&h4{$kU^yd`NJa0?pbZ^JEbuL~)4^$6MP$Tl>=Q*efUC=L$-8Q`2mYHC(R{Go zFYWGqW=+k_uYlji-0b$!cI4aLL^(OpH3IzL#mzi7USVPRV#m$kD`XW>z`4ub5WDF) zh^U7pM031wVYhK?vAdDQa|X5J%}B~LeiGRap06Ek7wPLCEQi{N>YX2jFBOr&B93o5 z`4CUZg+<}1a^OO{88d$#iceYBj2!L=Fa3}Oj9$YVm1DT&sMjNp(UG< z=e3|aGciynJk;KJQ3njS8yxX(kmDbJe)5d`yyoMQ@|9b^$^?}!uoNZAOGwTy9dS*; zPr%zq0Rg0%CDv30p!HI)ccwf$KG-pNI`j(?jv#NG#U-GnJxYUeo)A?JwrnO2yL=(@ zu>N*BvhT(f@e5b@uYO2($WS)2f!_0K9)h_g!Cbyvacbo(b_%K_T$AP)wnM*1%84hc zHlO&hPXs^g68mcR1M4>P9k#AGd0X?rj*ht39c5pGLg4v!a{D{@!l3sBPn1n4E_3-4 z-MoF${2AsGeEdI_uJY8SD>P6J@8PBHscG-+{VNKEx)1U;-30rAu|)H)_wKgViC)$F zOOxf?chMhZ;AY)HH*%`ulWQ%qvfb7s;QrgQp}QYUe+0~@)23=!Q2Rm$T`;0JWsOZ) zAMW>DVE4I9ywfb0ZGnb>$_{*@pwj-V6{3m=U&OD7JgMGUqrazxq~PRnl%MzN!a)=3 zk*VZqG>in^{zAqt?C-S8WARoeXfgWgB_+ra+8?^(-(mSj@#}Y1=zcDIe=zWKLHA=P z=O4wtME@hSKZAKt`x(rG+CRWNK=}W0Opl{dXgl9@|JA|m9Ut=~DpnhB2x_E|M!1Ct z*wMkEArH)aDv3nGt$vkTU^A*A1N!^>Cti;3m|&|mv9o0z@6!38)>G33qZBO zA8#<4m{iS$6mW=|gg(D@l)A8`M&rJ)w*9?%Vtlo6)0@;PeE%G1b%f{m5ei~6kB)qi z2?gwNpR{b01zd4m{Jnb<1hw8=Fw7M-+O`sSMD+-#shb+V5Aji;Xg?OJ6UF!QfUx;R zMf-&twALq4tCKuc1C!4#rog5eky0=dUEM7nt&dcrqv^`&V(gv9%HI$tQJI+*6EFE@ z-5k1KpQPF@O*;G+IdtJKiUc9G-H7jWw|T?KzJV)XvUstkfM%Au~8MY;P-WkMrRQ za&k_9al(c;_<{-UbNFQ?K6#(Lkb+T~H>07%_bWh3N(wt(iQ8gx)JhU7&>4JHi-l*; zeIC~C+8I2BnrYHLwO?hx8|6MJ#e!-MPu+gnztqf|YW!$yAq9f7mAzV&cJ~0WZNRjd zj!rL}yo-LkK9F&xSAKzQY^xS%0-HqG`A)!R+SfA0iqcT>FKUl2vI=Sy8q`}3fKnHS zYjJbad+vYmWXQ&sn2wjtz-TDnN#QqG(#@4oBY{j3E1GXCoge@#+-c^G=UHtvJSc$wR0}bTwK$BGM z_P$-2>Yd#foTy@3NZuKmnL_UNd~N)bo{}%+mtE%t{i$B_*gfoF+NAaePkkLpYsMSP zehiM?IY*!WsmTt=L!``D4u4!kxPqKIRk5ka9SnIHO?m&}!*3n-QW6ql5Lg+V@Lw3t zzkGl3t7>aMpO4FOmxvNAUP;D*Nzcp#WFAmE? z!^Som2MoQL{v7GAN|gwoel`yNC}z^!Fr6OS&cKz)MgyrX$%Mt@Fea(BXab@Jk??!=CUL3@xX409T>@ zM&({_ayb4HM8$fq=9G{*4okY%DOJCtLL^v#ZzkQufEMwyu2K?kH`{- z7dmSH)&xW*RSIe)odT*@5B5pLNun;^)qK~>?=F>UTGRaM4YAER;+6>xhYSwf)oH$q;K6ZX5)cOH zcyojbAUV?y^Fxzp@}SD1LG{gvR33deqRogAMP=$h{fjkI?U_?~Akld7!SBj);0v?^;gN<=?~Kd3s?>rxIt9tmfmN|HMOcvU}<^VJ0vm6-S<# zNR1!1anK5*+an5nF@_(uEWP&KGHBS)?0^5M>-MCK-R$$9?weEavCP8y=jKUyxw+Vy zUEZIcW_87J!lgt^O8UUPNl6tz>RWXJ$4>+#zr|iRML$HZ%Q0{`7{vbl$bJ^mKk%!0!cf#@@EadtN1FH~ct%7iA(N%>8xMJCI5 ziv6amt2^aqoIzi4x4ol2vywCMZO_=)c}fD!&MCIX772J}jTE_yJ)0@A5UIWTvX#@A zI2O&gSv32P$q#KuvfIoYos8_2#l=j_k6EQM!VYOGDiR6tQ8-zp%53*v_h6lr34pNp z;va2bL3G|!fyG8Ap9B-ACKKkQMpXftGouOYIO^RMjP&)rVQHTlOhv-k?{fYzrNho2 z^6FoboI(Ozwl7of(>&96XS~?5w*z0KhBw!<3-c9V3**G&sK2yIN!7Bcqxoy9*VMGW zL!}xGh(8_p=`UX7*{^Efe(9u}=tN8A6s8yP_ z|5ebKqFz52G`~f?elC8dc2N5VwFBBeQ#+{rOzoidFHsuM|3rasmUj0a`2UL-4U>OD z^VS4gKo1%bP)0vyu0#bIhIMEU&}YFKr{tx$(BWm z)Vu|CNkY45vF3j$Xki@n`e#w`{q8}_pNszn9oj;Hdi`AdOzpqO+-F#H#Z1;55-m2F zPEQ9joQlm^3+ZPQ1+`k2&zyN^Iun^&zxFJEWkB@WcU7Z!ZY(%ji@7*M$?PYX3=Z!x z`GeBFit0>p((&@%VK$%mlZeO0>lXRB!6B|mAa`2e8|+wtRr%j<|5&_J-=bOyHN5>1 z{U3R*4^K$|@EX?nQ*Jfmf)apeg|MWoo$ny`;YN83EeEO}Xr$5^r!iP*27YB>8H0lJUaLvkXSZi#h17n?c4 z&c}`Cnp`eiYQ1kW?xuJwlnW&D0k**II{jhH>Z6KRpoyPKIG*&=)NCq}C}LuG|#Lr;DofPUq5Bjo0|tD^a_Tx-p~5j2*7HIijnpZ4&*s z$g}cgLsJ;{jgOFJeBblP)-A(1W-fr+*xDga;iatGi5k{JS&%Qk7taK2Ef3_oIY)JZ zl1HkHkrysDzu_K{u2n0@xExt*ttsxs!Y%1wchhGk8o!eU$sm%Z4dY}Z&y`pIT?=9c!4iRVFE=1^$8n=wPE$a(o1kk+Vy zTDJh}lGW^~tJluU=QAlGJxm7!-RGopPruShIOV;#nTkBSFY7rqM7UEq zm#KgJi?uLgs!=`8F1~dWVeez+94p86!M@XNu@GSS_mNbN;bNm3F`>Wt^_Dr)*&`;$195h$TK~= z3=%nSLs=6E^|;6lb-C*028fq*{^?hd2J9V%6rE~*9yI*9fmZ!VPwC9nkAm&4hmqOs z!q&|n zpoJ?D%s%9f?a+*qL3NgchUg)$j1@WLit$!U%fJaXXSZbDUXE26pZ6;fJ_b^iX`cS( zNskcd{BT0jHADu#_^wppnu(V4%qs@qE(YJ|tnP&i<7FzO6rDiPpHy*KiQqOzl||4g z=BQQ|5o^w;?Hb)k9WHR!Dgq>zw);5URrB>p168-yX?c2YdJ)>%3h}_s_O{i?(Ng#L zUCtYomy{M5fRjT0EIQx40$p0ovBf?@rO0l%#`M+R9fB~t*gGDom%cd;I)A0mZeuLm zQSR^X63yreZGFb18Xn`JBLT4#YN;<%bv_X*a@ zwEB>eq_HYzw)O7bpeHuly{Ymt_!YP_1)OKlgB=W%7SYLD#>4E?+0;h}W4?GGH(r-1 zp#IaQU1p@96riV6E1opwvhwO`tVFHt8!^r5{tO~PuRH@2e}&3QQ$ea;b;cF@h_s-O+(1sU;+kdzd!7Q3Okf|}KWewTPW)K4PyyVxB`xfiTC}>N{ zZHN}dEZiBa2;0S-KqZ6yP9+dL)qJrg*yVc5sAG$3opo0>iF<_A#8Rue8p>x3ctONS z!QEwHv^T)LM#1Pz8p10Lgdw^i=39}3^Fa5hv1;%F^85q=o9|@2U$=m*FM>G?W7Dm= z*pd|uAGwg$3bpyJwJ^iHzl}Lky|=9V{>Ed3lXek#Zg89r4TRgGF8r8c=pK#IB_|P4 z^KE8Et*JW8Ru&-aCu{H2aZjo{p8-uwOl>@AC=aZo%=qUDhF`0F-;c9mY98d<#KNbq zGK8>*@D9!rYZ6fS8f|7>?^q7l6PbL<+}R}m0 z8!K=3#(_n}um{5gmZx^+>ILNSR_h%F0c>TwQF-055}A#2;FsLtURLPF=jt^T-8fgt zzUc)1z~FRY>qqtNbM@q?xd*ZMo=Ga@oZe8$2QiPzR@e8aHAzQo)}nfw+Maib9$L`t ztgfQxbUWrrESm69es&I*E}FACSEwk3UCrIaC!X&uYFJ@isYb)WcKoTlUjz7Ekf#YN_KxG8+On({Jz{ z5wV6+->71b1Ta4CflCJro=MwJrmKH}Yy4omDHzq|!n?oJ1y%(n-uQIO7Yk{C?27U} zaUJv>Yj=+pU$5q|LOQ^l9#tkW51a8$cr0~<={L>mLeFI$l5^Z6=P|QWPrPow2EeAi z90Y=oX6TF^@uLV87Sq^ZA{_8Z?{Zf6xA3qd8YX*`Vcwkgc?sx}Y4gvsJF6_NS|^Ri zv4!PUhXs&@h-_o%<-VPl1q<{7+6C|ePovAl%{sLr$254!E)N@q?l1Z3`-m{dDd4d~ za>egQE}{YFu6tOc_wGWq_Xi^opE3Zg#p{|522Q^{-S|of1W%i>8fdc^J?thy#Ldhi z#TOhDIqEW`^c%D00KZgan5Amju(KNG;o4uS%k5!@0&Wyz8YWH}^-y+{mzuswaS@-P zB7$Mi3hmCgA$I9&EJi(DfzA(2Z>{3CfT8+B*IfFKp@^ zi2aXMfUnKDv?3eth1hJr;GrNkX(`4=w>n3&`&G3rv+3(hx7KCDv8PVD$1=ke^R+Hl zBN>6m{A;H{CK$tukIY)Qcm1#%(^x@pq_S%>947O8V{c$rob?t{(f*1DYIfKWYr_-l z=w!GSp;cH_t!8Js3z23&Dq`JQjw!w}%(5TN|0b8sFntgVvrzMUXtsPRVV@%g|ETEO z(6Mwhqe)LCi+P}FqLvX!KPJk_)o9ree%z#|Ez!_~4ZV(KqKd3$cBJV>knCm!g9v7@ zQZ=(VV;)FWMn#CMdRshQjWbX-8Re+Tz@@Ilv+Fo^d{BO=KH>(8osCn81jw>iWo(I$ z2paWo4CrQy9EGc1&%6V*Yf@Z39P6?YY0IU%PdDzk_9;|r{MD(dna%XZU36-cK6Y8r zGGE33I+@&Be^DCjXi$aw8qO%-N-|4B=Fc@F^I;yh16w*@)m}VAq5$5twmM?#x0h8b z7ow{30N}xtYa@j1-^Z96QbvqimX>z|^$6DkI(O##)>EnJ(W%+21wmIvpCQ;uzN{as zCnZ+}`Wnovh2UYc$>x2Vvo$rHWkrYSXNp2p`WPE6I)~3j<%SU90|?8@7l_55PePoK zz2iE!TD?K1@;@z9b}mPq%az4F=O8K3*V(M;dm|sDr~$`OF$i*+iO|k9B`Pm5wWE+ zi5gSF9%ciNZCD8d-7Lw<7v*j{#84v?bZsciOSLW9lx%!iwiHFfu(JcPf(yrh8|{BCUGMWy7av{p=wp4;rQDVlmtLFp zY^09xptiMqoFMJ@FK4-Z$wM5GfTycFK0ixA_cEeS)Yvt=CpO;^2^#eFf?-5it&X_5$53@L&FnO3=HFV#(DBJz$HB28z zWo50L)FZRWJZdYM3VcAz!hApHR@ci({yPBaqA!x_heby3*TKGg!p9A5Tk7Z?>6;D# z0?pMK*vzd+GvRrCl>Po_ZTIwfTvvEUQp4!JmFnOb+0^hz3U^qMu zy)|nubY$maHH2*&Qhi&Uhh0O<9b_}?Y*mK8^0JDEm(R?`Xa4%WY|G06fSIl$znHSk z^|7e6a6`h1Z%7L0>WGB2_>HrXBb&u(jJ`<*;`Of3Ef$nF1CwoPzwmuZeo+`3A8DKL z66RC9x%LFaBMR7Fk22wxR;PCv;G?I`EEkbIBc!QbmFidSVY?`#E72M zQL&(E9*A?p`z>py46iQ@B?W(XbA?I$;&~86EnsJ7ES`ta0W*;^3i90ZKG-zKwek(q zwDaEO5d6RaZ!NgUH_VY3A#1DL_Z0Gc9g$$d7N7rav!&w0M}J)BFHH9+#E~83YEaCu z$lmt!=NkS<%uz<4Ah+RZusq-LlTz~%rzr@6U9~fH^Em-oi@}T{viNGftn$;ksM*myhZrdrGmh5g}y~wUn7fbrPwNaN=F-kW^(sC_IC$ zvg~)LIp}hfCr-LMw#?kLf!c%r88Gh%m$w@3?0~SRK=wSab{UH2XY0EbpRc<{LQ=!d zaUJi6_XL*N;E-RRs>ueuYu#311?~uwBCuU2qxY)HlWMNo^aJ42F%|qkhgME^RZx$k zx_}hoDgi;=n4As zajm8oSijp}8C~br{Q8|Y!y8^jiwRrDPVOGrJ#FO$D7fU3Qs90{B&>NF7t)3G*(IbT z`|-j4+#$-f@MUhyaEV{n)z!@3ZV8qj5scOvSajMC$Sq`iu|C->U2*qva{f3j$lfY1 zxD9bF0VVTDE*^l-9M?@YhGKUIRWq8SO$uw)(p#nI+??;z#IEBBVCUn>hf~=llP~#etDy=Yz`%NGs1Fn8`xK&Zb~FRM+J#`w{^2NP$80{_(^AbS=p*!Y`3AAh`+|Oe8XaD07P_zg1u6^4zU3KS|dm(sd_mPYhzZ6 z?#qPum^fQ4B+LQJKAE6p^I!$1aa~Zv^Lr{b)vZGTN5g%{nf7re%4tJxF^R9v(>OHJ(eT}~v z?oA%`KdDY~pp>t&wrL7b1vA!U#ui()<$t5#)|`NjK`6}LkY9ad?HkI{X-=Sb#AKgP z7)*^<`~Aq=CdLjWmh*j$K)sR-HX=bo6n4fTxllX?TVSr1I@Vq8R-J8R!wvf zepN;(unt&mW>B7sd~nz$^`-KNh2=iC+?-n*roY-&YZta$dv#FqVy#uILp7)FDRXn; zVnk%(yDh|icuB(_JH+?B>0Meed2cqe6>6SuH6_=&ZLBYu^#oeg{;abAV1RUEtIDghHhfg144o!BuXbIn5 zA1SCMu8`bTn?=XPe=Bvcn~TKoG>;M6dR#}{a61mm2`s6p4^V}K{%9=$i50P_mpknP zjx5>^I~(L|M;tm=WiIyGU7IBEcmt!p-B_^|vP(0ML(vC}v$T%Z7Ldlt?yS4(*`L(L z4pli%HAv4&YUQ}3>StCg$!}qZ@S!>|GG&!JM%3e}shi(yo1kqOx5vU}2x8=n$wGx| zYP}o;s#pK*o?ua7ztf_zsPGPHbWILnyxXcSu4>g+2o zvRG_&#NSg%i)`B&d#Ke)!K$}&Mvs->4JmRF>-*GPzByq4f2Qh@oT!H&4n_HB zKD?T$@jL<6kRGBJkg5i8b1>Q=C`;pQ-af+UhyZdLeG^lmFxTz)GOK115?!}HQs)(& z+RvTZW7)Eb^x3wcJ=v{6&ZDIZZC7946J+fXQ_+B}&q$)N%thc;!J>}y{W+F%9QU;H zqb284^kWLg**&`ob`~408{{$qt|n{bMv{w$H-Rjo*2KaBkcbaq;HG`#4E2E)G7&%d zm2KI5Wr93D-;V=$>Y!tSqP4T6mLzxHx$BWBGZh=Fsztc|YwtJsD$BCSS%CEkj>O-9 z4%|Q(ctW!J&8_180>D1v6l!1Nk6i8n-z?H^ z^5+yn%|U-ZMnua+AL80xU|8Iv9JQBoDg2)$F?|0xjzmp{97jbTTbv*ttL$2QwEE}v zBsF(IJ!AYMhe7T1kJD(r`^$96-_tw^Uytr7{zwo}+hcdg;Dcz~ z?rc^{aLUQ%I3>;s*dL+ihp8eLtP{?=(q+`sexa-)WMD$^RCw`R_DIgZAGj;eW%o1OJyylay>8 zc>&t+&h;U-3|7u)T<|^k#Nyzj-;eJmlzyt6{&B?c*B{RgYR7+kcJXuV$d40>2hR>_ zhktyo@pJ9a!I8#;PdUEV4p^c4@$6^Dey$y`@_z%Hp9NU`3CCG)Jfp4@>FCt%Xx%Qn I_4L*M0CvlC`2YX_ literal 22081 zcmeIaX;f3$)-Ftyrv#-0s%)@8h|@k4o~vd zreSZ~eG5O$LF;{MbJvO?QEF|RIENQIZ+~@O{GJqY@BN>D+7?&-fyO|d5eRDp+8%<+QL^r1qa&q6 zNAp7QMktnooTF1>KwDZr*O3RK8}eh)jkcq8`xNZK0^GT=FwBZcOhh2kIC*DgKPbiKG3+W})=2 zB^p^L=f9L%A1-L-vMC77;mfbaJ(|6l_|)Aa$t+I!ebK7zGc(-zDvpbnDPu}ar(8p` zk61O`%CG%pfHH}Rv>qn*A$j*BGLIaC0w>wcKBGDF>!`lRB5qoj52}&IUiMqxt&rYR z6)9A~%b_SKRMJl7vUq!Fxu^&fqt3wkZsldrrgd?P9qIHq1@l|=CwLuO&tC?hdVkyd zk<_o;OW%hDka+UlNjX<=kKve``TGl^-AkfWN#U@{>6VGI-p(P468{@hNIRZlLs z40H7VwaS}b5W7DNoY%7a&(eH4C?y6u-|=?ZD5>Q~f^kuREQk)Hb9v+V}zX=UIBm(e$v*!}Xj z0q9y8g#WZe4&4wj()w1wz7}QBd$5Hxa9r%|a<$=UzHFJU$He>r`^kJxWJ5%DTEVhmFABfzaC4 zV~}Z1++jFi(E3DO_{8fAKA_6+yn#~E+y1}QOx?x=Z=ljNLPwX7kr8Le8?;T!3Yg(0) zHpbI!R%Xt^hZ;GajWO1Sw$b!9dBfB6I@OTL=N_w~T+#RckZ9&7-1AOOm4jyZW@jvb z;klIshrq)|lK+TMaUB~s4%`uAceiN(;m)=XJ^JC#32D7UX6K6rd!dNSzV`1757`CY zlovBml-3;(tYGva{Vedhj9T@2EYMU?@`t{knSq}T%kR)Av5iT>{fLU1PHI!1;_P(f z760H*w~!O}yXiw>R-RqOT$3pbT1w>LCN?zo@eJj?m;YEsM)!yIhmgbkNgsIKgwP)B z1;5UrldT`DZ^|4EoWU~cy{^_m zb6iMzrA2gH8_3(t!a0x+|CMf%m{|pl>^i*9EkU6JT~zg>aBDR5XKRzNN3BZ)J|(Kk zdAX7?xPCtDw<>it2gq>_S$a8tr+-hW%_6({U@@$fjl>rDAQkfu?xx$--oCNV1l}E= zD}NYV^*dTu`s2|+3$w=yu|Agc`t`3Dp`^Uvs}4)O`aj7%(d}OM6r|lj-EP+h~@(iq?QGU!O68<^C`A|zS zaxhlzm1aIu@YO_IS0p9?g;$xYrH2@zwMqVr9+cQ*-|y-@J>T0&5p1q{lMdl!)n4PD zM6KA0>P}bs_uvOZBD4#5OM&)!@Ex}Os(Qm6IPEDcH{W2ZdYCz)Y*3bwTYKtg{UBVF zOfK+BB~~E#H(g{)u>2myjW~(0QleIfe9E*#xi#Mj)3P>M+@}a0FwG>;%#wytMtiq}z#&TY42}19|;RM{*akb%6(ZW;zWT z#|Q&9ei>+f&P?X_`ZR=9X3O**Vob5x_+CiF293fPp6>^UTZgm&?jpXi;>^~98dohY zRZ}Ur-`94-^hO{hX1mLX3!2_yTJgs$Wxe@=Wk}N;*CTR0`AN*83R4}@yts@L+Lf*^E8u zW@W?mBM&@_#ji5w5sa5E5#7jo{EupJ9VLM7tPylozdvaCpbY%tC0`pjDj1TpU2%`Nw9_aBfO@+w!1RLq^b`Do0hZ9Im4Zmh%M+G8jCl_PQ!Yh^H4s3ozetyuPaI zyIdA1;*MuTbbHu(5w(CiaSjs$8tAr#QZL&T?t&V;*!7&3nLlj{CJcDgl6U>XeI`%G zS-6@3P((!s^KIv(kMF7SuDh{2xALrLQy9F^okZb))^;P6`#6wk%#*Pd-^gpamrD@% z0(6#V1I0+=(#(0p{CtX+l}O)Cn5e9ocg< zDCYvZvqr&OrqrSAW=bfY=Bodbxs3l0raZ|gTSLPAHRBY1et!MexR1~uK9?oHC62@h za`i?@EuMy14vou`10kC@?Eucnn{Q_utMVty0+tf`G8S&)ht`;ws)&9v^ZKv29!1*# zM?+ADphm$Ec|K+%*{}o!Yz#0Gwtr63tZlD=z7%AY91WvQTxzRuO{v|# z5&3J|RgRgCzG0>Il#;m&CJHr!BaXl*o*$QALiw}n!SO%D+Aty;Cjb$8x#xqeW5i56 z&Ha>Q2DI=L;i_|Uv0nap-|&m?iMCO2VseBRcj=rpdytuSuhwP;EB)M~YZM9GDdU6c zTX(Q<+yrLTz69i3>=@+YTnA=+pG9lJFl)_a&Wuv>vD7!Ux@P=0hyy04s_qF9z=DS` z!AN8ev9ej<8#Q}e+u>VDqbmzDc@ZAu1nKQ|Zmwlcy zjW@%vh!cmGz!UH~!OU{O1Y`)9@v$=SGZWd{Ls%~Q4sr`amGOcomABXTi(f2GNKu= zluztlkBF*iZQX{#Du|*1CNBxGJHvR1sJNF45hep^ul07o*;yw$*x_0)Gy^ygPx`5S zntJElarzC8{XG7V737_d(!-?5kKTcrV-lOaKDeK+@Atu}_NHHm5dC6Iv?kcnv?Ly7 z4EU4(S`vBfFC#(k>LY^Z{~WUP%fA`UA&i0JwO;i115A;fR6X^d)iUnHr&?}I{v0uO zcH$S!21PWvz~k%t4Uthx;H7{xlo{u6vS+1d=Oo;#;0u0m@CzPNCw?Aa5Tb8?)N%Q8 z1JhpvbDWDOhw845G%PLAIyHiVg1dY3L*)RXb-HZB>D9VNHMr&y0%YVYXnD+_%j8<@ zTSt1tBI}VOLxJh^zE2&<8cka*nGt-V3h5hg>$mN*OdI%u22M20)gyq1t4XtZc_DqX zHmq9n594(K>-9>5u7E3J)?b=f%46g3rSvo9#2{<(l?|+xM!Z6qjb9gWJ;SA|i0W-I zHxk|wQ3>Dbwi167Q#$ZzeJa1?MiiUJ$UMIuRe6)eK?tr#3@ZK7JKdtiHpBOo7QD(% zXHHZk9@uk1_fEvft<=@k#j2jXYi{5B@B>k>D=R9u*tiNCEOvy3d`XV@ME_Y@c=Tcb z?D*xs-m-yMZMRkz z=9(^8{_k({zkKPtW#xF{{EdkDFS%Rajf{-^-239iq6n0Bl$wEhY_)A+Smf)c^7x>A zX)58#EHb7XDr&EVfeb1nijrb9<82`vUQd`jRnEFyQiq_%14^Q6ZI^qY)|3f$hhCkT zAnb5ys^uB22-U{p52Bo$y050cQVn_ed`fO#^MI<^DivV65^^s~iC-{851r`Li}4k` zmN?yH)Xw%ksHwQc9um2-`dt(1Ndrtq%~U_stJ~&`R(k1FLACl+MpI*Gkxpm!EN)i(>RrEwLGGn0j|)+u z5eZlXGx<>hI8fFqy)C4SI76<9m}UpClt`5?(hOQq$Z*a(r6HiMKJG@9zUz+h0xm6A z{mK)9$ElmzyCGzoLvBP{6gI4@*n#{|BjD+?p85dXy81aqQIkh1kHYmlx|T4?5pk{w#-29s z{KC^l4NtqWXwIB>Zdyu!feDw!=Ef^)ZO>G(~v6 zjbGGbVEV@ooDii;rTK4geqjGcwV>6-)Tzd3Uw_OWem_hUx?Zi_KLOQsb8r|g@9K$x z9S)ZkZx*mqDBEAb00wqlgR)vJj(ShMv=Syjh8c^1*p|>?S&|38PdOcHHaliKsI(06 zXnM4czRD%Y0Y2_bO1{X{(W#uqKuc1vjWxp;exTU{iZC0Yf~(aKBakC6i>L(uGrf|W03=7yLs~Az0MRhV zDyw73QGyw`Y9uIpdx4Ww6gJUHb>kcYzIv5iAfxu)PVHS+s$N~y8(v54!V5M&J#`Wj zjJSP6CLCVy)c{1x)oW|;8;Tw`Io7ttzelIDPmYv!_q29W-bD=A^NF5D0+Qa4j`g$D z$?BlpPzHJi01o>={OFjT_cnXsSdi>qRv=7(mTfB|nhaD8{z6)v=0+U(BOw)k?xFZQygXVLE5< z)yXunEYQ7~_9ro=!kx9T0BqrJy`m>S!Q9?k#oZ~BKJgr|b}*6@gQTwGTGw$sb!%U- z_aMHsNna~xXEv6-m79wk=pW75VKlBj?bid37kh^c3gYSdaLtnb{USm{D8fRu7(T^gHWf1dZ|b!)alsnk2w|La_=PuvIBPh3Fm2RGB>b zJ`3%Ey%^q+->F-ge~~$rK+Ti6+)-HM2`-fvoE|Qv=$Ugx_%Bdk|eM!-k znwG(4SlEt!;#>!AY_u@13m?cF<4GHj!MmGqmlYU#_2#Z(w4;36u9Q5ji74 zyM<;wgxyH!hc<}|5;Xu|3i|fo7?IVVrA?XK=+kJ%$QR=Of_g;>k~qR4j)+f?)2Vr( zScP9VX`HU1p&sn399|!5XHjAz9ozJA$Z@K4xdZ))h@ zns&-+bBYoaeh#-4%n+E+HqM+DcFVGbomAVPSm}wWBojK(H012!Ng8Xvdn6~xrD2Ad zt{gG*n8V?{e%ZunR&FrxpDvD^u2`oZLo^1#6GNe@_x0jZfwLp@Auo8(sI%9lR*#-y zBa=iYo$2xI7Zy+;bpib_$x~6h>qdVjTFObB37Rep7Y4K#R(jS4fidLHL>U;Y8@agQWU*bXMI2HwF)CqpSwy7mDaowY)d$>d zYQm&bbJ%u8$BU?SKCA*KzDawyCEzS8mH^hGf^r3IgxUwp5&s2^K@V)OvtP_RqDK^q zHgW~1ANR5RF}tqFgbrJsuD6LAXSE-uw0Tc{f-}ScOLeanjvXmF8fLoj{%R$Ytzzt0 z^JHWyJcDI&D9CGhAu1q%Io}&fJR@t&hI(;Mk?q|w@8q|bmERcJux3{v-e|jAp>`h1 zwubKn6xd_q;jr(Qp~FP7Y>h#*>`}-?WvrUd@WB+%}hy^pn@1R_>DGsl(Q`zhCoYzLiBwYT=mr zL0NY;G(EAuO>{fN)EZWXE>FQ|Lrw+4uX=h{{D%H4Eq?I{S=V-!o<(P2eh$hQ; zm;6T~??B8cg}zMd{5Hc&Yf~-ZqN^nzYQnm94y60(Y0bRyd^dL?AI{o{x|3f~=KQ|C zDo3!VpQ?w>l;korCgn(g;I2hqdWr(-VG=W(I7Z&`qr(c)d z!$mIpNbfxI)IW6^pp&;f*PZ7R6#>puk*h0zB>KE%uXrTW$)S9@&ZEJs&G-_28i2V~ z6GVM^;PA4x&Sb%d;lCV93J}dI_9d>r#%;4gOLS(ON)S~Mj$;R*B1LN@W-4LMa+ZMd-EIM^{F5WKRr zs=qf50iV14!-_*xzM)4-X}(_)rt=o`$rJ!rVCawE?r=02RhDbsZ5_3xli%}78gyrY zRsj~nHD{E|SdA-7OxzT6Wx4zBnu>@jU>46xC8wRcyw~q8>A{0NR3#<#A1uE7I{eNe zWhm;$zxx#c7v=uT$~*t(1)^^~{HIE7-z51>k`jym4;F8~Y1Ds*Ms4VYX#X!Rz@Eqc z4^-X1E!=;{!hKt;Z{FrVh}!;hq?>Q%|IPfrA%Xv7MD@)!|96OiqLelhdh)8JLS38B z*vr$WFYSBKZFu}82oyOG);vORq?UQMl?7I!yQku)&8|_Z|hZv|2wRg z`qz=~FYWy;bx-E&-`D?OgB$D^TPdkV0B*NSZ-aA0Y8K1o4k2T3B~nsT`?UTiTe9Qe zBdJ}_C|Xh0-%W;AXWL^r@PksHOl!aYKjlyU-*n}_!f_fBfqu+for=GfAibnjSS)Pc z2R9C6aH1tbfl0*vN#3gFv1lP>|1molbIJisn$b8pm6~X(vFntUvGsJJr@OBZ63D=s z=5yf2lG26jzkg$wqihCy@IDMMWNlE?0A$a?b~*^ObZA@X!{#H~D$<_O5Vui}Gmm$p zdW8j&At03`MATVnt)q5x^ox%*a|fdn^qf6%eo;}@iOXgp@G5W419Ff0m%x?s{j33r{-dH)K;W~_1XxHR{KtBmVSm{SAF-alRkHHGAD?a zY-@#e4e+o|+r;D|r^0qZf_;nb+gxmlwzf74O>wi(AXqll)!0=OZ(~>n6VRruFuQX{ z6ScZ5)xF%91|?6(fs{8Kjip!&YHquoR_Rvl$U zq5qf`(BzgcBBWp zJFS;erTHg~mt>3G87SuEdTO1s$>-0fcb4cS4OKdz>*)^alyNM#y{BM`M9FJu`xp90 zbcE6T-JpWhi)R+ZCs2&Jn& z*(hpT&v-tHLWHd>ejN)jI-nL8hAj;xV>M8dWb#KpTN_K+!=3v;Hu+}A$dJOjWv6f7 zl1yNviAUU6mj_1t=Iq>=A7OCYNgW?8>YW?Cc34)6P>wOnuq+yxm|RN6iohnS%+j2E7ckjekVG(zIWskA14lbWYi10A{b$|V3-H9aVP7vk=U!HSBL-EWMA#3O)qq6Nx ztOm0rM%*8}&#D1Zo`0G!KfgFT*PvTqy!FLa%Gs}J4{Y!5sRvm0}mKax3acCZkd_Sl2wg?9tWD(`O*r&!!_YLu#Au8G4UIe5`Va((g6$k_O1lTVK{$cmb64;8z8!Lrj;tOJ*Nw#R7l z_*1;ifreAfT1fE*uqY&#ErgZ0&71_B$p{=Rco1FWt7k(v-6Gqe8F1hO3cqn;9H?nTF zR1J8Z%r1|+OBzvHD$bH!xOO;RO_eOZ7+0ZxLWSb?C{Rx0fPzr-yDjr774M zc%-xnNVZ@s+ljRUCf6c|hGTJX&RS5BF>EPTo(GRZy%0;ht(Im0@FR@$3V`H`nrfFJz_U_P6s^Cve8P4-OvJ*8 z=kO^dtA;{CAhNb0d=OJ!`b-BHHTN%Qr}gl8lIW9`h456! zBv)YNMOZGkVqxGNy)wb>OA&oxS zEE{<}$n+LLbK(7YK#Th!wXp~Yr6y+3c9u5D$}hLkI5&Vlnx=o6{2-koRO{wl z{yOe#MybAquI_2IxE!noa(ibf7pBvTVIbz>dwY>4#-Yy2<&sjJA{_!H9FqFPvH3Zz z%3kMaKWwt@S4ypTt1_^{e-Oigx@XC$Ib;=sWMK`|E=?_GoBV9;1cd;=$tThDN*1?l z5{rPhFxBERp0~e>H}HB}45Emzz-qIERPyGhf~4>UF}yjF+)2(ERg2pm`}E0yyOHt+ zN**Vq%Bh{ZlZ-#&Y?|8ZCwX}H+_4uhMTe@C59lM7uJ2J}|8echnBkb8`G;qg{zb3j9@}#M z)EY{9spE7_W+L1}B`^pb?AVNMYBDr%xbs5aN54y&M3~~m1zABkD(n+j>FiAFT#~2T zi2#!Z_N9}kd@D_+&qCsD5YyG(TCzbHa{hfw!zrvUEJoOk$52+Ny~7g{{OU+) zt89s>1jXG66ld1kTHLe@G?PSCoLEWRw|OlCJhAoJs)gvlG8SvKv3leQ>6!^ViKj0)a}ZLZCw#PeuCB z0=HXE-N`Bf>T`|~2?kwdFet6nplhM)uC-sn*G<17mj;=My?raMV#W0FmP26ETpk|) zof&T_Z1P)=EKxFsyD?)=b!`u9X2e?n>fT>FJLG=Shx*R2fwPKM)YAvlO4Z9j1rkphk2SYToI606 z@Ay2s^}KxnRXo!4tbV2vE_a3fFW9v81z;P5lnB)Fn-Oddgk3mI80pxZ-P)2gj0-~- zRzmp&7OK@+jW0dm38P0i1uHMRF*GK!C6W069t-?nSZ`FRurZkvWpiWZ(ZV2dDw?A>+c zU5}Fw2|nd0MiWj!yo3x`f-}+hA$WNv zOYF~oY6Y^*H%5p?cHIlp;>vxw9a+#r1;#b>31`o7OqAZD19-U;C@fJ)@id07j?qH1 zy3sm~=*(k1(sH=)xzDep3*c0)hfX;ij4mpv6)}6c4`sL?1VXg(K@v3Jyb+Xaq%NT~mKolbx`nQYD1A@8p+|UwRd3Tqy zXL|cS_i|?Z1I4y{at-X{g&6MqrwRQMY4ku=`uoel^AeFyiv1|7KVjAp%Bwa5dS?>f zT^sEh)H!@@K}+o+krh_e5~YMu=1m6L=p0+Ri5_q!+rP^K_00t|VriMFr2{Ocu8vNH zLuX}RWfcm#HTnIP1B4LXtW0w^%atos>a$|@XMBXLSDh*9;vVfseJ6#bh!%4jBqS0K ziPHpsiBm|U(w@f~L48Juk&9Db&3~3aVaOwXKz>BiM|Vrf5rb!}N=%?mp3SkFx-XAzTzFGVhpWaswDQr6 zyX%sZ?GeaH#@yTiNFa2$f7Hg(Pqc1y!BUV+;U)c$;LVN6;o4MBgVfj5GxtR&~uLKTOSDox8**W&H7veFgI(M{!Tq5@)V z$?BwWZmnbs+S+b+kid-9`NgqqrR=85 zA-khb$*rE~AF?c0FF+-t&a% zc8{%1iY_|R1h>7@v=A#R!B6O>+DZuFPkkS&KrE6aSB1}jW9|=!&w0U7}(7IG2@=XgIQY_HvQ8f`Pku`{`Gmn zmo6DL*i}vl=C4tDKNAbUK9u5T&t(;X0)qJDL=z&^3l<28e6Tyu9R=y?Ib4&dwzU&8 zO>*Y@=;q%41xNwb)<&|Tl6cl|)s@Cg+Wpdth@A$paW(&ysZeFmfI3m#pM^)6!6FOu z7~|M?QM7^2U=yb!CHR<-om$%&$Rh@M1Xo@14pWL%w?C(ixAioRTwDBl=fVNCHV9qh z0VWwk?DDSgx2mtHf|Lz+z%Um8v(9?E|&GeIgo104$|zn=IO4j&MI+Lf3Adz+*%#z z5gD*DA0N70g;#s%3KJ7X-AFRyl(U3JR%uDSMNUn*E%b9VkDx905cu_+#3JTG_6nZeme;Q?^~rMa0&Mg<=ZYpuyd22}C$eVt=h| zS*7qgw|ZqQfK88?KaQ{vwvwQ`z^x(U3ruyleBUXY@ZpmtR~Kx^TCA4jkX~kA6-D@N z`D9u26WV}MRiu&I5}CqBDg-gSjV<)TflbI%CM(}$z*KLkH^3BQG}?z>bt}O zGW%-D#Iv~4XZQl*)a)(Vq`Wi3vXOTn$-`7jgqcSQfX7xr#cKidu9SIO+^RN zX>R9EbL*D`;OPrw_Sb%KIRBmE(4pkPfk8Z8_ekGunL;+PWC^f_prT+eQT*-A>e{Ss zzs!C@ApDmSNjANh<)O@PSf6StDnHi{b-%2>5@t_%U_frgF13u`(sitj;mC@|n`nu) zaw@pUi01ex6zcx{bIxh0mPJf!6`{P@ z_IRh8Yi;7bd_-SKB zGdNIa|7vCXQo(SR~}Yog9H8AXL=E|l+_PWU=90uL7$`F>j4nd%>H$}=M2qqayVCn*#Y_Y4ng=$aZq3QKh`o4au1hCtTGzlbUJQCS!0pWMTkj`ux4CF8WBh1Qul_2~0k5 zi0!e`*JOZV?hu1>UFvuEZ<5GXisP)AJ_xFz44REmoQ%`UOZm^bnj0jw2@L1*BJWcW zT0NJa=3?x}qmP{avwxocez&>4~c)k%WS|F*W_Xr0Tb9 zs4Ai1TBMOba^juq9VIBs0JOn*D5>rw*hsd#Szua_Jq$T2ERfJ?1r~Gi^8Y&(%l}IR zmKqNHd#O(i!JD(~eA6E!BG}#U^gktV<9{vmo?rx0F5m4@m;Xy^oc|4F)Nil&Z>v~; z6ZJPyOB}|3kOT2eqrPd>H;wwQU>AL}tZ$a}&9c5()?T_*^7()A7e9#udy@BJ1F8L7 zx0DB7-v5x&{>Q%?%Kkej_+B%LYwe0%(Ntn^JR-_&8x9R7b~B{D!GkLDB? TnuOgfC3X9T&2_Z-Z-4v`CCu=w diff --git a/lockscreen/pam/password.conf b/lockscreen/pam/password.conf new file mode 100644 index 0000000..7e5d75a --- /dev/null +++ b/lockscreen/pam/password.conf @@ -0,0 +1 @@ +auth required pam_unix.so diff --git a/lockscreen/shell.qml b/lockscreen/shell.qml index c873c68..c1e9b1e 100644 --- a/lockscreen/shell.qml +++ b/lockscreen/shell.qml @@ -1,38 +1,31 @@ -import QtQuick -import QtQuick.Controls.Basic import Quickshell import Quickshell.Wayland ShellRoot { - AuthContext { - id: authContext - onUnlocked: lock.locked = false + // This stores all the information shared between the lock surfaces on each screen. + LockContext { + id: lockContext + + onUnlocked: { + // Unlock the screen before exiting, or the compositor will display a + // fallback lock you can't interact with. + lock.locked = false; + + Qt.quit(); + } } WlSessionLock { id: lock + + // Lock the session immediately when quickshell starts. locked: true - onLockedChanged: { - if (!locked) Qt.quit(); - } - WlSessionLockSurface { - // You probably want to replace this with an image. - color: "#303030" - - // For your own sanity you should probably keep this - // while working on the lockscreen. - Button { - text: "Help! I misconfigured my lockscreen!" - onClicked: lock.locked = false - } - - Lockscreen { + LockSurface { anchors.fill: parent - context: authContext + context: lockContext } } } - } diff --git a/lockscreen/test.qml b/lockscreen/test.qml index 2917665..22dddb9 100644 --- a/lockscreen/test.qml +++ b/lockscreen/test.qml @@ -2,17 +2,24 @@ import QtQuick import Quickshell ShellRoot { - AuthContext { - id: authContext - onUnlocked: Qt.quit() + LockContext { + id: lockContext + onUnlocked: Qt.quit(); } FloatingWindow { - color: "#303030" - - Lockscreen { + LockSurface { anchors.fill: parent - context: authContext + context: lockContext + } + } + + // exit the example if the window closes + Connections { + target: Quickshell + + function onLastWindowClosed() { + Qt.quit(); } } }