1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-15 08:42:47 -04:00

(SystemUpdate): Ensure Polkit Prompts Top Level Auth layer

This commit is contained in:
purian23
2026-05-07 16:17:12 -04:00
parent 7fb4b6e0d9
commit 0d3eb774e2
2 changed files with 223 additions and 198 deletions
+213 -198
View File
@@ -1,11 +1,12 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import Quickshell.Wayland
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
FloatingWindow { PanelWindow {
id: root id: root
property bool disablePopupTransparency: true property bool disablePopupTransparency: true
@@ -55,7 +56,9 @@ FloatingWindow {
passwordField.forceActiveFocus(); passwordField.forceActiveFocus();
} }
function show() { function show(targetScreen) {
if (targetScreen)
screen = targetScreen;
passwordInput = ""; passwordInput = "";
isLoading = false; isLoading = false;
awaitingFprintForPassword = false; awaitingFprintForPassword = false;
@@ -96,12 +99,23 @@ FloatingWindow {
} }
objectName: "polkitAuthModal" objectName: "polkitAuthModal"
title: I18n.tr("Authentication")
minimumSize: Qt.size(460, 220) screen: Quickshell.screens[0]
maximumSize: Qt.size(460, 220) color: "transparent"
color: Theme.surfaceContainer
visible: false visible: false
WlrLayershell.namespace: "dms:polkit-auth"
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
anchors {
left: true
top: true
right: true
bottom: true
}
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
Qt.callLater(focusPasswordField); Qt.callLater(focusPasswordField);
@@ -191,212 +205,218 @@ FloatingWindow {
onLoadFailed: root.passwordAuthPamText = "" onLoadFailed: root.passwordAuthPamText = ""
} }
FocusScope { // Dim overlay — clicking outside cancels authentication
id: contentFocusScope Rectangle {
anchors.fill: parent anchors.fill: parent
focus: true color: Qt.rgba(0, 0, 0, 0.45)
Keys.onEscapePressed: event => { MouseArea {
cancelAuth(); anchors.fill: parent
event.accepted = true; onClicked: cancelAuth()
} }
}
Item { // Centered dialog box
id: headerSection Rectangle {
anchors.left: parent.left id: dialogBox
anchors.right: parent.right width: 460
anchors.top: parent.top height: 220
anchors.margins: Theme.spacingM anchors.centerIn: parent
height: Math.max(titleColumn.implicitHeight, windowButtonRow.implicitHeight) color: Theme.surfaceContainer
radius: Theme.cornerRadius
MouseArea { FocusScope {
anchors.fill: parent id: contentFocusScope
onPressed: windowControls.tryStartMove() anchors.fill: parent
onDoubleClicked: windowControls.tryToggleMaximize() focus: true
}
Column { Keys.onEscapePressed: event => {
id: titleColumn cancelAuth();
anchors.left: parent.left event.accepted = true;
anchors.right: windowButtonRow.left
anchors.rightMargin: Theme.spacingM
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Authentication Required")
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
StyledText {
text: currentFlow?.message ?? ""
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium
width: parent.width
wrapMode: Text.Wrap
maximumLineCount: 2
elide: Text.ElideRight
visible: text !== ""
}
StyledText {
text: currentFlow?.supplementaryMessage ?? ""
font.pixelSize: Theme.fontSizeSmall
color: (currentFlow?.supplementaryIsError ?? false) ? Theme.error : Theme.surfaceTextMedium
width: parent.width
wrapMode: Text.Wrap
maximumLineCount: 2
elide: Text.ElideRight
opacity: (currentFlow?.supplementaryIsError ?? false) ? 1 : 0.8
visible: text !== ""
}
}
Row {
id: windowButtonRow
anchors.right: parent.right
anchors.top: parent.top
spacing: Theme.spacingXS
DankActionButton {
visible: windowControls.supported && windowControls.canMaximize
iconName: root.maximized ? "fullscreen_exit" : "fullscreen"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: windowControls.tryToggleMaximize()
}
DankActionButton {
iconName: "close"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
enabled: !isLoading
opacity: enabled ? 1 : 0.5
onClicked: cancelAuth()
}
}
}
Column {
id: bottomSection
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
StyledText {
text: currentFlow?.inputPrompt ?? ""
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
width: parent.width
visible: text !== ""
}
DankTextField {
id: passwordField
width: parent.width
height: inputFieldHeight
backgroundColor: Theme.surfaceHover
normalBorderColor: Theme.outlineStrong
focusedBorderColor: Theme.primary
borderWidth: 1
focusedBorderWidth: 2
leftIconName: polkitPamHasFprint ? "fingerprint" : ""
leftIconSize: 20
leftIconColor: Theme.primary
leftIconFocusedColor: Theme.primary
opacity: isLoading ? 0.5 : 1
font.pixelSize: Theme.fontSizeMedium
textColor: Theme.surfaceText
text: passwordInput
showPasswordToggle: !(currentFlow?.responseVisible ?? false)
echoMode: (currentFlow?.responseVisible ?? false) || passwordVisible ? TextInput.Normal : TextInput.Password
placeholderText: ""
enabled: !isLoading
onTextEdited: passwordInput = text
onAccepted: submitAuth()
}
StyledText {
text: I18n.tr("Authentication failed, please try again")
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
width: parent.width
visible: currentFlow?.failed ?? false
} }
Item { Item {
width: parent.width id: headerSection
height: 36 anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingM
height: Math.max(titleColumn.implicitHeight, windowButtonRow.implicitHeight)
Row { Column {
anchors.right: parent.right id: titleColumn
anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left
spacing: Theme.spacingM anchors.right: windowButtonRow.left
anchors.rightMargin: Theme.spacingM
spacing: Theme.spacingXS
Rectangle { StyledText {
width: Math.max(70, cancelText.contentWidth + Theme.spacingM * 2) text: I18n.tr("Authentication Required")
height: 36 font.pixelSize: Theme.fontSizeLarge
radius: Theme.cornerRadius color: Theme.surfaceText
color: cancelArea.containsMouse ? Theme.surfaceTextHover : "transparent" font.weight: Font.Medium
border.color: Theme.surfaceVariantAlpha
border.width: 1
enabled: !isLoading
opacity: enabled ? 1 : 0.5
StyledText {
id: cancelText
anchors.centerIn: parent
text: I18n.tr("Cancel")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
MouseArea {
id: cancelArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: parent.enabled
onClicked: cancelAuth()
}
} }
Rectangle { StyledText {
width: Math.max(80, authText.contentWidth + Theme.spacingM * 2) text: currentFlow?.message ?? ""
height: 36 font.pixelSize: Theme.fontSizeMedium
radius: Theme.cornerRadius color: Theme.surfaceTextMedium
color: authArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary width: parent.width
wrapMode: Text.Wrap
maximumLineCount: 2
elide: Text.ElideRight
visible: text !== ""
}
StyledText {
text: currentFlow?.supplementaryMessage ?? ""
font.pixelSize: Theme.fontSizeSmall
color: (currentFlow?.supplementaryIsError ?? false) ? Theme.error : Theme.surfaceTextMedium
width: parent.width
wrapMode: Text.Wrap
maximumLineCount: 2
elide: Text.ElideRight
opacity: (currentFlow?.supplementaryIsError ?? false) ? 1 : 0.8
visible: text !== ""
}
}
Row {
id: windowButtonRow
anchors.right: parent.right
anchors.top: parent.top
spacing: Theme.spacingXS
DankActionButton {
iconName: "close"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
enabled: !isLoading enabled: !isLoading
opacity: enabled ? 1 : 0.5 opacity: enabled ? 1 : 0.5
onClicked: cancelAuth()
}
}
}
StyledText { Column {
id: authText id: bottomSection
anchors.centerIn: parent anchors.left: parent.left
text: I18n.tr("Authenticate") anchors.right: parent.right
font.pixelSize: Theme.fontSizeMedium anchors.bottom: parent.bottom
color: Theme.background anchors.margins: Theme.spacingM
font.weight: Font.Medium spacing: Theme.spacingS
StyledText {
text: currentFlow?.inputPrompt ?? ""
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
width: parent.width
visible: text !== ""
}
DankTextField {
id: passwordField
width: parent.width
height: inputFieldHeight
backgroundColor: Theme.surfaceHover
normalBorderColor: Theme.outlineStrong
focusedBorderColor: Theme.primary
borderWidth: 1
focusedBorderWidth: 2
leftIconName: polkitPamHasFprint ? "fingerprint" : ""
leftIconSize: 20
leftIconColor: Theme.primary
leftIconFocusedColor: Theme.primary
opacity: isLoading ? 0.5 : 1
font.pixelSize: Theme.fontSizeMedium
textColor: Theme.surfaceText
text: passwordInput
showPasswordToggle: !(currentFlow?.responseVisible ?? false)
echoMode: (currentFlow?.responseVisible ?? false) || passwordVisible ? TextInput.Normal : TextInput.Password
placeholderText: ""
enabled: !isLoading
onTextEdited: passwordInput = text
onAccepted: submitAuth()
}
StyledText {
text: I18n.tr("Authentication failed, please try again")
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
width: parent.width
visible: currentFlow?.failed ?? false
}
Item {
width: parent.width
height: 36
Row {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Rectangle {
width: Math.max(70, cancelText.contentWidth + Theme.spacingM * 2)
height: 36
radius: Theme.cornerRadius
color: cancelArea.containsMouse ? Theme.surfaceTextHover : "transparent"
border.color: Theme.surfaceVariantAlpha
border.width: 1
enabled: !isLoading
opacity: enabled ? 1 : 0.5
StyledText {
id: cancelText
anchors.centerIn: parent
text: I18n.tr("Cancel")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
MouseArea {
id: cancelArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: parent.enabled
onClicked: cancelAuth()
}
} }
MouseArea { Rectangle {
id: authArea width: Math.max(80, authText.contentWidth + Theme.spacingM * 2)
anchors.fill: parent height: 36
hoverEnabled: true radius: Theme.cornerRadius
cursorShape: Qt.PointingHandCursor color: authArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
enabled: parent.enabled enabled: !isLoading
onClicked: submitAuth() opacity: enabled ? 1 : 0.5
}
Behavior on color { StyledText {
ColorAnimation { id: authText
duration: Theme.shortDuration anchors.centerIn: parent
easing.type: Theme.standardEasing text: I18n.tr("Authenticate")
font.pixelSize: Theme.fontSizeMedium
color: Theme.background
font.weight: Font.Medium
}
MouseArea {
id: authArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: parent.enabled
onClicked: submitAuth()
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
} }
} }
} }
@@ -404,9 +424,4 @@ FloatingWindow {
} }
} }
} }
FloatingWindowControls {
id: windowControls
targetWindow: root
}
} }
@@ -33,6 +33,16 @@ DankPopout {
return WlrKeyboardFocus.Exclusive; return WlrKeyboardFocus.Exclusive;
} }
Connections {
target: PolkitService.agent
enabled: PolkitService.polkitAvailable && triggerScreen !== null
function onAuthenticationRequestStarted() {
if (PopoutService.polkitAuthModal && triggerScreen)
PopoutService.polkitAuthModal.screen = triggerScreen;
}
}
Connections { Connections {
target: SystemUpdateService target: SystemUpdateService
function onIsUpgradingChanged() { function onIsUpgradingChanged() {