Fork the desktop off Omarchy as a self-contained system

This commit is contained in:
2026-09-19 23:50:39 -04:00
parent 16a56f49a1
commit 9501f2bb4d
559 changed files with 43273 additions and 0 deletions
+392
View File
@@ -0,0 +1,392 @@
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Services.Polkit
import Quickshell.Wayland
import qs.Commons
import qs.Ui
import "PolkitModel.js" as PolkitModel
Item {
id: root
property string fontFamily: Style.font.menuFamily
// Bound to the central [polkit] section in shell.toml via Color.qml.
property color accent: Color.polkit.accent
property color background: Color.polkit.background
property color foreground: Color.polkit.text
property color border: Color.polkit.border
property color borderError: Color.polkit.borderError
property var borderSpec: Border.surfaceSpec("polkit", errorFlash ? "border-error" : "border", errorFlash ? borderError : border, Math.max(1, Style.space(2)), "border-alpha")
property color scrim: Color.polkit.scrim
readonly property int cornerRadius: Style.cornerRadius
property int contentMargin: Style.spacing.panelPadding
property int fieldHeight: Math.max(Style.space(42), Style.spacing.controlHeight)
property bool closing: false
property bool submitted: false
property string currentMessage: ""
property string currentPrompt: ""
property string currentSupplementary: ""
property bool responseRequired: false
property bool responseVisible: false
property bool failed: false
property bool errorFlash: false
// pam_fprintd appears in the polkit PAM stack (a sensor is enrolled).
property bool fingerprintConfigured: false
// Lid shut right now — the reader is physically unreachable, so we fall back
// to the password even when a sensor is enrolled. Refreshed per request.
property bool laptopClosed: false
property int shakeOffset: 0
readonly property bool dialogVisible: polkitAgent.isActive || closing
// We show one method at a time. Fingerprint owns the dialog while PAM is
// waiting on the reader (lid open, sensor enrolled); the moment PAM asks for
// a password — including immediately when the lid is shut and the clamshell
// gate skips pam_fprintd — we switch to the password field instead.
readonly property bool fingerprintMode: fingerprintConfigured && !laptopClosed && dialogVisible && !responseRequired && !submitted && !errorFlash
readonly property int cardHeight: panel.height > 0 ? Math.min(fieldHeight + contentMargin * 2, panel.height - Style.gapsOut * 2) : fieldHeight + contentMargin * 2
// Password mode is a wide field; fingerprint mode collapses to a square that
// just frames the centered sensor icon.
readonly property int cardWidth: fingerprintMode ? cardHeight : Math.min(Style.space(312), Math.max(Style.space(260), panel.width - Style.gapsOut * 2))
function authorizationLabel(message) {
return PolkitModel.authorizationLabel(message)
}
function loadPamConfig(raw) {
fingerprintConfigured = PolkitModel.fingerprintConfiguredFromPamConfig(raw)
}
function refreshLidState() {
if (!laptopClosedProc.running) laptopClosedProc.running = true
}
function resetSnapshot() {
currentMessage = ""
currentPrompt = ""
currentSupplementary = ""
responseRequired = false
responseVisible = false
failed = false
errorFlash = false
submitted = false
passwordInput.text = ""
}
function syncFromFlow() {
var flow = polkitAgent.flow
if (!flow) return
currentMessage = String(flow.message || "Authentication is needed...")
currentPrompt = String(flow.inputPrompt || "")
currentSupplementary = String(flow.supplementaryMessage || "")
responseRequired = !!flow.isResponseRequired
responseVisible = !!flow.responseVisible
failed = !!flow.failed
if (responseRequired) submitted = false
}
function beginFlow() {
closeTimer.stop()
closing = false
submitted = false
passwordInput.text = ""
refreshLidState()
syncFromFlow()
Qt.callLater(refocus)
}
function refocus() {
if (!dialogVisible) return
// In fingerprint mode there is no field to type into — park focus on the
// key catcher so Escape still cancels; otherwise focus the password field.
if (fingerprintMode) keyCatcher.forceActiveFocus()
else passwordInput.forceActiveFocus()
}
function submitResponse() {
var flow = polkitAgent.flow
if (!flow || !flow.isResponseRequired) return
submitted = true
errorFlash = false
flow.submit(passwordInput.text)
passwordInput.text = ""
keyCatcher.forceActiveFocus()
}
function cancelRequest() {
var flow = polkitAgent.flow
passwordInput.text = ""
submitted = false
closing = true
closeTimer.restart()
if (flow) flow.cancelAuthenticationRequest()
}
function triggerFailureFeedback() {
submitted = false
errorFlash = true
passwordInput.text = ""
errorTimer.restart()
shakeAnimation.restart()
Qt.callLater(refocus)
}
Timer {
id: closeTimer
interval: 300
repeat: false
onTriggered: {
closing = false
resetSnapshot()
}
}
Timer {
id: errorTimer
interval: 1200
repeat: false
onTriggered: root.errorFlash = false
}
SequentialAnimation {
id: shakeAnimation
NumberAnimation { target: root; property: "shakeOffset"; to: -8; duration: 35; easing.type: Easing.OutQuad }
NumberAnimation { target: root; property: "shakeOffset"; to: 8; duration: 50; easing.type: Easing.InOutQuad }
NumberAnimation { target: root; property: "shakeOffset"; to: 0; duration: 55; easing.type: Easing.OutQuad }
}
FileView {
path: "/etc/pam.d/polkit-1"
watchChanges: true
printErrors: false
onLoaded: root.loadPamConfig(text())
onLoadFailed: root.fingerprintConfigured = false
onFileChanged: reload()
}
Process {
id: laptopClosedProc
command: ["bash", "-c", "blob-hw-laptop-closed && echo closed || echo open"]
stdout: StdioCollector { id: laptopClosedOut; waitForEnd: true }
onExited: root.laptopClosed = String(laptopClosedOut.text || "").trim() === "closed"
}
PolkitAgent {
id: polkitAgent
path: "/org/blob/PolkitAgent"
onAuthenticationRequestStarted: root.beginFlow()
onIsActiveChanged: {
if (isActive) root.syncFromFlow()
else if (!root.closing) root.resetSnapshot()
}
onIsRegisteredChanged: {
if (isRegistered) console.log("blob polkit agent registered")
else console.warn("blob polkit agent is not registered; another agent may be running")
}
}
Connections {
target: polkitAgent.flow
function onIsResponseRequiredChanged() {
root.syncFromFlow()
if (!polkitAgent.flow || !polkitAgent.flow.isResponseRequired) passwordInput.text = ""
Qt.callLater(root.refocus)
}
function onInputPromptChanged() { root.syncFromFlow() }
function onResponseVisibleChanged() { root.syncFromFlow() }
function onSupplementaryMessageChanged() { root.syncFromFlow() }
function onFailedChanged() { root.syncFromFlow() }
function onAuthenticationFailed() {
root.syncFromFlow()
root.triggerFailureFeedback()
}
function onAuthenticationSucceeded() {
root.closing = true
closeTimer.restart()
}
function onAuthenticationRequestCancelled() {
root.closing = true
closeTimer.restart()
}
}
PanelWindow {
id: panel
visible: root.dialogVisible
anchors { top: true; bottom: true; left: true; right: true }
color: "transparent"
WlrLayershell.namespace: "blob-polkit"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
exclusionMode: ExclusionMode.Ignore
Rectangle {
anchors.fill: parent
color: root.scrim
}
MouseArea {
anchors.fill: parent
onClicked: root.refocus()
}
BorderSurface {
id: card
width: root.cardWidth
height: root.cardHeight
radius: root.cornerRadius
anchors.centerIn: parent
anchors.horizontalCenterOffset: root.shakeOffset
color: root.background
borderSpec: root.borderSpec
padding: root.contentMargin
MouseArea { anchors.fill: parent; onClicked: root.refocus() }
Item {
id: keyCatcher
anchors.fill: parent
focus: true
Keys.priority: Keys.BeforeItem
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
root.cancelRequest()
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
if (root.responseRequired) root.submitResponse()
event.accepted = true
}
}
}
// Fingerprint mode shows just the sensor icon, centered and alone \u2014 no
// padlock, no field, no prompt text.
OpticalGlyph {
anchors.centerIn: parent
width: Math.round(root.fieldHeight * 0.7)
height: width
visible: root.fingerprintMode
text: "\udb80\ude37"
fontFamily: root.fontFamily
fontSize: Math.round(root.fieldHeight * 0.7)
color: root.errorFlash ? Color.polkit.textError : root.accent
}
Row {
id: cardRow
visible: !root.fingerprintMode
anchors.fill: parent
anchors.topMargin: card.contentTopInset
anchors.rightMargin: card.contentRightInset
anchors.bottomMargin: card.contentBottomInset
anchors.leftMargin: card.contentLeftInset
spacing: Style.space(14)
Text {
text: "\uf023"
color: root.errorFlash ? Color.polkit.textError : root.accent
font.family: root.fontFamily
font.pixelSize: Style.font.iconLarge
width: Style.space(26)
height: root.fieldHeight
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Item {
width: parent.width - Style.space(40)
height: root.fieldHeight
TextInput {
id: passwordInput
anchors.fill: parent
verticalAlignment: TextInput.AlignVCenter
activeFocusOnPress: true
clip: true
selectionColor: Util.alpha(root.accent, 0.45)
selectedTextColor: root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.iconLarge
echoMode: root.responseVisible ? TextInput.Normal : TextInput.Password
passwordCharacter: "\u2022"
color: root.errorFlash ? Color.polkit.textError : root.foreground
cursorVisible: activeFocus && !root.submitted && !root.errorFlash
readOnly: root.submitted || root.errorFlash
enabled: root.dialogVisible
onAccepted: root.submitResponse()
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
root.cancelRequest()
event.accepted = true
}
}
}
Text {
textFormat: Text.PlainText
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: root.errorFlash ? "Wrong" : (root.submitted ? "Checking..." : "Enter password")
color: root.errorFlash ? Color.polkit.textError : root.foreground
opacity: root.errorFlash ? 1 : 0.36
font.family: root.fontFamily
font.pixelSize: Style.font.iconLarge
elide: Text.ElideRight
visible: passwordInput.text.length === 0
}
Rectangle {
width: Math.max(1, Style.space(2))
height: Style.space(24)
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
color: root.errorFlash ? Color.polkit.textError : root.foreground
visible: passwordInput.visible && passwordInput.activeFocus && passwordInput.text.length === 0 && !root.submitted && !root.errorFlash
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
enabled: passwordInput.visible
onClicked: passwordInput.forceActiveFocus()
}
}
}
}
Rectangle {
width: Math.min(justificationText.implicitWidth + Style.space(24), panel.width - Style.gapsOut * 2)
height: Style.space(28)
anchors.horizontalCenter: card.horizontalCenter
anchors.bottom: card.top
anchors.bottomMargin: Style.space(10)
radius: root.cornerRadius
color: root.background
Text {
id: justificationText
textFormat: Text.PlainText
anchors.fill: parent
anchors.leftMargin: Style.space(12)
anchors.rightMargin: Style.space(12)
text: root.authorizationLabel(root.currentMessage)
color: root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideMiddle
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
function promptLooksFingerprint(text) {
var s = String(text || "").toLowerCase()
return s.indexOf("finger") !== -1 || s.indexOf("fprint") !== -1 || s.indexOf("swipe") !== -1
}
function fingerprintConfiguredFromPamConfig(raw) {
// Fingerprint is available whenever pam_fprintd appears anywhere in the auth
// stack — it need not be the first module. A clamshell gate (pam_exec) may
// legitimately precede it to skip fingerprint while the lid is closed.
var lines = String(raw || "").split("\n")
for (var i = 0; i < lines.length; i++) {
var line = lines[i].replace(/^\s+|\s+$/g, "")
if (!line || line.charAt(0) === "#") continue
if (!line.match(/^auth\s+/)) continue
if (line.indexOf("pam_fprintd.so") !== -1) return true
}
return false
}
function authorizationLabel(message) {
var text = String(message || "")
var match = text.match(/^Authentication is (?:needed|required) to run [`']([^`']+)[`'] as /i)
return match ? "Authorize running '" + match[1] + "'" : text
}
if (typeof module !== "undefined") {
module.exports = {
promptLooksFingerprint: promptLooksFingerprint,
fingerprintConfiguredFromPamConfig: fingerprintConfiguredFromPamConfig,
authorizationLabel: authorizationLabel
}
}
+20
View File
@@ -0,0 +1,20 @@
{
"schemaVersion": 1,
"id": "blob.polkit",
"name": "Polkit Agent",
"version": "1.0.0",
"author": "Blob",
"description": "Theme-aware authentication dialog for privileged actions.",
"blob": {
"capabilities": [
"authentication"
]
},
"kinds": [
"service"
],
"keepLoaded": true,
"entryPoints": {
"service": "PolkitAgent.qml"
}
}