feat(ags): use gtk4 lockscreen
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
3a55413cae
commit
44c0ac6f33
11 changed files with 18 additions and 317 deletions
21
flake.lock
generated
21
flake.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
@use 'common';
|
|
||||||
|
|
||||||
@use '../widgets/lockscreen';
|
|
|
@ -1,4 +0,0 @@
|
||||||
.lock-clock {
|
|
||||||
font-size: 80pt;
|
|
||||||
font-family: 'Ubuntu Mono';
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
};
|
|
|
@ -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();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -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 () => {
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
'';
|
'';
|
||||||
|
|
Loading…
Add table
Reference in a new issue