summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdEnv.js20
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdMemory.qml128
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdSettings.qml199
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterContent.qml1908
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterState.qml30
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterSurface.qml34
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/README.md277
-rwxr-xr-xraveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-greeter424
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-hypr.conf3
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-niri.kdl23
-rwxr-xr-xraveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-hyprland.sh11
-rwxr-xr-xraveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-niri.sh8
12 files changed, 0 insertions, 3065 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdEnv.js b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdEnv.js
deleted file mode 100644
index fcce181..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdEnv.js
+++ /dev/null
@@ -1,20 +0,0 @@
-.pragma library
-
-function readBoolOverride(envReader, names, fallbackValue) {
- for (let i = 0; i < names.length; i++) {
- const name = names[i];
- const raw = envReader(name);
- if (raw === undefined || raw === null || raw === "")
- continue;
-
- const normalized = String(raw).trim().toLowerCase();
- if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on")
- return true;
- if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off")
- return false;
-
- console.warn("Invalid boolean override for", name + ":", raw, "- trying next override/fallback");
- }
-
- return fallbackValue;
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdMemory.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdMemory.qml
deleted file mode 100644
index da949d3..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdMemory.qml
+++ /dev/null
@@ -1,128 +0,0 @@
-pragma Singleton
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import Quickshell.Io
-import "GreetdEnv.js" as GreetdEnv
-
-Singleton {
- id: root
-
- readonly property string greetCfgDir: Quickshell.env("DMS_GREET_CFG_DIR") || "/var/cache/dms-greeter"
- readonly property string sessionConfigPath: greetCfgDir + "/session.json"
- readonly property string memoryFile: greetCfgDir + "/.local/state/memory.json"
- readonly property bool rememberLastSession: GreetdEnv.readBoolOverride(Quickshell.env, ["DMS_GREET_REMEMBER_LAST_SESSION", "DMS_SAVE_SESSION"], true)
- readonly property bool rememberLastUser: GreetdEnv.readBoolOverride(Quickshell.env, ["DMS_GREET_REMEMBER_LAST_USER", "DMS_SAVE_USERNAME"], true)
-
- property string lastSessionId: ""
- property string lastSuccessfulUser: ""
- property bool memoryReady: false
- property bool isLightMode: false
- property bool nightModeEnabled: false
-
- Component.onCompleted: {
- loadMemory();
- loadSessionConfig();
- }
-
- function loadMemory() {
- parseMemory(memoryFileView.text());
- }
-
- function loadSessionConfig() {
- parseSessionConfig(sessionConfigFileView.text());
- }
-
- function parseSessionConfig(content) {
- try {
- if (content && content.trim()) {
- const config = JSON.parse(content);
- isLightMode = config.isLightMode !== undefined ? config.isLightMode : false;
- nightModeEnabled = config.nightModeEnabled !== undefined ? config.nightModeEnabled : false;
- }
- } catch (e) {
- console.warn("Failed to parse greeter session config:", e);
- }
- }
-
- function parseMemory(content) {
- try {
- if (!content || !content.trim())
- return;
- const memory = JSON.parse(content);
- lastSessionId = rememberLastSession ? (memory.lastSessionId || "") : "";
- lastSuccessfulUser = rememberLastUser ? (memory.lastSuccessfulUser || "") : "";
- if (!rememberLastSession || !rememberLastUser)
- saveMemory();
- } catch (e) {
- console.warn("Failed to parse greetd memory:", e);
- }
- }
-
- function saveMemory() {
- let memory = {};
- if (rememberLastSession && lastSessionId)
- memory.lastSessionId = lastSessionId;
- if (rememberLastUser && lastSuccessfulUser)
- memory.lastSuccessfulUser = lastSuccessfulUser;
- memoryFileView.setText(JSON.stringify(memory, null, 2));
- }
-
- function setLastSessionId(id) {
- if (!rememberLastSession) {
- if (lastSessionId !== "") {
- lastSessionId = "";
- saveMemory();
- }
- return;
- }
- lastSessionId = id || "";
- saveMemory();
- }
-
- function setLastSuccessfulUser(username) {
- if (!rememberLastUser) {
- if (lastSuccessfulUser !== "") {
- lastSuccessfulUser = "";
- saveMemory();
- }
- return;
- }
- lastSuccessfulUser = username || "";
- saveMemory();
- }
-
- FileView {
- id: memoryFileView
- path: root.memoryFile
- blockLoading: false
- blockWrites: false
- atomicWrites: true
- watchChanges: false
- printErrors: false
- onLoaded: {
- parseMemory(memoryFileView.text());
- root.memoryReady = true;
- }
- onLoadFailed: {
- root.memoryReady = true;
- }
- }
-
- FileView {
- id: sessionConfigFileView
- path: root.sessionConfigPath
- blockLoading: false
- blockWrites: true
- atomicWrites: false
- watchChanges: false
- printErrors: true
- onLoaded: {
- parseSessionConfig(sessionConfigFileView.text());
- }
- onLoadFailed: error => {
- console.warn("Could not load greeter session config from", root.sessionConfigPath, "error:", error);
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdSettings.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdSettings.qml
deleted file mode 100644
index e1f670c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreetdSettings.qml
+++ /dev/null
@@ -1,199 +0,0 @@
-pragma Singleton
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import Quickshell.Io
-import qs.Common
-import "GreetdEnv.js" as GreetdEnv
-
-Singleton {
- id: root
-
- readonly property string configPath: {
- const greetCfgDir = Quickshell.env("DMS_GREET_CFG_DIR") || "/var/cache/dms-greeter";
- return greetCfgDir + "/settings.json";
- }
-
- readonly property string _greeterCacheDir: {
- const i = root.configPath.lastIndexOf("/");
- return i >= 0 ? root.configPath.substring(0, i) : "";
- }
- readonly property string greeterWallpaperOverridePath: root._greeterCacheDir ? (root._greeterCacheDir + "/greeter_wallpaper_override.jpg") : ""
-
- property string currentThemeName: "purple"
- property bool settingsLoaded: false
- property string customThemeFile: ""
- property var registryThemeVariants: ({})
- property string matugenScheme: "scheme-tonal-spot"
- property bool use24HourClock: true
- property bool showSeconds: false
- property bool padHours12Hour: false
- property bool greeterUse24HourClock: true
- property bool greeterShowSeconds: false
- property bool greeterPadHours12Hour: false
- property string greeterLockDateFormat: ""
- property string greeterFontFamily: ""
- property string greeterWallpaperFillMode: ""
- property bool useFahrenheit: false
- property bool nightModeEnabled: false
- property string weatherLocation: "New York, NY"
- property string weatherCoordinates: "40.7128,-74.0060"
- property bool useAutoLocation: false
- property bool weatherEnabled: true
- property string iconTheme: "System Default"
- property bool useOSLogo: false
- property string osLogoColorOverride: ""
- property real osLogoBrightness: 0.5
- property real osLogoContrast: 1
- property string fontFamily: "Inter Variable"
- property string monoFontFamily: "Fira Code"
- property int fontWeight: Font.Normal
- property real fontScale: 1.0
- property real cornerRadius: 12
- property string widgetBackgroundColor: "sch"
- property string lockDateFormat: ""
- property bool lockScreenShowPowerActions: true
- property bool lockScreenShowProfileImage: true
- property bool rememberLastSession: true
- property bool rememberLastUser: true
- property bool greeterEnableFprint: false
- property bool greeterEnableU2f: false
- property string greeterWallpaperPath: ""
- property bool powerActionConfirm: true
- property real powerActionHoldDuration: 0.5
- property var powerMenuActions: ["reboot", "logout", "poweroff", "lock", "suspend", "restart"]
- property string powerMenuDefaultAction: "logout"
- property bool powerMenuGridLayout: false
- property var screenPreferences: ({})
- property int animationSpeed: 2
- property string wallpaperFillMode: "Fill"
-
- function parseSettings(content) {
- try {
- let settings = {};
- if (content && content.trim()) {
- settings = JSON.parse(content);
- }
-
- const envRememberLastSession = GreetdEnv.readBoolOverride(Quickshell.env, ["DMS_GREET_REMEMBER_LAST_SESSION", "DMS_SAVE_SESSION"], undefined);
- const envRememberLastUser = GreetdEnv.readBoolOverride(Quickshell.env, ["DMS_GREET_REMEMBER_LAST_USER", "DMS_SAVE_USERNAME"], undefined);
-
- currentThemeName = settings.currentThemeName !== undefined ? settings.currentThemeName : "purple";
- customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : "";
- registryThemeVariants = settings.registryThemeVariants !== undefined ?
- settings.registryThemeVariants : ({});
- matugenScheme = settings.matugenScheme !== undefined ? settings.matugenScheme : "scheme-tonal-spot";
- use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true;
- showSeconds = settings.showSeconds !== undefined ? settings.showSeconds : false;
- padHours12Hour = settings.padHours12Hour !== undefined ? settings.padHours12Hour : false;
- greeterUse24HourClock = settings.greeterUse24HourClock !== undefined ? settings.greeterUse24HourClock : use24HourClock;
- greeterShowSeconds = settings.greeterShowSeconds !== undefined ? settings.greeterShowSeconds : showSeconds;
- greeterPadHours12Hour = settings.greeterPadHours12Hour !== undefined ? settings.greeterPadHours12Hour : padHours12Hour;
- greeterLockDateFormat = settings.greeterLockDateFormat !== undefined ? settings.greeterLockDateFormat : "";
- greeterFontFamily = settings.greeterFontFamily !== undefined ? settings.greeterFontFamily : "";
- greeterWallpaperFillMode = settings.greeterWallpaperFillMode !== undefined ? settings.greeterWallpaperFillMode : "";
- useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false;
- nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false;
- weatherLocation = settings.weatherLocation !== undefined ? settings.weatherLocation : "New York, NY";
- weatherCoordinates = settings.weatherCoordinates !== undefined ? settings.weatherCoordinates : "40.7128,-74.0060";
- useAutoLocation = settings.useAutoLocation !== undefined ? settings.useAutoLocation : false;
- weatherEnabled = settings.weatherEnabled !== undefined ? settings.weatherEnabled : true;
- iconTheme = settings.iconTheme !== undefined ? settings.iconTheme : "System Default";
- useOSLogo = settings.useOSLogo !== undefined ? settings.useOSLogo : false;
- osLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : "";
- osLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5;
- osLogoContrast = settings.osLogoContrast !== undefined ? settings.osLogoContrast : 1;
- fontFamily = settings.fontFamily !== undefined ? settings.fontFamily : Theme.defaultFontFamily;
- monoFontFamily = settings.monoFontFamily !== undefined ? settings.monoFontFamily : Theme.defaultMonoFontFamily;
- fontWeight = settings.fontWeight !== undefined ? settings.fontWeight : Font.Normal;
- fontScale = settings.fontScale !== undefined ? settings.fontScale : 1.0;
- cornerRadius = settings.cornerRadius !== undefined ? settings.cornerRadius : 12;
- widgetBackgroundColor = settings.widgetBackgroundColor !== undefined ? settings.widgetBackgroundColor : "sch";
- lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : "";
- lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true;
- lockScreenShowProfileImage = settings.lockScreenShowProfileImage !== undefined ? settings.lockScreenShowProfileImage : true;
- if (envRememberLastSession !== undefined) {
- rememberLastSession = envRememberLastSession;
- } else {
- rememberLastSession = settings.greeterRememberLastSession !== undefined ? settings.greeterRememberLastSession : settings.rememberLastSession !== undefined ? settings.rememberLastSession : true;
- }
- if (envRememberLastUser !== undefined) {
- rememberLastUser = envRememberLastUser;
- } else {
- rememberLastUser = settings.greeterRememberLastUser !== undefined ? settings.greeterRememberLastUser : settings.rememberLastUser !== undefined ? settings.rememberLastUser : true;
- }
- greeterEnableFprint = settings.greeterEnableFprint !== undefined ? settings.greeterEnableFprint : false;
- greeterEnableU2f = settings.greeterEnableU2f !== undefined ? settings.greeterEnableU2f : false;
- greeterWallpaperPath = settings.greeterWallpaperPath !== undefined ? settings.greeterWallpaperPath : "";
- powerActionConfirm = settings.powerActionConfirm !== undefined ? settings.powerActionConfirm : true;
- powerActionHoldDuration = settings.powerActionHoldDuration !== undefined ? settings.powerActionHoldDuration : 0.5;
- powerMenuActions = settings.powerMenuActions !== undefined ? settings.powerMenuActions : ["reboot", "logout", "poweroff", "lock", "suspend", "restart"];
- powerMenuDefaultAction = settings.powerMenuDefaultAction !== undefined ? settings.powerMenuDefaultAction : "logout";
- powerMenuGridLayout = settings.powerMenuGridLayout !== undefined ? settings.powerMenuGridLayout : false;
- screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({});
- animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : 2;
- wallpaperFillMode = settings.wallpaperFillMode !== undefined ? settings.wallpaperFillMode : "Fill";
-
- if (typeof Theme !== "undefined") {
- if (currentThemeName === "custom" && customThemeFile) {
- Theme.loadCustomThemeFromFile(customThemeFile);
- }
- Theme.applyGreeterTheme(currentThemeName);
- }
- } catch (e) {
- console.warn("Failed to parse greetd settings:", e);
- } finally {
- settingsLoaded = true;
- }
- }
-
- function getEffectiveTimeFormat() {
- const use24 = greeterUse24HourClock;
- const secs = greeterShowSeconds;
- const pad = greeterPadHours12Hour;
- if (use24)
- return secs ? "hh:mm:ss" : "hh:mm";
- if (pad)
- return secs ? "hh:mm:ss AP" : "hh:mm AP";
- return secs ? "h:mm:ss AP" : "h:mm AP";
- }
-
- function getEffectiveLockDateFormat() {
- const fmt = (greeterLockDateFormat !== undefined && greeterLockDateFormat !== "") ? greeterLockDateFormat : lockDateFormat;
- return fmt && fmt.length > 0 ? fmt : Locale.LongFormat;
- }
-
- function getEffectiveWallpaperFillMode() {
- return (greeterWallpaperFillMode && greeterWallpaperFillMode !== "") ? greeterWallpaperFillMode : wallpaperFillMode;
- }
-
- function getEffectiveFontFamily() {
- return (greeterFontFamily && greeterFontFamily !== "") ? greeterFontFamily : fontFamily;
- }
-
- function getFilteredScreens(componentId) {
- const prefs = screenPreferences && screenPreferences[componentId] || ["all"];
- if (prefs.includes("all")) {
- return Quickshell.screens;
- }
- return Quickshell.screens.filter(screen => prefs.includes(screen.name));
- }
-
- FileView {
- id: settingsFile
- path: root.configPath
- blockLoading: false
- blockWrites: true
- atomicWrites: false
- watchChanges: false
- printErrors: true
- onLoaded: {
- parseSettings(settingsFile.text());
- }
- onLoadFailed: error => {
- console.warn("Failed to load greetd settings:", error);
- root.parseSettings("");
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterContent.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterContent.qml
deleted file mode 100644
index fa82315..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterContent.qml
+++ /dev/null
@@ -1,1908 +0,0 @@
-import QtCore
-import QtQuick
-import QtQuick.Effects
-import QtQuick.Layouts
-import Qt.labs.folderlistmodel
-import Quickshell
-import Quickshell.Hyprland
-import Quickshell.Io
-import Quickshell.Services.Greetd
-import qs.Common
-import qs.Services
-import qs.Widgets
-import qs.Modules.Lock
-
-Item {
- id: root
-
- function encodeFileUrl(path) {
- if (!path)
- return "";
- return "file://" + path.split('/').map(s => encodeURIComponent(s)).join('/');
- }
-
- readonly property string xdgDataDirs: Quickshell.env("XDG_DATA_DIRS")
- property string screenName: ""
- property string hyprlandCurrentLayout: ""
- property string hyprlandKeyboard: ""
- property int hyprlandLayoutCount: 0
- property bool isPrimaryScreen: !Quickshell.screens?.length || screenName === Quickshell.screens[0]?.name
-
- signal launchRequested
-
- property bool weatherInitialized: false
- property bool awaitingExternalAuth: false
- property bool pendingPasswordResponse: false
- property bool passwordSubmitRequested: false
- property bool cancelingExternalAuthForPassword: false
- property int defaultAuthTimeoutMs: 10000
- property int externalAuthTimeoutMs: 30000
- property int memoryFlushDelayMs: 120
- property string pendingLaunchCommand: ""
- property var pendingLaunchEnv: []
- property int passwordFailureCount: 0
- property int passwordAttemptLimitHint: 0
- property string authFeedbackMessage: ""
- property string greetdPamText: ""
- property string systemAuthPamText: ""
- property string commonAuthPamText: ""
- property string passwordAuthPamText: ""
- property string systemLoginPamText: ""
- property string systemLocalLoginPamText: ""
- property string commonAuthPcPamText: ""
- property string loginPamText: ""
- property string faillockConfigText: ""
- property bool greeterWallpaperOverrideExists: false
- property string externalAuthAutoStartedForUser: ""
- property int passwordSessionTransitionRetryCount: 0
- property int maxPasswordSessionTransitionRetries: 2
- property bool fprintdProbeComplete: false
- property bool fprintdHasDevice: false
- // Falls back to PAM-only detection until the fprintd D-Bus probe completes.
- readonly property bool greeterPamHasFprint: greeterPamStackHasModule("pam_fprintd") && (!fprintdProbeComplete || fprintdHasDevice)
- readonly property bool greeterPamHasU2f: greeterPamStackHasModule("pam_u2f")
- readonly property bool greeterExternalAuthAvailable: (greeterPamHasFprint && GreetdSettings.greeterEnableFprint) || (greeterPamHasU2f && GreetdSettings.greeterEnableU2f)
- readonly property bool greeterPamHasExternalAuth: greeterPamHasFprint || greeterPamHasU2f
-
- function initWeatherService() {
- if (weatherInitialized)
- return;
- if (!GreetdSettings.settingsLoaded)
- return;
- if (!GreetdSettings.weatherEnabled)
- return;
- weatherInitialized = true;
- WeatherService.addRef();
- WeatherService.forceRefresh();
- }
-
- function stripPamComment(line) {
- if (!line)
- return "";
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith("//"))
- return "";
- const hashIdx = trimmed.indexOf("//");
- if (hashIdx >= 0)
- return trimmed.substring(0, hashIdx).trim();
- return trimmed;
- }
-
- function pamModuleEnabled(pamText, moduleName) {
- if (!pamText || !moduleName)
- return false;
- const lines = pamText.split(/\r?\n/);
- for (let i = 0; i < lines.length; i++) {
- const line = stripPamComment(lines[i]);
- if (!line)
- continue;
- if (line.includes(moduleName))
- return true;
- }
- return false;
- }
-
- function pamTextIncludesFile(pamText, filename) {
- if (!pamText || !filename)
- return false;
- const lines = pamText.split(/\r?\n/);
- for (let i = 0; i < lines.length; i++) {
- const line = stripPamComment(lines[i]);
- if (!line)
- continue;
- if (line.includes(filename) && (line.includes("include") || line.includes("substack") || line.startsWith("@include")))
- return true;
- }
- return false;
- }
-
- function greeterPamStackHasModule(moduleName) {
- if (pamModuleEnabled(greetdPamText, moduleName))
- return true;
- const includedPamStacks = [
- ["system-auth", systemAuthPamText],
- ["common-auth", commonAuthPamText],
- ["password-auth", passwordAuthPamText],
- ["system-login", systemLoginPamText],
- ["system-local-login", systemLocalLoginPamText],
- ["common-auth-pc", commonAuthPcPamText],
- ["login", loginPamText]
- ];
- for (let i = 0; i < includedPamStacks.length; i++) {
- const stack = includedPamStacks[i];
- if (pamTextIncludesFile(greetdPamText, stack[0]) && pamModuleEnabled(stack[1], moduleName))
- return true;
- }
- return false;
- }
-
- function usesPamLockoutPolicy(pamText) {
- if (!pamText)
- return false;
- const lines = pamText.split(/\r?\n/);
- for (let i = 0; i < lines.length; i++) {
- const line = stripPamComment(lines[i]);
- if (!line)
- continue;
- if (line.includes("pam_faillock.so") || line.includes("pam_tally2.so") || line.includes("pam_tally.so"))
- return true;
- }
- return false;
- }
-
- function parsePamLineDenyValue(pamText) {
- if (!pamText)
- return -1;
- const lines = pamText.split(/\r?\n/);
- for (let i = 0; i < lines.length; i++) {
- const line = stripPamComment(lines[i]);
- if (!line)
- continue;
- if (!line.includes("pam_faillock.so") && !line.includes("pam_tally2.so") && !line.includes("pam_tally.so"))
- continue;
- const denyMatch = line.match(/\bdeny\s*=\s*(\d+)\b/i);
- if (!denyMatch)
- continue;
- const parsed = parseInt(denyMatch[1], 10);
- if (!isNaN(parsed))
- return parsed;
- }
- return -1;
- }
-
- function parseFaillockDenyValue(configText) {
- if (!configText)
- return -1;
- const lines = configText.split(/\r?\n/);
- for (let i = 0; i < lines.length; i++) {
- const line = stripPamComment(lines[i]);
- if (!line)
- continue;
- const denyMatch = line.match(/^deny\s*=\s*(\d+)\s*$/i);
- if (!denyMatch)
- continue;
- const parsed = parseInt(denyMatch[1], 10);
- if (!isNaN(parsed))
- return parsed;
- }
- return -1;
- }
-
- function refreshPasswordAttemptPolicyHint() {
- const pamSources = [greetdPamText, systemAuthPamText, commonAuthPamText, passwordAuthPamText, systemLoginPamText, systemLocalLoginPamText, commonAuthPcPamText, loginPamText];
- let lockoutConfigured = false;
- let denyFromPam = -1;
- for (let i = 0; i < pamSources.length; i++) {
- const source = pamSources[i];
- if (!source)
- continue;
- if (usesPamLockoutPolicy(source))
- lockoutConfigured = true;
- const denyValue = parsePamLineDenyValue(source);
- if (denyValue >= 0 && (denyFromPam < 0 || denyValue < denyFromPam))
- denyFromPam = denyValue;
- }
-
- if (!lockoutConfigured) {
- passwordAttemptLimitHint = 0;
- return;
- }
-
- const denyFromConfig = parseFaillockDenyValue(faillockConfigText);
- if (denyFromConfig >= 0) {
- passwordAttemptLimitHint = denyFromConfig;
- return;
- }
-
- if (denyFromPam >= 0) {
- passwordAttemptLimitHint = denyFromPam;
- return;
- }
-
- // pam_faillock default deny value when no explicit config is set.
- passwordAttemptLimitHint = 3;
- }
-
- function isLikelyLockoutMessage(message) {
- const lower = (message || "").toLowerCase();
- return lower.includes("account is locked") || lower.includes("too many") || lower.includes("maximum number of") || lower.includes("auth_err");
- }
-
- function currentAuthMessage() {
- if (GreeterState.pamState === "error")
- return I18n.tr("Authentication error - try again");
- if (GreeterState.pamState === "max")
- return I18n.tr("Too many failed attempts - account may be locked");
- if (GreeterState.pamState === "fail") {
- if (passwordAttemptLimitHint > 0) {
- const attempt = Math.max(1, Math.min(passwordFailureCount, passwordAttemptLimitHint));
- const remaining = Math.max(passwordAttemptLimitHint - attempt, 0);
- if (remaining > 0) {
- return I18n.tr("Incorrect password - attempt %1 of %2 (lockout may follow)").arg(attempt).arg(passwordAttemptLimitHint);
- }
- return I18n.tr("Incorrect password - next failures may trigger account lockout");
- }
- return I18n.tr("Incorrect password");
- }
- return "";
- }
-
- function clearAuthFeedback() {
- GreeterState.pamState = "";
- authFeedbackMessage = "";
- }
-
- function resetPasswordSessionTransition(clearSubmitRequest) {
- cancelingExternalAuthForPassword = false;
- passwordSessionTransitionRetryCount = 0;
- if (clearSubmitRequest)
- passwordSubmitRequested = false;
- }
-
- Connections {
- target: GreetdSettings
- function onSettingsLoadedChanged() {
- if (GreetdSettings.settingsLoaded) {
- initWeatherService();
- if (isPrimaryScreen) {
- applyLastSuccessfulUser();
- finalizeSessionSelection();
- }
- }
- }
-
- function onRememberLastUserChanged() {
- if (!isPrimaryScreen)
- return;
- if (!GreetdSettings.rememberLastUser && GreetdMemory.lastSuccessfulUser) {
- GreetdMemory.setLastSuccessfulUser("");
- }
- applyLastSuccessfulUser();
- }
-
- function onRememberLastSessionChanged() {
- if (!isPrimaryScreen)
- return;
- if (!GreetdSettings.rememberLastSession && GreetdMemory.lastSessionId) {
- GreetdMemory.setLastSessionId("");
- }
- finalizeSessionSelection();
- }
- }
-
- FileView {
- id: greetdPamWatcher
- path: "/etc/pam.d/greetd"
- printErrors: false
- onLoaded: {
- root.greetdPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.greetdPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: systemAuthPamWatcher
- path: "/etc/pam.d/system-auth"
- printErrors: false
- onLoaded: {
- root.systemAuthPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.systemAuthPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: commonAuthPamWatcher
- path: "/etc/pam.d/common-auth"
- printErrors: false
- onLoaded: {
- root.commonAuthPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.commonAuthPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: passwordAuthPamWatcher
- path: "/etc/pam.d/password-auth"
- printErrors: false
- onLoaded: {
- root.passwordAuthPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.passwordAuthPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: systemLoginPamWatcher
- path: "/etc/pam.d/system-login"
- printErrors: false
- onLoaded: {
- root.systemLoginPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.systemLoginPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: systemLocalLoginPamWatcher
- path: "/etc/pam.d/system-local-login"
- printErrors: false
- onLoaded: {
- root.systemLocalLoginPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.systemLocalLoginPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: commonAuthPcPamWatcher
- path: "/etc/pam.d/common-auth-pc"
- printErrors: false
- onLoaded: {
- root.commonAuthPcPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.commonAuthPcPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: loginPamWatcher
- path: "/etc/pam.d/login"
- printErrors: false
- onLoaded: {
- root.loginPamText = text();
- root.refreshPasswordAttemptPolicyHint();
- root.maybeAutoStartExternalAuth();
- }
- onLoadFailed: {
- root.loginPamText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- FileView {
- id: faillockConfigWatcher
- path: "/etc/security/faillock.conf"
- printErrors: false
- onLoaded: {
- root.faillockConfigText = text();
- root.refreshPasswordAttemptPolicyHint();
- }
- onLoadFailed: {
- root.faillockConfigText = "";
- root.refreshPasswordAttemptPolicyHint();
- }
- }
-
- Component.onCompleted: {
- initWeatherService();
- refreshPasswordAttemptPolicyHint();
-
- if (isPrimaryScreen)
- applyLastSuccessfulUser();
-
- if (CompositorService.isHyprland)
- updateHyprlandLayout();
-
- fprintdDeviceProbe.running = true;
- }
-
- function applyLastSuccessfulUser() {
- if (!GreetdSettings.settingsLoaded || !GreetdSettings.rememberLastUser)
- return;
- const lastUser = GreetdMemory.lastSuccessfulUser;
- if (lastUser && !GreeterState.showPasswordInput && !GreeterState.username) {
- GreeterState.username = lastUser;
- GreeterState.usernameInput = lastUser;
- GreeterState.showPasswordInput = true;
- PortalService.getGreeterUserProfileImage(lastUser);
- maybeAutoStartExternalAuth();
- }
- }
-
- function submitUsername(rawValue) {
- const user = (rawValue || "").trim();
- if (!user)
- return;
- if (GreeterState.username !== user) {
- passwordFailureCount = 0;
- clearAuthFeedback();
- externalAuthAutoStartedForUser = "";
- }
- GreeterState.username = user;
- GreeterState.showPasswordInput = true;
- PortalService.getGreeterUserProfileImage(user);
- GreeterState.passwordBuffer = "";
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- maybeAutoStartExternalAuth();
- }
-
- function submitBufferedPassword() {
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- awaitingExternalAuth = false;
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.restart();
- // Some PAM stacks expect an explicit empty response to advance U2F/fprint or fail normally.
- Greetd.respond(GreeterState.passwordBuffer || "");
- GreeterState.passwordBuffer = "";
- inputField.text = "";
- return true;
- }
-
- function requestPasswordSessionTransition() {
- const hasPasswordBuffer = GreeterState.passwordBuffer && GreeterState.passwordBuffer.length > 0;
- if (!passwordSubmitRequested && !hasPasswordBuffer)
- return;
- if (cancelingExternalAuthForPassword)
- return;
- if (passwordSessionTransitionRetryCount >= maxPasswordSessionTransitionRetries) {
- pendingPasswordResponse = false;
- awaitingExternalAuth = false;
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.stop();
- resetPasswordSessionTransition(true);
- GreeterState.pamState = "error";
- authFeedbackMessage = currentAuthMessage();
- placeholderDelay.restart();
- Greetd.cancelSession();
- return;
- }
- cancelingExternalAuthForPassword = true;
- passwordSessionTransitionRetryCount = passwordSessionTransitionRetryCount + 1;
- awaitingExternalAuth = false;
- pendingPasswordResponse = false;
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.stop();
- Greetd.cancelSession();
- }
-
- function startAuthSession(submitPassword) {
- submitPassword = submitPassword === true;
- if (!GreeterState.showPasswordInput || !GreeterState.username)
- return;
- if (GreeterState.unlocking)
- return;
- const hasPasswordBuffer = GreeterState.passwordBuffer && GreeterState.passwordBuffer.length > 0;
- if (Greetd.state !== GreetdState.Inactive) {
- if (pendingPasswordResponse && submitPassword)
- submitBufferedPassword();
- else if (submitPassword)
- passwordSubmitRequested = true;
- return;
- }
- if (cancelingExternalAuthForPassword) {
- if (submitPassword)
- passwordSubmitRequested = true;
- return;
- }
- if (!submitPassword && !hasPasswordBuffer && !root.greeterExternalAuthAvailable)
- return;
- pendingPasswordResponse = false;
- passwordSubmitRequested = submitPassword;
- awaitingExternalAuth = !submitPassword && !hasPasswordBuffer && root.greeterExternalAuthAvailable;
- // Use greeterExternalAuthAvailable so systems with pam_fprintd but no hardware don't incur the 30 s wait.
- const waitingOnPamExternalBeforePassword = submitPassword && root.greeterExternalAuthAvailable;
- authTimeout.interval = (awaitingExternalAuth || waitingOnPamExternalBeforePassword) ? externalAuthTimeoutMs : defaultAuthTimeoutMs;
- authTimeout.restart();
- Greetd.createSession(GreeterState.username);
- }
-
- function maybeAutoStartExternalAuth() {
- if (!GreeterState.showPasswordInput || !GreeterState.username)
- return;
- if (!root.greeterExternalAuthAvailable)
- return;
- if (GreeterState.unlocking || Greetd.state !== GreetdState.Inactive)
- return;
- if (passwordSubmitRequested || cancelingExternalAuthForPassword)
- return;
- if (GreeterState.passwordBuffer && GreeterState.passwordBuffer.length > 0)
- return;
- if (externalAuthAutoStartedForUser === GreeterState.username)
- return;
-
- externalAuthAutoStartedForUser = GreeterState.username;
- startAuthSession(false);
- }
-
- function isExternalAuthPrompt(message, responseRequired) {
- // Non-response PAM messages commonly represent waiting states (fprint/U2F/token touch).
- return !responseRequired;
- }
-
- Component.onDestruction: {
- if (weatherInitialized)
- WeatherService.removeRef();
- }
-
- function updateHyprlandLayout() {
- if (CompositorService.isHyprland) {
- hyprlandLayoutProcess.running = true;
- }
- }
-
- Process {
- id: hyprlandLayoutProcess
- running: false
- command: ["hyprctl", "-j", "devices"]
- stdout: StdioCollector {
- onStreamFinished: {
- try {
- const data = JSON.parse(text);
- const mainKeyboard = data.keyboards.find(kb => kb.main === true);
- if (!mainKeyboard) {
- hyprlandCurrentLayout = "";
- hyprlandLayoutCount = 0;
- return;
- }
- hyprlandKeyboard = mainKeyboard.name;
- if (mainKeyboard.active_keymap) {
- const parts = mainKeyboard.active_keymap.split(" ");
- hyprlandCurrentLayout = parts[0].substring(0, 2).toUpperCase();
- } else {
- hyprlandCurrentLayout = "";
- }
- hyprlandLayoutCount = mainKeyboard.layout ? mainKeyboard.layout.split(",").length : 0;
- } catch (e) {
- hyprlandCurrentLayout = "";
- hyprlandLayoutCount = 0;
- }
- }
- }
- }
-
- // Probe fprintd D-Bus for physically enrolled scanners to eliminate PAM stack false-positives.
- Process {
- id: fprintdDeviceProbe
- running: false
- // sh wrapper: emits PROBE_UNAVAILABLE if gdbus is absent or fprintd unreachable,
- // keeping the PAM-only fallback active in those cases.
- command: ["sh", "-c",
- "command -v gdbus >/dev/null 2>&1 || { echo PROBE_UNAVAILABLE; exit 0; }; " +
- "gdbus call --system " +
- "--dest net.reactivated.Fprint " +
- "--object-path /net/reactivated/Fprint/Manager " +
- "--method net.reactivated.Fprint.Manager.GetDevices 2>/dev/null " +
- "|| echo PROBE_UNAVAILABLE"]
- stdout: StdioCollector {
- onStreamFinished: {
- if (text.includes("PROBE_UNAVAILABLE"))
- return; // PAM-only fallback stays active
- root.fprintdHasDevice = text.includes("objectpath");
- root.fprintdProbeComplete = true;
- root.maybeAutoStartExternalAuth();
- }
- }
- onExited: function(exitCode, exitStatus) {
- if (!root.fprintdProbeComplete)
- root.maybeAutoStartExternalAuth(); // PAM-only fallback stays active
- }
- }
-
- Connections {
- target: CompositorService.isHyprland ? Hyprland : null
- enabled: CompositorService.isHyprland
-
- function onRawEvent(event) {
- if (event.name === "activelayout")
- updateHyprlandLayout();
- }
- }
-
- Connections {
- target: GreetdMemory
- enabled: isPrimaryScreen
- function onLastSuccessfulUserChanged() {
- applyLastSuccessfulUser();
- }
- function onMemoryReadyChanged() {
- finalizeSessionSelection();
- }
- }
-
- Connections {
- target: GreeterState
- function onUsernameChanged() {
- if (GreeterState.username) {
- PortalService.getGreeterUserProfileImage(GreeterState.username);
- }
- }
- }
-
- FileView {
- id: greeterWallpaperOverrideFile
- path: GreetdSettings.greeterWallpaperOverridePath
- printErrors: false
- watchChanges: true
- onLoaded: root.greeterWallpaperOverrideExists = true
- onLoadFailed: root.greeterWallpaperOverrideExists = false
- }
-
- Connections {
- target: GreetdSettings
- function onGreeterWallpaperOverridePathChanged() {
- if (!GreetdSettings.greeterWallpaperOverridePath) {
- root.greeterWallpaperOverrideExists = false;
- return;
- }
- greeterWallpaperOverrideFile.reload();
- }
- function onGreeterWallpaperPathChanged() {
- if (!GreetdSettings.greeterWallpaperPath) {
- root.greeterWallpaperOverrideExists = false;
- return;
- }
- greeterWallpaperOverrideFile.reload();
- }
- }
-
- DankBackdrop {
- anchors.fill: parent
- screenName: root.screenName
- visible: {
- if (GreetdSettings.greeterWallpaperPath !== "" && root.greeterWallpaperOverrideExists)
- return false;
- var _ = SessionData.perMonitorWallpaper;
- var __ = SessionData.monitorWallpapers;
- var currentWallpaper = SessionData.getMonitorWallpaper(screenName);
- return !currentWallpaper || currentWallpaper === "" || (currentWallpaper && currentWallpaper.startsWith("#"));
- }
- }
-
- Image {
- id: wallpaperBackground
-
- anchors.fill: parent
- source: {
- if (GreetdSettings.greeterWallpaperPath !== "" && root.greeterWallpaperOverrideExists)
- return encodeFileUrl(GreetdSettings.greeterWallpaperOverridePath);
- var _ = SessionData.perMonitorWallpaper;
- var __ = SessionData.monitorWallpapers;
- var currentWallpaper = SessionData.getMonitorWallpaper(screenName);
- return (currentWallpaper && !currentWallpaper.startsWith("#")) ? encodeFileUrl(currentWallpaper) : "";
- }
- fillMode: Theme.getFillMode(GreetdSettings.getEffectiveWallpaperFillMode())
- smooth: true
- asynchronous: false
- cache: true
- visible: source !== ""
- layer.enabled: true
-
- layer.effect: MultiEffect {
- autoPaddingEnabled: false
- blurEnabled: true
- blur: 0.8
- blurMax: 32
- blurMultiplier: 1
- }
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.mediumDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- Rectangle {
- anchors.fill: parent
- color: "black"
- opacity: 0.4
- }
-
- SystemClock {
- id: systemClock
- precision: SystemClock.Seconds
- }
-
- Rectangle {
- anchors.fill: parent
- color: "transparent"
-
- Item {
- id: clockContainer
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.verticalCenter
- anchors.bottomMargin: 60
- width: parent.width
- height: clockText.implicitHeight
-
- Row {
- id: clockText
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- spacing: 0
-
- property string fullTimeStr: {
- const format = GreetdSettings.getEffectiveTimeFormat();
- return systemClock.date.toLocaleTimeString(I18n.locale(), format);
- }
- property var timeParts: fullTimeStr.split(':')
- property string hours: timeParts[0] || ""
- property string minutes: timeParts[1] || ""
- property string secondsWithAmPm: timeParts.length > 2 ? timeParts[2] : ""
- property string seconds: secondsWithAmPm.replace(/\s*(AM|PM|am|pm)$/i, '')
- property string ampm: {
- const match = fullTimeStr.match(/\s*(AM|PM|am|pm)$/i);
- return match ? match[0].trim() : "";
- }
- property bool hasSeconds: timeParts.length > 2
-
- StyledText {
- width: 75
- text: clockText.hours.length > 1 ? clockText.hours[0] : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- width: 75
- text: clockText.hours.length > 1 ? clockText.hours[1] : clockText.hours.length > 0 ? clockText.hours[0] : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- text: ":"
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- }
-
- StyledText {
- width: 75
- text: clockText.minutes.length > 0 ? clockText.minutes[0] : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- width: 75
- text: clockText.minutes.length > 1 ? clockText.minutes[1] : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- text: clockText.hasSeconds ? ":" : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- visible: clockText.hasSeconds
- }
-
- StyledText {
- width: 75
- text: clockText.hasSeconds && clockText.seconds.length > 0 ? clockText.seconds[0] : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- horizontalAlignment: Text.AlignHCenter
- visible: clockText.hasSeconds
- }
-
- StyledText {
- width: 75
- text: clockText.hasSeconds && clockText.seconds.length > 1 ? clockText.seconds[1] : ""
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- horizontalAlignment: Text.AlignHCenter
- visible: clockText.hasSeconds
- }
-
- StyledText {
- width: 20
- text: " "
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- visible: clockText.ampm !== ""
- }
-
- StyledText {
- text: clockText.ampm
- font.pixelSize: 120
- font.weight: Font.Light
- color: "white"
- visible: clockText.ampm !== ""
- }
- }
- }
-
- StyledText {
- id: dateText
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: clockContainer.bottom
- anchors.topMargin: 4
- text: {
- return systemClock.date.toLocaleDateString(I18n.locale(), GreetdSettings.getEffectiveLockDateFormat());
- }
- font.pixelSize: Theme.fontSizeXLarge
- color: "white"
- opacity: 0.9
- }
-
- Item {
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: dateText.bottom
- anchors.topMargin: Theme.spacingL
- width: 380
- height: 140
-
- ColumnLayout {
- anchors.fill: parent
- spacing: Theme.spacingM
-
- RowLayout {
- spacing: Theme.spacingL
- Layout.fillWidth: true
-
- DankCircularImage {
- Layout.preferredWidth: 60
- Layout.preferredHeight: 60
- imageSource: {
- if (PortalService.profileImage === "")
- return "";
- if (PortalService.profileImage.startsWith("/"))
- return encodeFileUrl(PortalService.profileImage);
- return PortalService.profileImage;
- }
- fallbackIcon: "person"
- visible: GreetdSettings.lockScreenShowProfileImage
- }
-
- Rectangle {
- property bool showPassword: false
-
- Layout.fillWidth: true
- Layout.preferredHeight: 60
- radius: Theme.cornerRadius
- color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
- border.color: inputField.activeFocus ? Theme.primary : Qt.rgba(1, 1, 1, 0.3)
- border.width: inputField.activeFocus ? 2 : 1
-
- DankIcon {
- id: lockIcon
-
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingM
- anchors.verticalCenter: parent.verticalCenter
- name: GreeterState.showPasswordInput ? "lock" : "person"
- size: 20
- color: inputField.activeFocus ? Theme.primary : Theme.surfaceVariantText
- }
-
- TextInput {
- id: inputField
-
- property bool syncingFromState: false
-
- anchors.fill: parent
- anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
- anchors.rightMargin: {
- let margin = Theme.spacingM;
- if (GreeterState.showPasswordInput && revealButton.visible) {
- margin += revealButton.width;
- }
- if (externalAuthButton.visible) {
- margin += externalAuthButton.width;
- }
- if (virtualKeyboardButton.visible) {
- margin += virtualKeyboardButton.width;
- }
- if (enterButton.visible) {
- margin += enterButton.width + 2;
- }
- return margin;
- }
- opacity: 0
- focus: true
- echoMode: GreeterState.showPasswordInput ? (parent.showPassword ? TextInput.Normal : TextInput.Password) : TextInput.Normal
- onTextChanged: {
- if (syncingFromState)
- return;
- if (GreeterState.showPasswordInput) {
- GreeterState.passwordBuffer = text;
- if (!text || text.length === 0)
- root.passwordSubmitRequested = false;
- } else {
- GreeterState.usernameInput = text;
- }
- }
- onAccepted: {
- if (GreeterState.showPasswordInput) {
- root.startAuthSession(true);
- } else {
- if (text.trim()) {
- root.submitUsername(text);
- syncingFromState = true;
- text = "";
- syncingFromState = false;
- }
- }
- }
-
- Component.onCompleted: {
- syncingFromState = true;
- text = GreeterState.showPasswordInput ? GreeterState.passwordBuffer : GreeterState.usernameInput;
- syncingFromState = false;
- if (isPrimaryScreen && !powerMenu.isVisible)
- forceActiveFocus();
- }
- onVisibleChanged: {
- if (visible && isPrimaryScreen && !powerMenu.isVisible)
- forceActiveFocus();
- }
- }
-
- KeyboardController {
- id: keyboard_controller
- target: inputField
- rootObject: root
- }
-
- StyledText {
- id: placeholder
-
- anchors.left: lockIcon.right
- anchors.leftMargin: Theme.spacingM
- anchors.right: (GreeterState.showPasswordInput && revealButton.visible ? revealButton.left : (externalAuthButton.visible ? externalAuthButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right))))
- anchors.rightMargin: 2
- anchors.verticalCenter: parent.verticalCenter
- text: {
- if (GreeterState.unlocking) {
- return I18n.tr("Logging in...");
- }
- if (Greetd.state !== GreetdState.Inactive && !awaitingExternalAuth && !pendingPasswordResponse) {
- return I18n.tr("Authenticating...");
- }
- if (GreeterState.showPasswordInput) {
- return I18n.tr("Password...");
- }
- return I18n.tr("Username...");
- }
- color: (GreeterState.unlocking || (Greetd.state !== GreetdState.Inactive && !awaitingExternalAuth && !pendingPasswordResponse)) ? Theme.primary : Theme.outline
- font.pixelSize: Theme.fontSizeMedium
- opacity: (GreeterState.showPasswordInput ? GreeterState.passwordBuffer.length === 0 : GreeterState.usernameInput.length === 0) ? 1 : 0
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.mediumDuration
- easing.type: Theme.standardEasing
- }
- }
-
- Behavior on color {
- ColorAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- StyledText {
- anchors.left: lockIcon.right
- anchors.leftMargin: Theme.spacingM
- anchors.right: (GreeterState.showPasswordInput && revealButton.visible ? revealButton.left : (externalAuthButton.visible ? externalAuthButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right))))
- anchors.rightMargin: 2
- anchors.verticalCenter: parent.verticalCenter
- text: {
- if (GreeterState.showPasswordInput) {
- if (parent.showPassword) {
- return GreeterState.passwordBuffer;
- }
- return "•".repeat(GreeterState.passwordBuffer.length);
- }
- return GreeterState.usernameInput;
- }
- color: Theme.surfaceText
- font.pixelSize: (GreeterState.showPasswordInput && !parent.showPassword) ? Theme.fontSizeLarge : Theme.fontSizeMedium
- opacity: (GreeterState.showPasswordInput ? GreeterState.passwordBuffer.length > 0 : GreeterState.usernameInput.length > 0) ? 1 : 0
- clip: true
- elide: Text.ElideNone
- horizontalAlignment: implicitWidth > width ? Text.AlignRight : Text.AlignLeft
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.mediumDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- DankActionButton {
- id: revealButton
-
- anchors.right: externalAuthButton.visible ? externalAuthButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right))
- anchors.rightMargin: 0
- anchors.verticalCenter: parent.verticalCenter
- iconName: parent.showPassword ? "visibility_off" : "visibility"
- buttonSize: 32
- visible: GreeterState.showPasswordInput && GreeterState.passwordBuffer.length > 0 && (Greetd.state === GreetdState.Inactive || awaitingExternalAuth || pendingPasswordResponse) && !GreeterState.unlocking
- enabled: visible
- onClicked: parent.showPassword = !parent.showPassword
- }
- DankActionButton {
- id: externalAuthButton
-
- anchors.right: virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : parent.right)
- anchors.rightMargin: 0
- anchors.verticalCenter: parent.verticalCenter
- iconName: root.greeterPamHasFprint ? "fingerprint" : "key"
- buttonSize: 32
- visible: GreeterState.showPasswordInput && root.greeterExternalAuthAvailable && GreeterState.passwordBuffer.length === 0 && (Greetd.state === GreetdState.Inactive || awaitingExternalAuth || pendingPasswordResponse) && !GreeterState.unlocking
- enabled: visible
- onClicked: root.startAuthSession(false)
- }
- DankActionButton {
- id: virtualKeyboardButton
-
- anchors.right: enterButton.visible ? enterButton.left : parent.right
- anchors.rightMargin: enterButton.visible ? 0 : Theme.spacingS
- anchors.verticalCenter: parent.verticalCenter
- iconName: "keyboard"
- buttonSize: 32
- visible: (Greetd.state === GreetdState.Inactive || awaitingExternalAuth || pendingPasswordResponse) && !GreeterState.unlocking
- enabled: visible
- onClicked: {
- if (keyboard_controller.isKeyboardActive) {
- keyboard_controller.hide();
- } else {
- keyboard_controller.show();
- }
- }
- }
-
- DankActionButton {
- id: enterButton
-
- anchors.right: parent.right
- anchors.rightMargin: 2
- anchors.verticalCenter: parent.verticalCenter
- iconName: "keyboard_return"
- buttonSize: 36
- visible: (Greetd.state === GreetdState.Inactive || awaitingExternalAuth || pendingPasswordResponse) && !GreeterState.unlocking
- enabled: true
- onClicked: {
- if (GreeterState.showPasswordInput) {
- root.startAuthSession(true);
- } else {
- if (inputField.text.trim()) {
- root.submitUsername(inputField.text);
- inputField.text = "";
- }
- }
- }
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- Behavior on border.color {
- ColorAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
- }
-
- StyledText {
- Layout.fillWidth: true
- Layout.preferredHeight: 38
- Layout.topMargin: -Theme.spacingS
- Layout.bottomMargin: -Theme.spacingS
- text: root.authFeedbackMessage
- color: Theme.error
- font.pixelSize: Theme.fontSizeSmall
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.WordWrap
- maximumLineCount: 2
- opacity: root.authFeedbackMessage !== "" ? 1 : 0
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- Rectangle {
- Layout.alignment: Qt.AlignHCenter
- Layout.topMargin: 0
- Layout.preferredWidth: switchUserRow.width + Theme.spacingL * 2
- Layout.preferredHeight: 40
- radius: Theme.cornerRadius
- color: Theme.surfaceContainer
- opacity: GreeterState.showPasswordInput ? 1 : 0
- enabled: GreeterState.showPasswordInput
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.mediumDuration
- easing.type: Theme.standardEasing
- }
- }
-
- Row {
- id: switchUserRow
- anchors.centerIn: parent
- spacing: Theme.spacingS
-
- DankIcon {
- name: "people"
- size: Theme.iconSize - 4
- color: Theme.surfaceText
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- text: I18n.tr("Switch User")
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- anchors.verticalCenter: parent.verticalCenter
- }
- }
-
- StateLayer {
- stateColor: Theme.primary
- cornerRadius: parent.radius
- enabled: !GreeterState.unlocking && Greetd.state === GreetdState.Inactive && GreeterState.showPasswordInput
- onClicked: {
- GreeterState.reset();
- root.externalAuthAutoStartedForUser = "";
- inputField.text = "";
- PortalService.profileImage = "";
- }
- }
- }
- }
- }
-
- Row {
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.margins: Theme.spacingXL
- spacing: Theme.spacingL
-
- Item {
- width: keyboardLayoutRow.width
- height: keyboardLayoutRow.height
- anchors.verticalCenter: parent.verticalCenter
- visible: {
- if (CompositorService.isNiri) {
- return NiriService.keyboardLayoutNames.length > 1;
- } else if (CompositorService.isHyprland) {
- return hyprlandLayoutCount > 1;
- }
- return false;
- }
-
- Row {
- id: keyboardLayoutRow
- spacing: 4
-
- Item {
- width: Theme.iconSize
- height: Theme.iconSize
-
- DankIcon {
- name: "keyboard"
- size: Theme.iconSize
- color: "white"
- anchors.centerIn: parent
- }
- }
-
- Item {
- width: childrenRect.width
- height: Theme.iconSize
-
- StyledText {
- text: {
- if (CompositorService.isNiri) {
- const layout = NiriService.getCurrentKeyboardLayoutName();
- if (!layout)
- return "";
- const parts = layout.split(" ");
- if (parts.length > 0) {
- return parts[0].substring(0, 2).toUpperCase();
- }
- return layout.substring(0, 2).toUpperCase();
- } else if (CompositorService.isHyprland) {
- return hyprlandCurrentLayout;
- }
- return "";
- }
- font.pixelSize: Theme.fontSizeMedium
- font.weight: Font.Light
- color: "white"
- anchors.verticalCenter: parent.verticalCenter
- }
- }
- }
-
- MouseArea {
- id: keyboardLayoutArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (CompositorService.isNiri) {
- NiriService.cycleKeyboardLayout();
- } else if (CompositorService.isHyprland) {
- Quickshell.execDetached(["hyprctl", "switchxkblayout", hyprlandKeyboard, "next"]);
- updateHyprlandLayout();
- }
- }
- }
- }
-
- Rectangle {
- width: 1
- height: 24
- color: Qt.rgba(255, 255, 255, 0.2)
- anchors.verticalCenter: parent.verticalCenter
- visible: {
- const keyboardVisible = (CompositorService.isNiri && NiriService.keyboardLayoutNames.length > 1) || (CompositorService.isHyprland && hyprlandLayoutCount > 1);
- return keyboardVisible && GreetdSettings.weatherEnabled && WeatherService.weather.available;
- }
- }
-
- Row {
- spacing: 6
- visible: GreetdSettings.weatherEnabled && WeatherService.weather.available
- anchors.verticalCenter: parent.verticalCenter
-
- DankIcon {
- name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
- size: Theme.iconSize
- color: "white"
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- text: (GreetdSettings.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°"
- font.pixelSize: Theme.fontSizeLarge
- font.weight: Font.Light
- color: "white"
- anchors.verticalCenter: parent.verticalCenter
- }
- }
-
- Rectangle {
- width: 1
- height: 24
- color: Qt.rgba(255, 255, 255, 0.2)
- anchors.verticalCenter: parent.verticalCenter
- visible: GreetdSettings.weatherEnabled && WeatherService.weather.available && (NetworkService.networkStatus !== "disconnected" || BluetoothService.enabled || (AudioService.sink && AudioService.sink.audio) || BatteryService.batteryAvailable)
- }
-
- Row {
- spacing: Theme.spacingM
- anchors.verticalCenter: parent.verticalCenter
- visible: NetworkService.networkStatus !== "disconnected" || (BluetoothService.available && BluetoothService.enabled) || (AudioService.sink && AudioService.sink.audio)
-
- DankIcon {
- name: NetworkService.networkStatus === "ethernet" ? "lan" : NetworkService.wifiSignalIcon
- size: Theme.iconSize - 2
- color: NetworkService.networkStatus !== "disconnected" ? "white" : Qt.rgba(255, 255, 255, 0.5)
- anchors.verticalCenter: parent.verticalCenter
- visible: NetworkService.networkStatus !== "disconnected"
- }
-
- DankIcon {
- name: "bluetooth"
- size: Theme.iconSize - 2
- color: "white"
- anchors.verticalCenter: parent.verticalCenter
- visible: BluetoothService.available && BluetoothService.enabled
- }
-
- DankIcon {
- name: {
- if (!AudioService.sink?.audio) {
- return "volume_up";
- }
- if (AudioService.sink.audio.muted)
- return "volume_off";
- if (AudioService.sink.audio.volume === 0)
- return "volume_mute";
- if (AudioService.sink.audio.volume * 100 < 33) {
- return "volume_down";
- }
- return "volume_up";
- }
- size: Theme.iconSize - 2
- color: (AudioService.sink && AudioService.sink.audio && (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0)) ? Qt.rgba(255, 255, 255, 0.5) : "white"
- anchors.verticalCenter: parent.verticalCenter
- visible: AudioService.sink && AudioService.sink.audio
- }
- }
-
- Rectangle {
- width: 1
- height: 24
- color: Qt.rgba(255, 255, 255, 0.2)
- anchors.verticalCenter: parent.verticalCenter
- visible: BatteryService.batteryAvailable && (NetworkService.networkStatus !== "disconnected" || BluetoothService.enabled || (AudioService.sink && AudioService.sink.audio))
- }
-
- Row {
- spacing: 4
- visible: BatteryService.batteryAvailable
- anchors.verticalCenter: parent.verticalCenter
-
- DankIcon {
- name: {
- if (BatteryService.isCharging) {
- if (BatteryService.batteryLevel >= 90) {
- return "battery_charging_full";
- }
-
- if (BatteryService.batteryLevel >= 80) {
- return "battery_charging_90";
- }
-
- if (BatteryService.batteryLevel >= 60) {
- return "battery_charging_80";
- }
-
- if (BatteryService.batteryLevel >= 50) {
- return "battery_charging_60";
- }
-
- if (BatteryService.batteryLevel >= 30) {
- return "battery_charging_50";
- }
-
- if (BatteryService.batteryLevel >= 20) {
- return "battery_charging_30";
- }
-
- return "battery_charging_20";
- }
- if (BatteryService.isPluggedIn) {
- if (BatteryService.batteryLevel >= 90) {
- return "battery_charging_full";
- }
-
- if (BatteryService.batteryLevel >= 80) {
- return "battery_charging_90";
- }
-
- if (BatteryService.batteryLevel >= 60) {
- return "battery_charging_80";
- }
-
- if (BatteryService.batteryLevel >= 50) {
- return "battery_charging_60";
- }
-
- if (BatteryService.batteryLevel >= 30) {
- return "battery_charging_50";
- }
-
- if (BatteryService.batteryLevel >= 20) {
- return "battery_charging_30";
- }
-
- return "battery_charging_20";
- }
- if (BatteryService.batteryLevel >= 95) {
- return "battery_full";
- }
-
- if (BatteryService.batteryLevel >= 85) {
- return "battery_6_bar";
- }
-
- if (BatteryService.batteryLevel >= 70) {
- return "battery_5_bar";
- }
-
- if (BatteryService.batteryLevel >= 55) {
- return "battery_4_bar";
- }
-
- if (BatteryService.batteryLevel >= 40) {
- return "battery_3_bar";
- }
-
- if (BatteryService.batteryLevel >= 25) {
- return "battery_2_bar";
- }
-
- return "battery_1_bar";
- }
- size: Theme.iconSize
- color: {
- if (BatteryService.isLowBattery && !BatteryService.isCharging) {
- return Theme.error;
- }
-
- if (BatteryService.isCharging || BatteryService.isPluggedIn) {
- return Theme.primary;
- }
-
- return "white";
- }
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- text: BatteryService.batteryLevel + "%"
- font.pixelSize: Theme.fontSizeLarge
- font.weight: Font.Light
- color: "white"
- anchors.verticalCenter: parent.verticalCenter
- }
- }
- }
-
- DankActionButton {
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.margins: Theme.spacingXL
- visible: GreetdSettings.lockScreenShowPowerActions
- iconName: "power_settings_new"
- iconColor: Theme.error
- buttonSize: 40
- onClicked: powerMenu.show()
- }
-
- Item {
- anchors.bottom: parent.bottom
- anchors.right: parent.right
- anchors.margins: Theme.spacingXL
- width: Math.max(200, currentSessionMetrics.width + 80)
- height: 60
-
- StyledTextMetrics {
- id: currentSessionMetrics
- text: root.currentSessionName
- }
-
- property real longestSessionWidth: {
- let maxWidth = 0;
- for (var i = 0; i < sessionMetricsRepeater.count; i++) {
- const item = sessionMetricsRepeater.itemAt(i);
- if (item && item.width > maxWidth) {
- maxWidth = item.width;
- }
- }
- return maxWidth;
- }
-
- Repeater {
- id: sessionMetricsRepeater
- model: GreeterState.sessionList
- delegate: StyledTextMetrics {
- text: modelData
- }
- }
-
- DankDropdown {
- id: sessionDropdown
- anchors.fill: parent
- text: ""
- description: ""
- currentValue: root.currentSessionName
- options: GreeterState.sessionList
- enableFuzzySearch: GreeterState.sessionList.length > 5
- popupWidthOffset: 0
- popupWidth: Math.max(250, parent.longestSessionWidth + 100)
- openUpwards: true
- alignPopupRight: true
- onValueChanged: value => {
- const idx = GreeterState.sessionList.indexOf(value);
- if (idx < 0)
- return;
- GreeterState.currentSessionIndex = idx;
- GreeterState.selectedSession = GreeterState.sessionExecs[idx];
- GreeterState.selectedSessionPath = GreeterState.sessionPaths[idx];
- }
- }
- }
- }
-
- property string currentSessionName: GreeterState.sessionList[GreeterState.currentSessionIndex] || ""
-
- function finalizeSessionSelection() {
- if (GreeterState.sessionList.length === 0)
- return;
- if (!GreetdMemory.memoryReady)
- return;
- if (!GreetdSettings.settingsLoaded)
- return;
-
- const savedSession = GreetdSettings.rememberLastSession ? GreetdMemory.lastSessionId : "";
- if (savedSession && GreetdSettings.rememberLastSession) {
- for (var i = 0; i < GreeterState.sessionPaths.length; i++) {
- if (GreeterState.sessionPaths[i] === savedSession) {
- GreeterState.currentSessionIndex = i;
- GreeterState.selectedSession = GreeterState.sessionExecs[i] || "";
- GreeterState.selectedSessionPath = GreeterState.sessionPaths[i];
- return;
- }
- }
- }
-
- GreeterState.currentSessionIndex = 0;
- GreeterState.selectedSession = GreeterState.sessionExecs[0] || "";
- GreeterState.selectedSessionPath = GreeterState.sessionPaths[0] || "";
- }
-
- property var sessionDirs: {
- const homeDir = Quickshell.env("HOME") || "";
- const dirs = ["/usr/share/wayland-sessions", "/usr/share/xsessions", "/usr/local/share/wayland-sessions", "/usr/local/share/xsessions"];
-
- if (homeDir) {
- dirs.push(homeDir + "/.local/share/wayland-sessions");
- dirs.push(homeDir + "/.local/share/xsessions");
- }
-
- if (xdgDataDirs) {
- xdgDataDirs.split(":").forEach(dir => {
- if (dir) {
- dirs.push(dir + "/wayland-sessions");
- dirs.push(dir + "/xsessions");
- }
- });
- }
- return dirs;
- }
-
- property var _pendingFiles: ({})
- property int _pendingCount: 0
-
- function _addSession(path, name, exec) {
- if (!name || !exec || GreeterState.sessionList.includes(name))
- return;
- GreeterState.sessionList = GreeterState.sessionList.concat([name]);
- GreeterState.sessionExecs = GreeterState.sessionExecs.concat([exec]);
- GreeterState.sessionPaths = GreeterState.sessionPaths.concat([path]);
- }
-
- function _parseDesktopFile(content, path) {
- let name = "";
- let exec = "";
- const lines = content.split("\n");
- for (let i = 0; i < lines.length; i++) {
- const line = lines[i];
- if (!name && line.startsWith("Name="))
- name = line.substring(5).trim();
- else if (!exec && line.startsWith("Exec="))
- exec = line.substring(5).trim();
- if (name && exec)
- break;
- }
- _addSession(path, name, exec);
- }
-
- function _loadDesktopFile(filePath) {
- if (_pendingFiles[filePath])
- return;
- _pendingFiles[filePath] = true;
- _pendingCount++;
-
- const loader = desktopFileLoader.createObject(root, {
- "filePath": filePath
- });
- }
-
- function _onFileLoaded(filePath) {
- _pendingCount--;
- if (_pendingCount === 0)
- Qt.callLater(finalizeSessionSelection);
- }
-
- Component {
- id: desktopFileLoader
-
- FileView {
- id: fv
- property string filePath: ""
- path: filePath
-
- onLoaded: {
- root._parseDesktopFile(text(), filePath);
- root._onFileLoaded(filePath);
- fv.destroy();
- }
-
- onLoadFailed: {
- root._onFileLoaded(filePath);
- fv.destroy();
- }
- }
- }
-
- Repeater {
- model: isPrimaryScreen ? sessionDirs : []
-
- Item {
- required property string modelData
-
- FolderListModel {
- folder: encodeFileUrl(modelData)
- nameFilters: ["*.desktop"]
- showDirs: false
- showDotAndDotDot: false
-
- onStatusChanged: {
- if (status !== FolderListModel.Ready)
- return;
- for (let i = 0; i < count; i++) {
- let fp = get(i, "filePath");
- if (fp.startsWith("file://"))
- fp = fp.substring(7);
- root._loadDesktopFile(fp);
- }
- }
- }
- }
- }
-
- Connections {
- target: Greetd
- enabled: isPrimaryScreen
-
- function onAuthMessage(message, error, responseRequired, echoResponse) {
- if (responseRequired) {
- cancelingExternalAuthForPassword = false;
- passwordSessionTransitionRetryCount = 0;
- awaitingExternalAuth = false;
- pendingPasswordResponse = true;
- const hasPasswordBuffer = GreeterState.passwordBuffer && GreeterState.passwordBuffer.length > 0;
- if (!passwordSubmitRequested && hasPasswordBuffer)
- passwordSubmitRequested = true;
- if (passwordSubmitRequested && !root.submitBufferedPassword())
- passwordSubmitRequested = false;
- if (passwordSubmitRequested || hasPasswordBuffer) {
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.restart();
- } else {
- authTimeout.stop();
- }
- return;
- }
- pendingPasswordResponse = false;
- const externalPrompt = root.isExternalAuthPrompt(message, responseRequired);
- if (!passwordSubmitRequested)
- awaitingExternalAuth = root.greeterExternalAuthAvailable && externalPrompt;
- if (awaitingExternalAuth || (passwordSubmitRequested && externalPrompt && root.greeterPamHasExternalAuth))
- authTimeout.interval = externalAuthTimeoutMs;
- else
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.restart();
- Greetd.respond("");
- }
-
- function onStateChanged() {
- if (Greetd.state === GreetdState.Inactive) {
- const resumePasswordSubmit = cancelingExternalAuthForPassword && passwordSubmitRequested;
- awaitingExternalAuth = false;
- pendingPasswordResponse = false;
- cancelingExternalAuthForPassword = false;
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.stop();
- if (resumePasswordSubmit) {
- Qt.callLater(function() {
- root.startAuthSession(true);
- });
- return;
- }
- resetPasswordSessionTransition(true);
- }
- }
-
- function onReadyToLaunch() {
- awaitingExternalAuth = false;
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.stop();
- passwordFailureCount = 0;
- clearAuthFeedback();
- const sessionCmd = GreeterState.selectedSession || GreeterState.sessionExecs[GreeterState.currentSessionIndex];
- const sessionPath = GreeterState.selectedSessionPath || GreeterState.sessionPaths[GreeterState.currentSessionIndex];
- if (!sessionCmd) {
- GreeterState.pamState = "error";
- authFeedbackMessage = currentAuthMessage();
- placeholderDelay.restart();
- return;
- }
-
- GreeterState.unlocking = true;
- launchTimeout.restart();
- if (GreetdSettings.rememberLastSession) {
- GreetdMemory.setLastSessionId(sessionPath);
- } else if (GreetdMemory.lastSessionId) {
- GreetdMemory.setLastSessionId("");
- }
- if (GreetdSettings.rememberLastUser) {
- GreetdMemory.setLastSuccessfulUser(GreeterState.username);
- } else if (GreetdMemory.lastSuccessfulUser) {
- GreetdMemory.setLastSuccessfulUser("");
- }
- pendingLaunchCommand = sessionCmd;
- pendingLaunchEnv = ["XDG_SESSION_TYPE=wayland"];
- memoryFlushTimer.restart();
- }
-
- function onAuthFailure(message) {
- awaitingExternalAuth = false;
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.stop();
- launchTimeout.stop();
- GreeterState.unlocking = false;
- if (isLikelyLockoutMessage(message)) {
- GreeterState.pamState = "max";
- } else {
- GreeterState.pamState = "fail";
- passwordFailureCount = passwordFailureCount + 1;
- }
- authFeedbackMessage = currentAuthMessage();
- GreeterState.passwordBuffer = "";
- inputField.text = "";
- placeholderDelay.restart();
- Greetd.cancelSession();
- }
-
- function onError(error) {
- awaitingExternalAuth = false;
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- authTimeout.interval = defaultAuthTimeoutMs;
- authTimeout.stop();
- launchTimeout.stop();
- GreeterState.unlocking = false;
- GreeterState.pamState = "error";
- authFeedbackMessage = currentAuthMessage();
- GreeterState.passwordBuffer = "";
- inputField.text = "";
- placeholderDelay.restart();
- Greetd.cancelSession();
- }
- }
-
- Timer {
- id: memoryFlushTimer
- interval: memoryFlushDelayMs
- onTriggered: {
- if (!pendingLaunchCommand)
- return;
- const sessionCommand = pendingLaunchCommand;
- const launchEnv = pendingLaunchEnv;
- pendingLaunchCommand = "";
- pendingLaunchEnv = [];
- Greetd.launch(sessionCommand.split(" "), launchEnv);
- }
- }
-
- Timer {
- id: authTimeout
- interval: defaultAuthTimeoutMs
- onTriggered: {
- if (GreeterState.unlocking || Greetd.state === GreetdState.Inactive)
- return;
- awaitingExternalAuth = false;
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- authTimeout.interval = defaultAuthTimeoutMs;
- GreeterState.pamState = "error";
- authFeedbackMessage = currentAuthMessage();
- GreeterState.passwordBuffer = "";
- inputField.text = "";
- placeholderDelay.restart();
- Greetd.cancelSession();
- }
- }
-
- Timer {
- id: launchTimeout
- interval: 8000
- onTriggered: {
- if (!GreeterState.unlocking)
- return;
- pendingPasswordResponse = false;
- resetPasswordSessionTransition(true);
- GreeterState.unlocking = false;
- GreeterState.pamState = "error";
- authFeedbackMessage = currentAuthMessage();
- placeholderDelay.restart();
- Greetd.cancelSession();
- }
- }
-
- Timer {
- id: placeholderDelay
- interval: 4000
- onTriggered: clearAuthFeedback()
- }
-
- LockPowerMenu {
- id: powerMenu
- showLogout: false
- powerActionConfirmOverride: GreetdSettings.powerActionConfirm
- powerActionHoldDurationOverride: GreetdSettings.powerActionHoldDuration
- powerMenuActionsOverride: GreetdSettings.powerMenuActions
- powerMenuDefaultActionOverride: GreetdSettings.powerMenuDefaultAction
- powerMenuGridLayoutOverride: GreetdSettings.powerMenuGridLayout
- requiredActions: ["poweroff"]
- onClosed: {
- if (isPrimaryScreen && inputField && inputField.forceActiveFocus) {
- Qt.callLater(() => inputField.forceActiveFocus());
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterState.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterState.qml
deleted file mode 100644
index ac57de7..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterState.qml
+++ /dev/null
@@ -1,30 +0,0 @@
-pragma Singleton
-pragma ComponentBehavior: Bound
-import QtQuick
-import Quickshell
-
-Singleton {
- id: root
-
- property string passwordBuffer: ""
- property string username: ""
- property string usernameInput: ""
- property bool showPasswordInput: false
- property string selectedSession: ""
- property string selectedSessionPath: ""
- property string pamState: ""
- property bool unlocking: false
-
- property var sessionList: []
- property var sessionExecs: []
- property var sessionPaths: []
- property int currentSessionIndex: 0
-
- function reset() {
- showPasswordInput = false;
- username = "";
- usernameInput = "";
- passwordBuffer = "";
- pamState = "";
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterSurface.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterSurface.qml
deleted file mode 100644
index a8af5df..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/GreeterSurface.qml
+++ /dev/null
@@ -1,34 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import Quickshell.Wayland
-import Quickshell.Services.Greetd
-import qs.Common
-
-Variants {
- model: Quickshell.screens
-
- PanelWindow {
- id: root
-
- property var modelData
-
- screen: modelData
- anchors {
- left: true
- right: true
- top: true
- bottom: true
- }
- exclusionMode: ExclusionMode.Normal
- WlrLayershell.layer: WlrLayer.Overlay
- WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
- color: "transparent"
-
- GreeterContent {
- anchors.fill: parent
- screenName: root.screen?.name ?? ""
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/README.md b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/README.md
deleted file mode 100644
index 4ac5a77..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/README.md
+++ /dev/null
@@ -1,277 +0,0 @@
-# Dank (dms) Greeter
-
-A greeter for [greetd](https://github.com/kennylevinsen/greetd) that follows the aesthetics of the dms lock screen.
-
-## Features
-
-- **Multi user**: Login with any system user
-- **dms sync**: Sync settings with dms for consistent styling between shell and greeter
-- **Multiple compositors**: The `dms-greeter` wrapper supports niri, Hyprland, sway, scroll, miracle-wm, labwc, and mangowc.
-- **Custom PAM**: Supports custom PAM configuration in `/etc/pam.d/greetd`
-- **Session Memory**: Remembers last selected session and user
- - Can be disabled via `settings.json` keys: `greeterRememberLastSession` and `greeterRememberLastUser`
-
-## Installation
-
-### Arch Linux
-
-Arch linux users can install [greetd-dms-greeter-git](https://aur.archlinux.org/packages/greetd-dms-greeter-git) from the AUR.
-
-```bash
-paru -S greetd-dms-greeter-git
-# Or with yay
-yay -S greetd-dms-greeter-git
-```
-
-### Debian / openSUSE
-
-Official packages are available from the [DankLinux OBS repository](https://software.opensuse.org/download/package?package=dms-greeter&project=home%3AAvengeMedia%3Adanklinux). Add the repo for your distribution and install:
-
-```bash
-# Debian 13
-sudo apt install dms-greeter # after adding the repo
-
-# openSUSE Tumbleweed
-zypper install dms-greeter # after adding the repo
-```
-
-See the [Installation guide](https://danklinux.com/docs/dankgreeter/installation) for full repository setup.
-
-If you previously installed manually, remove legacy files first:
-
-```bash
-sudo rm -f /usr/local/bin/dms-greeter
-sudo rm -rf /etc/xdg/quickshell/dms-greeter
-```
-
-Then complete setup:
-
-```bash
-dms greeter enable
-dms greeter sync
-```
-
-#### Syncing themes (Optional)
-
-To sync your wallpaper and theme with the greeter login screen, follow the manual setup below:
-
-<details>
-<summary>Manual theme syncing</summary>
-
-```bash
-# Add yourself to greeter group
-sudo usermod -aG greeter <username>
-
-# Set ACLs to allow greeter to traverse your directories
-setfacl -m u:greeter:x ~ ~/.config ~/.local ~/.cache ~/.local/state
-
-# Set group ownership on config directories
-sudo chgrp -R greeter ~/.config/DankMaterialShell
-sudo chgrp -R greeter ~/.local/state/DankMaterialShell
-sudo chgrp -R greeter ~/.cache/DankMaterialShell
-sudo chmod -R g+rX ~/.config/DankMaterialShell ~/.cache/DankMaterialShell ~/.cache/quickshell
-
-# Create symlinks
-sudo ln -sf ~/.config/DankMaterialShell/settings.json /var/cache/dms-greeter/settings.json
-sudo ln -sf ~/.local/state/DankMaterialShell/session.json /var/cache/dms-greeter/session.json
-sudo ln -sf ~/.cache/DankMaterialShell/dms-colors.json /var/cache/dms-greeter/colors.json
-
-# Logout and login for group membership to take effect
-```
-
-</details>
-
-### Fedora / RHEL / Rocky / Alma
-
-Install from COPR or build the RPM:
-
-```bash
-# From COPR (when available)
-sudo dnf copr enable avenge/dms
-sudo dnf install dms-greeter
-
-# Or build locally
-cd /path/to/DankMaterialShell
-rpkg local
-sudo rpm -ivh x86_64/dms-greeter-*.rpm
-```
-
-The package automatically:
-- Creates the greeter user
-- Sets up directories and permissions
-- Configures greetd with auto-detected compositor
-- Applies SELinux contexts
-
-Then complete setup:
-
-```bash
-dms greeter enable
-dms greeter sync
-```
-
-#### Syncing themes (Optional)
-
-Run:
-
-```bash
-dms greeter sync
-```
-
-Then logout/login to see your wallpaper on the greeter.
-
-### Automatic
-
-The easiest thing is to run `dms greeter install` or `dms` for interactive installation.
-On Debian/openSUSE, this now prefers the `dms-greeter` package when the OBS repo is configured.
-
-### Manual (fallback only)
-
-Use this only if no package is available for your distro.
-
-1. Install `greetd` (in most distro's standard repositories) and `quickshell`
-
-2. Create the greeter user (if not already created by greetd):
-```bash
-sudo groupadd -r greeter
-sudo useradd -r -g greeter -d /var/lib/greeter -s /bin/bash -c "System Greeter" greeter
-sudo mkdir -p /var/lib/greeter
-sudo chown greeter:greeter /var/lib/greeter
-```
-
-3. Clone the dms project to `/etc/xdg/quickshell/dms-greeter`:
-```bash
-sudo git clone https://github.com/AvengeMedia/DankMaterialShell.git /etc/xdg/quickshell/dms-greeter
-```
-
-4. Copy `Modules/Greetd/assets/dms-greeter` to `/usr/local/bin/dms-greeter`:
-```bash
-sudo cp /etc/xdg/quickshell/dms-greeter/Modules/Greetd/assets/dms-greeter /usr/local/bin/dms-greeter
-sudo chmod +x /usr/local/bin/dms-greeter
-```
-
-5. Create greeter cache directory with proper permissions:
-```bash
-sudo mkdir -p /var/cache/dms-greeter
-sudo chown <greeter-user>:<greeter-group> /var/cache/dms-greeter
-sudo chmod 2770 /var/cache/dms-greeter
-```
-
-6. Edit or create `/etc/greetd/config.toml`:
-```toml
-[terminal]
-vt = 1
-
-[default_session]
-user = "greeter"
-# Change compositor to another wrapper-supported compositor if preferred
-command = "/usr/local/bin/dms-greeter --command niri"
-```
-
-7. Disable existing display manager and enable greetd:
-```bash
-sudo systemctl disable gdm sddm lightdm
-sudo systemctl enable greetd
-```
-
-8. (Optional) Set up theme syncing using the manual ACL method described in the Configuration → Personalization section below
-
-#### Legacy installation (deprecated)
-
-If you prefer the old method with separate shell scripts and config files:
-1. Copy `assets/dms-niri.kdl` or `assets/dms-hypr.conf` to `/etc/greetd`
-2. Copy `assets/greet-niri.sh` or `assets/greet-hyprland.sh` to `/usr/local/bin/start-dms-greetd.sh`
-3. Edit the config file and replace `_DMS_PATH_` with your DMS installation path
-4. Configure greetd to use `/usr/local/bin/start-dms-greetd.sh`
-
-### NixOS
-
-To install the greeter on NixOS add the repo to your flake inputs as described in the readme. Then somewhere in your NixOS config add this to imports:
-```nix
-imports = [
- inputs.dank-material-shell.nixosModules.greeter
-]
-```
-
-Enable the greeter with this in your NixOS config:
-```nix
-programs.dank-material-shell.greeter = {
- enable = true;
- compositor.name = "niri"; # or set to hyprland
- configHome = "/home/user"; # optionally copyies that users DMS settings (and wallpaper if set) to the greeters data directory as root before greeter starts
-};
-```
-
-## Usage
-
-### Using dms-greeter wrapper (recommended)
-
-The `dms-greeter` wrapper simplifies running the greeter with any compositor:
-
-```bash
-dms-greeter --command niri
-dms-greeter --command hyprland
-dms-greeter --command sway
-dms-greeter --command mangowc
-dms-greeter --command niri -C /path/to/custom-niri.kdl
-dms-greeter --command niri --remember-last-user false --remember-last-session false
-```
-
-Configure greetd to use it in `/etc/greetd/config.toml`:
-```toml
-[terminal]
-vt = 1
-
-[default_session]
-user = "greeter"
-command = "/usr/bin/dms-greeter --command niri"
-```
-
-### Manual usage
-
-To run dms in greeter mode you can also manually set environment variables:
-
-```bash
-DMS_RUN_GREETER=1 qs -p /path/to/dms
-```
-
-### Configuration
-
-#### Compositor
-
-For current wrapper-based installs, the `dms-greeter` wrapper supports niri, hyprland, sway, scroll, miracle-wm, labwc, and mangowc.
-
-Only niri currently has a generated greeter config path managed by `dms greeter sync`.
-
-- niri: `dms greeter sync` writes the generated greeter config to `/etc/greetd/niri/config.kdl`. Add local manual tweaks in `/etc/greetd/niri_overrides.kdl`.
-- Other wrapper-supported compositors use the wrapper-generated config by default. If you need a custom compositor config, add `-C /path/to/config` to the `dms-greeter` command in `/etc/greetd/config.toml`.
-
-#### Personalization
-
-The greeter can be personalized with wallpapers, themes, weather, clock formats, and more - configured exactly the same as dms.
-
-**Easiest method:** Run `dms greeter sync` to automatically sync your DMS theme with the greeter.
-
-**Manual method:** You can manually synchronize configurations if you want greeter settings to always mirror your shell:
-
-```bash
-# Add yourself to the greeter group
-sudo usermod -aG greeter $USER
-
-# Set ACLs to allow greeter user to traverse your home directory
-setfacl -m u:greeter:x ~ ~/.config ~/.local ~/.cache ~/.local/state
-
-# Set group permissions on DMS directories
-sudo chgrp -R greeter ~/.config/DankMaterialShell ~/.local/state/DankMaterialShell ~/.cache/quickshell
-sudo chmod -R g+rX ~/.config/DankMaterialShell ~/.local/state/DankMaterialShell ~/.cache/quickshell
-
-# Create symlinks for theme files
-sudo ln -sf ~/.config/DankMaterialShell/settings.json /var/cache/dms-greeter/settings.json
-sudo ln -sf ~/.local/state/DankMaterialShell/session.json /var/cache/dms-greeter/session.json
-sudo ln -sf ~/.cache/DankMaterialShell/dms-colors.json /var/cache/dms-greeter/colors.json
-
-# Logout and login for group membership to take effect
-```
-
-**Advanced:** You can override the configuration path with the `DMS_GREET_CFG_DIR` environment variable or the `--cache-dir` flag when using `dms-greeter`. The default is `/var/cache/dms-greeter`.
-
-The cache directory should be owned by `<greeter-user>:<greeter-group>` with `2770` permissions. If the greeter user is not available yet, DMS falls back to `root:<greeter-group>`.
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-greeter b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-greeter
deleted file mode 100755
index 5d3419c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-greeter
+++ /dev/null
@@ -1,424 +0,0 @@
-#!/bin/bash
-
-set -e
-
-COMPOSITOR=""
-COMPOSITOR_CONFIG=""
-DMS_PATH="dms-greeter"
-CACHE_DIR="/var/cache/dms-greeter"
-REMEMBER_LAST_SESSION=""
-REMEMBER_LAST_USER=""
-DEBUG_MODE=0
-
-show_help() {
- cat << EOF
-dms-greeter - DankMaterialShell greeter launcher
-
-Usage: dms-greeter --command COMPOSITOR [OPTIONS]
-
-Required:
- --command COMPOSITOR Compositor to use (niri, hyprland, sway, scroll, miracle, mango, or labwc)
-
-Options:
- -C, --config PATH Custom compositor config file
- -p, --path PATH DMS path (config name or absolute path)
- (default: dms-greeter)
- --cache-dir PATH Cache directory for greeter data
- (default: /var/cache/dms-greeter)
- --remember-last-session BOOL
- Persist selected session to greeter memory
- (BOOL: true/false, default: from settings.json)
- --remember-last-user BOOL
- Persist last successful username to greeter memory
- (BOOL: true/false, default: from settings.json)
- --no-save-session Alias for --remember-last-session false
- --no-save-username Alias for --remember-last-user false
- --debug Enable verbose startup logging to stderr
- -h, --help Show this help message
-
-Examples:
- dms-greeter --command niri
- dms-greeter --command hyprland -C /etc/greetd/custom-hypr.conf
- dms-greeter --command sway -p /home/user/.config/quickshell/custom-dms
- dms-greeter --command scroll -p /home/user/.config/quickshell/custom-dms
- dms-greeter --command niri --cache-dir /tmp/dmsgreeter
- dms-greeter --command niri --no-save-session --no-save-username
- dms-greeter --command mango
- dms-greeter --command labwc
-EOF
-}
-
-require_command() {
- local cmd="$1"
- if ! command -v "$cmd" >/dev/null 2>&1; then
- echo "Error: required command '$cmd' was not found in PATH" >&2
- exit 1
- fi
-}
-
-normalize_bool_flag() {
- local flag_name="$1"
- local value="$2"
- local normalized="${value,,}"
-
- case "$normalized" in
- 1|true|yes|on)
- echo "1"
- ;;
- 0|false|no|off)
- echo "0"
- ;;
- *)
- echo "Error: $flag_name must be true/false (or 1/0, yes/no, on/off)" >&2
- exit 1
- ;;
- esac
-}
-
-exec_compositor() {
- local log_tag="$1"
- shift
-
- if [[ "$DEBUG_MODE" == "1" ]]; then
- exec "$@"
- fi
-
- if command -v systemd-cat >/dev/null 2>&1; then
- exec "$@" > >(systemd-cat -t "dms-greeter/$log_tag" -p info) 2>&1
- fi
-
- exec "$@"
-}
-
-while [[ $# -gt 0 ]]; do
- case $1 in
- --command)
- COMPOSITOR="$2"
- shift 2
- ;;
- -C|--config)
- COMPOSITOR_CONFIG="$2"
- shift 2
- ;;
- -p|--path)
- DMS_PATH="$2"
- shift 2
- ;;
- --cache-dir)
- CACHE_DIR="$2"
- shift 2
- ;;
- --remember-last-session)
- REMEMBER_LAST_SESSION="$2"
- shift 2
- ;;
- --remember-last-user)
- REMEMBER_LAST_USER="$2"
- shift 2
- ;;
- --no-save-session)
- REMEMBER_LAST_SESSION="0"
- shift
- ;;
- --no-save-username)
- REMEMBER_LAST_USER="0"
- shift
- ;;
- --debug)
- DEBUG_MODE=1
- shift
- ;;
- -h|--help)
- show_help
- exit 0
- ;;
- *)
- echo "Unknown option: $1" >&2
- show_help
- exit 1
- ;;
- esac
-done
-
-if [[ -z "$COMPOSITOR" ]]; then
- echo "Error: --command COMPOSITOR is required" >&2
- show_help
- exit 1
-fi
-
-locate_dms_config() {
- local config_name="$1"
- local search_paths=()
-
- local config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
- search_paths+=("$config_home/quickshell/$config_name")
-
- search_paths+=("/usr/share/quickshell/$config_name")
-
- local config_dirs="${XDG_CONFIG_DIRS:-/etc/xdg}"
- IFS=':' read -ra dirs <<< "$config_dirs"
- for dir in "${dirs[@]}"; do
- if [[ -n "$dir" ]]; then
- search_paths+=("$dir/quickshell/$config_name")
- fi
- done
-
- for path in "${search_paths[@]}"; do
- if [[ -f "$path/shell.qml" ]]; then
- echo "$path"
- return 0
- fi
- done
-
- return 1
-}
-
-export XDG_SESSION_TYPE=wayland
-export QT_QPA_PLATFORM=wayland
-export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
-export EGL_PLATFORM=gbm
-export DMS_RUN_GREETER=1
-
-if [[ ! -d "$CACHE_DIR" ]]; then
- echo "Error: cache directory '$CACHE_DIR' does not exist." >&2
- echo " Run 'dms greeter sync' to initialize it, or pass --cache-dir to an existing directory." >&2
- exit 1
-fi
-
-export DMS_GREET_CFG_DIR="$CACHE_DIR"
-
-if [[ -n "$REMEMBER_LAST_SESSION" ]]; then
- DMS_GREET_REMEMBER_LAST_SESSION=$(normalize_bool_flag "--remember-last-session" "$REMEMBER_LAST_SESSION")
- export DMS_GREET_REMEMBER_LAST_SESSION
- if [[ "$DMS_GREET_REMEMBER_LAST_SESSION" == "1" ]]; then
- DMS_SAVE_SESSION=true
- else
- DMS_SAVE_SESSION=false
- fi
- export DMS_SAVE_SESSION
-fi
-
-if [[ -n "$REMEMBER_LAST_USER" ]]; then
- DMS_GREET_REMEMBER_LAST_USER=$(normalize_bool_flag "--remember-last-user" "$REMEMBER_LAST_USER")
- export DMS_GREET_REMEMBER_LAST_USER
- if [[ "$DMS_GREET_REMEMBER_LAST_USER" == "1" ]]; then
- DMS_SAVE_USERNAME=true
- else
- DMS_SAVE_USERNAME=false
- fi
- export DMS_SAVE_USERNAME
-fi
-
-export HOME="$CACHE_DIR"
-export XDG_STATE_HOME="$CACHE_DIR/.local/state"
-export XDG_DATA_HOME="$CACHE_DIR/.local/share"
-export XDG_CACHE_HOME="$CACHE_DIR/.cache"
-
-
-# Keep greeter VT clean by default; callers can override via env or --debug.
-if [[ -z "${RUST_LOG:-}" ]]; then
- export RUST_LOG=warn
-fi
-if [[ -z "${NIRI_LOG:-}" ]]; then
- export NIRI_LOG=warn
-fi
-
-if command -v qs >/dev/null 2>&1; then
- QS_BIN="qs"
-elif command -v quickshell >/dev/null 2>&1; then
- QS_BIN="quickshell"
-else
- echo "Error: neither 'qs' nor 'quickshell' was found in PATH" >&2
- exit 1
-fi
-
-QS_CMD="$QS_BIN"
-if [[ "$DMS_PATH" == /* ]]; then
- QS_CMD="$QS_BIN -p $DMS_PATH"
-else
- RESOLVED_PATH=$(locate_dms_config "$DMS_PATH")
- if [[ $? -eq 0 && -n "$RESOLVED_PATH" ]]; then
- if [[ "$DEBUG_MODE" == "1" ]]; then
- echo "Located DMS config at: $RESOLVED_PATH" >&2
- fi
- QS_CMD="$QS_BIN -p $RESOLVED_PATH"
- else
- echo "Error: Could not find DMS config '$DMS_PATH' (shell.qml) in any valid config path" >&2
- exit 1
- fi
-fi
-
-case "$COMPOSITOR" in
- niri)
- require_command "niri"
- if [[ -z "$COMPOSITOR_CONFIG" ]]; then
- TEMP_CONFIG=$(mktemp)
- # base/default config
- cat > "$TEMP_CONFIG" << NIRI_EOF
-hotkey-overlay {
- skip-at-startup
-}
-
-environment {
- DMS_RUN_GREETER "1"
-}
-
-debug {
- keep-max-bpc-unchanged
-}
-
-gestures {
- hot-corners {
- off
- }
-}
-
-layout {
- background-color "#000000"
-}
-NIRI_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- else
- TEMP_CONFIG=$(mktemp)
- cat "$COMPOSITOR_CONFIG" > "$TEMP_CONFIG"
- fi
- # Append includes if override_files exist
- OVERRIDE_FILES=(
- /usr/share/greetd/niri_overrides.kdl # for building into a system image
- /etc/greetd/niri_overrides.kdl # for local overrides
- )
- for override_file in "${OVERRIDE_FILES[@]}"; do
- if [[ -e "$override_file" ]]; then
- # TODO: maybe move to optional=true when Niri Next drops, so we can avoid these checks ;-)
- cat >> "$TEMP_CONFIG" << NIRI_EOF
-
-include "$override_file"
-NIRI_EOF
- fi
- done
- # Append spawn command
- cat >> "$TEMP_CONFIG" << NIRI_EOF
-
-spawn-at-startup "sh" "-c" "$QS_CMD; niri msg action quit --skip-confirmation"
-NIRI_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- exec_compositor "niri" niri -c "$COMPOSITOR_CONFIG"
- ;;
-
- hyprland)
- if ! command -v start-hyprland >/dev/null 2>&1 && ! command -v Hyprland >/dev/null 2>&1; then
- echo "Error: neither 'start-hyprland' nor 'Hyprland' was found in PATH" >&2
- exit 1
- fi
- if [[ -z "$COMPOSITOR_CONFIG" ]]; then
- TEMP_CONFIG=$(mktemp)
- cat > "$TEMP_CONFIG" << HYPRLAND_EOF
-env = DMS_RUN_GREETER,1
-
-misc {
- disable_hyprland_logo = true
-}
-
-exec-once = sh -c "$QS_CMD; hyprctl dispatch exit"
-HYPRLAND_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- else
- TEMP_CONFIG=$(mktemp)
- cat "$COMPOSITOR_CONFIG" > "$TEMP_CONFIG"
- cat >> "$TEMP_CONFIG" << HYPRLAND_EOF
-
-exec-once = sh -c "$QS_CMD; hyprctl dispatch exit"
-HYPRLAND_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- fi
- if command -v start-hyprland >/dev/null 2>&1; then
- exec_compositor "hyprland" start-hyprland -- --config "$COMPOSITOR_CONFIG"
- else
- exec_compositor "hyprland" Hyprland -c "$COMPOSITOR_CONFIG"
- fi
- ;;
-
- sway)
- require_command "sway"
- if [[ -z "$COMPOSITOR_CONFIG" ]]; then
- TEMP_CONFIG=$(mktemp)
- cat > "$TEMP_CONFIG" << SWAY_EOF
-exec "$QS_CMD; swaymsg exit"
-SWAY_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- else
- TEMP_CONFIG=$(mktemp)
- cat "$COMPOSITOR_CONFIG" > "$TEMP_CONFIG"
- cat >> "$TEMP_CONFIG" << SWAY_EOF
-
-exec "$QS_CMD; swaymsg exit"
-SWAY_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- fi
- exec_compositor "sway" sway --unsupported-gpu -c "$COMPOSITOR_CONFIG"
- ;;
-
- scroll)
- require_command "scroll"
- if [[ -z "$COMPOSITOR_CONFIG" ]]; then
- TEMP_CONFIG=$(mktemp)
- cat > "$TEMP_CONFIG" << SCROLL_EOF
-exec "$QS_CMD; scrollmsg exit"
-SCROLL_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- else
- TEMP_CONFIG=$(mktemp)
- cat "$COMPOSITOR_CONFIG" > "$TEMP_CONFIG"
- cat >> "$TEMP_CONFIG" << SCROLL_EOF
-
-exec "$QS_CMD; scrollmsg exit"
-SCROLL_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- fi
- exec_compositor "scroll" scroll -c "$COMPOSITOR_CONFIG"
- ;;
-
- miracle|miracle-wm)
- require_command "miracle-wm"
- if [[ -z "$COMPOSITOR_CONFIG" ]]; then
- TEMP_CONFIG=$(mktemp)
- cat > "$TEMP_CONFIG" << MIRACLE_EOF
-exec "$QS_CMD; miraclemsg exit"
-MIRACLE_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- else
- TEMP_CONFIG=$(mktemp)
- cat "$COMPOSITOR_CONFIG" > "$TEMP_CONFIG"
- cat >> "$TEMP_CONFIG" << MIRACLE_EOF
-
-exec "$QS_CMD; miraclemsg exit"
-MIRACLE_EOF
- COMPOSITOR_CONFIG="$TEMP_CONFIG"
- fi
- exec_compositor "miracle" miracle-wm -c "$COMPOSITOR_CONFIG"
- ;;
-
- labwc)
- require_command "labwc"
- if [[ -n "$COMPOSITOR_CONFIG" ]]; then
- exec_compositor "labwc" labwc --config "$COMPOSITOR_CONFIG" --session "$QS_CMD"
- else
- exec_compositor "labwc" labwc --session "$QS_CMD"
- fi
- ;;
-
- mango|mangowc)
- require_command "mango"
- if [[ -n "$COMPOSITOR_CONFIG" ]]; then
- exec_compositor "mango" mango -c "$COMPOSITOR_CONFIG" -s "$QS_CMD && mmsg -d quit"
- else
- exec_compositor "mango" mango -s "$QS_CMD && mmsg -d quit"
- fi
- ;;
-
- *)
- echo "Error: Unsupported compositor: $COMPOSITOR" >&2
- echo "Supported compositors: niri, hyprland, sway, scroll, miracle, mango, labwc" >&2
- exit 1
- ;;
-esac
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-hypr.conf b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-hypr.conf
deleted file mode 100644
index 33eefcd..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-hypr.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-env = DMS_RUN_GREETER,1
-
-exec = sh -c "qs -p _DMS_PATH_; hyprctl dispatch exit"
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-niri.kdl b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-niri.kdl
deleted file mode 100644
index dfc4703..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/dms-niri.kdl
+++ /dev/null
@@ -1,23 +0,0 @@
-hotkey-overlay {
- skip-at-startup
-}
-
-environment {
- DMS_RUN_GREETER "1"
-}
-
-spawn-at-startup "sh" "-c" "qs -p _DMS_PATH_; niri msg action quit --skip-confirmation"
-
-debug {
- keep-max-bpc-unchanged
-}
-
-gestures {
- hot-corners {
- off
- }
-}
-
-layout {
- background-color "#000000"
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-hyprland.sh b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-hyprland.sh
deleted file mode 100755
index c23b479..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-hyprland.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-export XDG_SESSION_TYPE=wayland
-export QT_QPA_PLATFORM=wayland
-export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
-export EGL_PLATFORM=gbm
-if command -v start-hyprland >/dev/null 2>&1; then
- exec start-hyprland -- -c /etc/greetd/dms-hypr.conf
-else
- exec Hyprland -c /etc/greetd/dms-hypr.conf
-fi
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-niri.sh b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-niri.sh
deleted file mode 100755
index d31db65..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Greetd/assets/greet-niri.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-export XDG_SESSION_TYPE=wayland
-export QT_QPA_PLATFORM=wayland
-export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
-export EGL_PLATFORM=gbm
-
-exec niri -c /etc/greetd/dms-niri.kdl