// The authentication prompt. // // Deliberately a Panama surface rather than the compositor's stock agent: this // is the window that asks for the password to everything, and it was the one // window on the desktop that looked like it belonged to something else. // // Two things here are security, not styling. It takes EXCLUSIVE keyboard focus, // so keystrokes cannot reach the window underneath while a password is being // typed. And the field is cleared on every exit path, including the ones nobody // plans for. import Quickshell import Quickshell.Wayland import QtQuick import qs.config import qs.services import qs.modules.settings PanelWindow { id: root visible: Polkit.active color: "transparent" anchors { top: true; bottom: true; left: true; right: true } exclusiveZone: 0 WlrLayershell.namespace: "qs-polkit" WlrLayershell.layer: WlrLayer.Overlay // Exclusive, not OnDemand: a password prompt that lets keystrokes through // to whatever is behind it is a keylogger with extra steps. WlrLayershell.keyboardFocus: Polkit.active ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None onVisibleChanged: { if (root.visible) { field.text = ""; field.forceActiveFocus(); } else { field.text = ""; } } // Dims what is behind, and swallows clicks so nothing outside the dialog // can be operated while it is waiting. Rectangle { anchors.fill: parent color: Theme.alpha(Theme.bgDark, Theme.overlayAlpha) MouseArea { anchors.fill: parent // Clicking outside does nothing on purpose. Dismissing an // authentication request by misclick, and having the thing that // asked report a mysterious failure, is worse than an explicit // Cancel. hoverEnabled: true } } Rectangle { id: dialog anchors.centerIn: parent width: 420 implicitHeight: layout.implicitHeight + 44 radius: Theme.popoverRadius color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha) border.width: 1 border.color: Theme.alpha(Theme.fg, 0.1) Column { id: layout anchors.centerIn: parent width: parent.width - 44 spacing: 14 Text { width: parent.width text: "Authentication required" color: Theme.fg font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeLarge font.weight: Font.DemiBold wrapMode: Text.WordWrap } Text { width: parent.width text: Polkit.message color: Theme.fgDim font.family: Theme.fontFamily font.pixelSize: Theme.fontSize wrapMode: Text.WordWrap } Text { width: parent.width visible: Polkit.users.length > 1 text: "Authenticating as " + Polkit.chosenUser color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall } PasswordField { id: field width: parent.width placeholder: "Password" enabled: !Polkit.authenticating onAccepted: { if (field.text !== "") Polkit.submit(field.text); field.text = ""; } } Text { width: parent.width visible: Polkit.failureText !== "" text: Polkit.failureText color: Theme.danger font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall wrapMode: Text.WordWrap } Row { anchors.right: parent.right spacing: 8 SettingsButton { text: "Cancel" onClicked: Polkit.cancel() } SettingsButton { text: Polkit.authenticating ? "Checking…" : "Authenticate" tone: "accent" enabled: !Polkit.authenticating onClicked: { if (field.text !== "") Polkit.submit(field.text); field.text = ""; } } } } } // Escape cancels, which is what every other dialog on this desktop does. Item { anchors.fill: parent focus: true Keys.onEscapePressed: Polkit.cancel() } }