feat(ags): use gtk4 lockscreen
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2025-03-08 17:46:00 -05:00
parent 3a55413cae
commit 44c0ac6f33
11 changed files with 18 additions and 317 deletions

21
flake.lock generated
View file

@ -438,26 +438,6 @@
"type": "github" "type": "github"
} }
}, },
"gtk-session-lock": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1713713322,
"narHash": "sha256-A9U/BnzdypE1rt53uhw5X4JQkayR8CkD2Qhn/vhmUSU=",
"owner": "Cu3PO42",
"repo": "gtk-session-lock",
"rev": "b9ddb2792b613d14622acada73c64f16a2635b40",
"type": "github"
},
"original": {
"owner": "Cu3PO42",
"repo": "gtk-session-lock",
"type": "github"
}
},
"gtk-theme-src": { "gtk-theme-src": {
"flake": false, "flake": false,
"locked": { "locked": {
@ -1652,7 +1632,6 @@
"git-theme-src": "git-theme-src", "git-theme-src": "git-theme-src",
"gpu-screen-recorder-src": "gpu-screen-recorder-src", "gpu-screen-recorder-src": "gpu-screen-recorder-src",
"grim-hyprland": "grim-hyprland", "grim-hyprland": "grim-hyprland",
"gtk-session-lock": "gtk-session-lock",
"gtk-theme-src": "gtk-theme-src", "gtk-theme-src": "gtk-theme-src",
"home-manager": "home-manager", "home-manager": "home-manager",
"hyprgrass": "hyprgrass", "hyprgrass": "hyprgrass",

View file

@ -127,12 +127,6 @@
repo = "grim-hyprland"; repo = "grim-hyprland";
type = "github"; type = "github";
}; };
gtk-session-lock = {
inputs.nixpkgs.follows = "nixpkgs";
owner = "Cu3PO42";
repo = "gtk-session-lock";
type = "github";
};
gtk-theme-src = { gtk-theme-src = {
flake = false; flake = false;
owner = "dracula"; owner = "dracula";

View file

@ -221,11 +221,6 @@ let
inputs.astal.follows = "astal"; inputs.astal.follows = "astal";
}; };
gtk-session-lock = mkInput {
owner = "Cu3PO42";
repo = "gtk-session-lock";
};
virtualkeyboard-adapter = mkInput { virtualkeyboard-adapter = mkInput {
owner = "horriblename"; owner = "horriblename";
repo = "fcitx-virtualkeyboard-adapter"; repo = "fcitx-virtualkeyboard-adapter";

View file

@ -9,7 +9,6 @@ import binto from './configurations/binto';
import wim from './configurations/wim'; import wim from './configurations/wim';
import greeter from './configurations/greeter'; import greeter from './configurations/greeter';
import lock from './configurations/lock';
switch (programArgs[0]) { switch (programArgs[0]) {
@ -18,6 +17,4 @@ switch (programArgs[0]) {
case 'wim': wim(); break; case 'wim': wim(); break;
case 'greeter': greeter(); break; case 'greeter': greeter(); break;
case 'lock': lock(); break;
} }

View file

@ -1,3 +0,0 @@
@use 'common';
@use '../widgets/lockscreen';

View file

@ -1,4 +0,0 @@
.lock-clock {
font-size: 80pt;
font-family: 'Ubuntu Mono';
}

View file

@ -1,241 +0,0 @@
import { bind, idle, timeout, Variable } from 'astal';
import { App, Astal, Gdk, Gtk, Widget } from 'astal/gtk3';
import { register } from 'astal/gobject';
import AstalAuth from 'gi://AstalAuth';
import Lock from 'gi://GtkSessionLock';
import Separator from '../misc/separator';
import { get_hyprland_monitor_desc } from '../../lib';
// This file is generated by Nix
import Vars from './vars';
/* Types */
declare global {
function authFinger(): void;
}
@register()
class BlurredBox extends Widget.Box {
geometry = {} as { w: number, h: number };
}
export default () => {
const windows = new Map<Gdk.Monitor, Gtk.Window>();
const blurBGs: BlurredBox[] = [];
const transition_duration = 1000;
const WINDOW_MARGINS = -2;
const ENTRY_SPACING = 20;
const CLOCK_SPACING = 60;
const bgCSS = ({ w = 1, h = 1 } = {}) => `
border: 2px solid rgba(189, 147, 249, 0.8);
background: rgba(0, 0, 0, 0.2);
min-height: ${h}px;
min-width: ${w}px;
transition: min-height ${transition_duration / 2}ms,
min-width ${transition_duration / 2}ms;
`;
const lock = Lock.prepare_lock();
const unlock = () => {
blurBGs.forEach((b) => {
b.set_css(bgCSS({
w: b.geometry.w,
h: 1,
}));
timeout(transition_duration / 2, () => {
b.set_css(bgCSS({
w: 1,
h: 1,
}));
});
});
timeout(transition_duration, () => {
lock.unlock_and_destroy();
Gdk.Display.get_default()?.sync();
App.quit();
});
};
const Clock = () => {
const time = Variable<string>('').poll(1000, () => {
return (new Date().toLocaleString([], {
hour: 'numeric',
minute: 'numeric',
hour12: true,
}) ?? '')
.replace('a.m.', 'AM')
.replace('p.m.', 'PM');
});
return (
<label
className="lock-clock"
label={bind(time)}
/>
);
};
const PasswordPrompt = (monitor: Gdk.Monitor, visible: boolean) => {
const rev = new BlurredBox({ css: bgCSS() });
idle(() => {
rev.geometry = {
w: monitor.get_geometry().width,
h: monitor.get_geometry().height,
};
rev.css = bgCSS({
w: rev.geometry.w,
h: 1,
});
timeout(transition_duration / 2, () => {
rev.css = bgCSS({
w: rev.geometry.w,
h: rev.geometry.h,
});
});
});
blurBGs.push(rev);
<window
name={`blur-bg-${monitor.get_model()}`}
namespace={`blur-bg-${monitor.get_model()}`}
gdkmonitor={monitor}
layer={Astal.Layer.OVERLAY}
anchor={
Astal.WindowAnchor.TOP |
Astal.WindowAnchor.LEFT |
Astal.WindowAnchor.RIGHT |
Astal.WindowAnchor.BOTTOM
}
margin={WINDOW_MARGINS}
exclusivity={Astal.Exclusivity.IGNORE}
>
<box
halign={Gtk.Align.CENTER}
valign={Gtk.Align.CENTER}
>
{rev}
</box>
</window>;
const label = <label label="Enter password:" /> as Widget.Label;
return new Gtk.Window({
child: visible ?
(
<box
vertical
halign={Gtk.Align.CENTER}
valign={Gtk.Align.CENTER}
spacing={16}
>
<Clock />
<Separator size={CLOCK_SPACING} vertical />
<box
halign={Gtk.Align.CENTER}
className="avatar"
/>
<box
className="entry-box"
vertical
>
{label}
<Separator size={ENTRY_SPACING} vertical />
<entry
halign={Gtk.Align.CENTER}
xalign={0.5}
visibility={false}
placeholder_text="password"
onRealize={(self) => self.grab_focus()}
onActivate={(self) => {
self.set_sensitive(false);
AstalAuth.Pam.authenticate(self.get_text() ?? '', (_, task) => {
try {
AstalAuth.Pam.authenticate_finish(task);
unlock();
}
catch (e) {
self.set_text('');
label.set_label((e as Error).message);
self.set_sensitive(true);
}
});
}}
/>
</box>
</box>
) :
<box />,
});
};
const createWindow = (monitor: Gdk.Monitor) => {
const hyprDesc = get_hyprland_monitor_desc(monitor);
const entryVisible = Vars.mainMonitor === hyprDesc || Vars.dupeLockscreen;
const win = PasswordPrompt(monitor, entryVisible);
windows.set(monitor, win);
};
const lock_screen = () => {
const display = Gdk.Display.get_default();
for (let m = 0; m < (display?.get_n_monitors() ?? 0); m++) {
const monitor = display?.get_monitor(m);
if (monitor) {
createWindow(monitor);
}
}
display?.connect('monitor-added', (_, monitor) => {
createWindow(monitor);
});
lock.lock_lock();
windows.forEach((win, monitor) => {
lock.new_surface(win, monitor);
win.show();
});
};
const on_finished = () => {
lock.destroy();
Gdk.Display.get_default()?.sync();
App.quit();
};
lock.connect('finished', on_finished);
if (Vars.hasFprintd) {
globalThis.authFinger = () => AstalAuth.Pam.authenticate('', (_, task) => {
try {
AstalAuth.Pam.authenticate_finish(task);
unlock();
}
catch (e) {
console.error((e as Error).message);
}
});
globalThis.authFinger();
}
lock_screen();
};

View file

@ -1,17 +1,8 @@
import { App } from 'astal/gtk4'; import { programArgs } from 'system';
import style from './style.scss'; import lock from './configurations/lock';
// import Bar from './widgets/bar';
import Lockscreen from './widgets/lockscreen';
App.start({ switch (programArgs[0]) {
css: style, case 'lock': lock(); break;
instanceName: 'gtk4', }
main() {
// Bar();
Lockscreen();
},
});

View file

@ -1,8 +1,8 @@
import { App } from 'astal/gtk3'; import { App } from 'astal/gtk4';
import Lockscreen from '../widgets/lockscreen'; import Lockscreen from '../widgets/lockscreen';
import style from '../style/lock.scss'; import style from '../style.scss';
export default () => { export default () => {

View file

@ -5,7 +5,7 @@ self: {
pkgs, pkgs,
... ...
}: let }: let
inherit (self.inputs) gtk-session-lock kompass; inherit (self.inputs) kompass;
inherit (lib) attrValues boolToString filter getExe mkIf optionalAttrs optionals; inherit (lib) attrValues boolToString filter getExe mkIf optionalAttrs optionals;
@ -54,9 +54,6 @@ in {
wireplumber wireplumber
; ;
# TODO: switch to Gtk4 version to get rid of this dep
gtkSessionLock = gtk-session-lock.packages.${pkgs.system}.default;
# TODO: add overlays to upstream flake # TODO: add overlays to upstream flake
libKompass = kompass.packages.${pkgs.system}.libkompass; libKompass = kompass.packages.${pkgs.system}.libkompass;
@ -79,8 +76,10 @@ in {
name = "lock"; name = "lock";
runtimeInputs = [cfg.package]; runtimeInputs = [cfg.package];
text = '' text = ''
gsettings set org.gnome.desktop.interface cursor-size 30
if [ "$#" == 0 ]; then if [ "$#" == 0 ]; then
exec ags run ~/${cfg.configDir} -a lock exec ags run ~/${gtk4ConfigDir}/app.ts -a lock --gtk4
else else
exec ags "$@" -i lock exec ags "$@" -i lock
fi fi
@ -97,14 +96,12 @@ in {
runtimeInputs = [cfg.package]; runtimeInputs = [cfg.package];
text = '' text = ''
gsettings set org.gnome.desktop.interface cursor-size 30 gsettings set org.gnome.desktop.interface cursor-size 30
exec ags run ~/${gtk4ConfigDir}/app.ts --gtk4
''; if [ "$#" == 0 ]; then
}) exec ags run ~/${gtk4ConfigDir}/app.ts --gtk4 -a ${hostName}
(pkgs.writeShellApplication { else
name = "agsConf"; exec ags "$@"
runtimeInputs = [cfg.package]; fi
text = ''
exec ags run ~/${cfg.configDir} -a "$1"
''; '';
}) })
] ]
@ -167,7 +164,7 @@ in {
pname = "ags"; pname = "ags";
configPath = "${gtk4ConfigDir}/@girs"; configPath = "${gtk4ConfigDir}/@girs";
packages = filter (x: packages = filter (x:
x.pname != "gtk-session-lock") true)
cfg.astalLibs; cfg.astalLibs;
}) })
// { // {
@ -181,7 +178,6 @@ in {
source = buildNodeModules ./config (import ./config).npmDepsHash; source = buildNodeModules ./config (import ./config).npmDepsHash;
}; };
"${cfg.configDir}/widgets/lockscreen/vars.ts".text = lockscreenVars;
"${gtk4ConfigDir}/widgets/lockscreen/vars.ts".text = lockscreenVars; "${gtk4ConfigDir}/widgets/lockscreen/vars.ts".text = lockscreenVars;
} }
// optionalAttrs cfgDesktop.isTouchscreen { // optionalAttrs cfgDesktop.isTouchscreen {

View file

@ -14,14 +14,11 @@ self: {
agsConfig = let agsConfig = let
homeFiles = config.home-manager.users.${cfg.user}.home.file; homeFiles = config.home-manager.users.${cfg.user}.home.file;
nodeModules = homeFiles."${agsCfg.configDir}/node_modules".source; nodeModules = homeFiles."${agsCfg.configDir}/node_modules".source;
varsTs = homeFiles."${agsCfg.configDir}/widgets/lockscreen/vars.ts".source;
in in
pkgs.runCommandLocal "agsConfig" {} '' pkgs.runCommandLocal "agsConfig" {} ''
cp -ar ${../../../ags/config}/* ./. cp -ar ${../../../ags/config}/* ./.
chmod +w -R ./. chmod +w -R ./.
cp -ar ${varsTs} ./widgets/lockscreen/vars.ts
cp -ar ${nodeModules} ./node_modules cp -ar ${nodeModules} ./node_modules
${agsCfg.package}/bin/ags bundle ./app.ts $out ${agsCfg.package}/bin/ags bundle ./app.ts $out
''; '';