mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
lock+greeter: show keyboard layout widget, spacing adjustments
This commit is contained in:
@@ -19,6 +19,9 @@ Item {
|
||||
|
||||
property string screenName: ""
|
||||
property string randomFact: ""
|
||||
property string hyprlandCurrentLayout: ""
|
||||
property string hyprlandKeyboard: ""
|
||||
property int hyprlandLayoutCount: 0
|
||||
property bool isPrimaryScreen: {
|
||||
if (!Qt.application.screens || Qt.application.screens.length === 0)
|
||||
return true
|
||||
@@ -61,6 +64,11 @@ Item {
|
||||
sessionListProc.running = true
|
||||
applyLastSuccessfulUser()
|
||||
}
|
||||
|
||||
if (CompositorService.isHyprland) {
|
||||
updateHyprlandLayout()
|
||||
hyprlandLayoutUpdateTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
function applyLastSuccessfulUser() {
|
||||
@@ -75,6 +83,56 @@ Item {
|
||||
|
||||
Component.onDestruction: {
|
||||
WeatherService.removeRef()
|
||||
if (CompositorService.isHyprland) {
|
||||
hyprlandLayoutUpdateTimer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
hyprlandKeyboard = mainKeyboard.name
|
||||
if (mainKeyboard && mainKeyboard.active_keymap) {
|
||||
const parts = mainKeyboard.active_keymap.split(" ")
|
||||
if (parts.length > 0) {
|
||||
hyprlandCurrentLayout = parts[0].substring(0, 2).toUpperCase()
|
||||
} else {
|
||||
hyprlandCurrentLayout = mainKeyboard.active_keymap.substring(0, 2).toUpperCase()
|
||||
}
|
||||
} else {
|
||||
hyprlandCurrentLayout = ""
|
||||
}
|
||||
if (mainKeyboard && mainKeyboard.layout_names) {
|
||||
hyprlandLayoutCount = mainKeyboard.layout_names.length
|
||||
} else {
|
||||
hyprlandLayoutCount = 0
|
||||
}
|
||||
} catch (e) {
|
||||
hyprlandCurrentLayout = ""
|
||||
hyprlandLayoutCount = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hyprlandLayoutUpdateTimer
|
||||
interval: 1000
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: updateHyprlandLayout()
|
||||
}
|
||||
|
||||
// ! This was for development and testing, just leaving so people can see how I did it.
|
||||
@@ -438,6 +496,8 @@ Item {
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 20
|
||||
Layout.topMargin: -Theme.spacingS
|
||||
Layout.bottomMargin: -Theme.spacingS
|
||||
text: {
|
||||
if (GreeterState.pamState === "error")
|
||||
return "Authentication error - try again"
|
||||
@@ -448,7 +508,6 @@ Item {
|
||||
color: Theme.error
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: GreeterState.pamState !== ""
|
||||
opacity: GreeterState.pamState !== "" ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -461,7 +520,7 @@ Item {
|
||||
|
||||
Rectangle {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: Theme.spacingS
|
||||
Layout.topMargin: 0
|
||||
Layout.preferredWidth: switchUserRow.width + Theme.spacingL * 2
|
||||
Layout.preferredHeight: 40
|
||||
radius: Theme.cornerRadius
|
||||
@@ -516,6 +575,91 @@ Item {
|
||||
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: MprisController.activePlayer
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
visible: MprisController.activePlayer
|
||||
@@ -1106,9 +1250,8 @@ Item {
|
||||
|
||||
function onAuthFailure(message) {
|
||||
GreeterState.pamState = "fail"
|
||||
GreeterState.reset()
|
||||
GreeterState.passwordBuffer = ""
|
||||
inputField.text = ""
|
||||
PortalService.profileImage = ""
|
||||
placeholderDelay.restart()
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Manual installation:
|
||||
1. Install `greetd` (in most distro's standard repositories)
|
||||
2. Copy `assets/dms-niri.kdl` or `assets/dms-hypr.conf` to `/etc/greetd`
|
||||
- niri if you want to run the greeter under niri, hypr if you want to run the greeter under Hyprland
|
||||
3. Copy `assets/greet-niri.sh` or `assets/greet-hyprland.sh` to `/etc/greetd/start-dms.sh`
|
||||
3. Copy `assets/greet-niri.sh` or `assets/greet-hyprland.sh` to `/usr/local/bin/start-dms-greetd.sh`
|
||||
4. Edit `/etc/greetd/dms-niri.kdl` or `/etc/greetd/dms-hypr.conf` and replace `_DMS_PATH_` with the absolute path to dms, e.g. `/home/joecool/.config/quickshell/dms`
|
||||
5. Edit or create `/etc/greetd/config.toml`
|
||||
```toml
|
||||
@@ -38,7 +38,7 @@ vt = 1
|
||||
# in the `video` group.
|
||||
user = "greeter"
|
||||
|
||||
command = "/etc/greetd/start-dms.sh"%
|
||||
command = "/usr/local/bin/start-dms-greetd.sh"
|
||||
```
|
||||
|
||||
Enable the greeter with `sudo systemctl enable greetd`
|
||||
|
||||
@@ -20,6 +20,9 @@ Item {
|
||||
property bool unlocking: false
|
||||
property string pamState: ""
|
||||
property string randomFact: ""
|
||||
property string hyprlandCurrentLayout: ""
|
||||
property string hyprlandKeyboard: ""
|
||||
property int hyprlandLayoutCount: 0
|
||||
|
||||
signal unlockRequested
|
||||
|
||||
@@ -55,6 +58,11 @@ Item {
|
||||
|
||||
WeatherService.addRef()
|
||||
UserInfoService.refreshUserInfo()
|
||||
|
||||
if (CompositorService.isHyprland) {
|
||||
updateHyprlandLayout()
|
||||
hyprlandLayoutUpdateTimer.start()
|
||||
}
|
||||
}
|
||||
onDemoModeChanged: {
|
||||
if (demoMode) {
|
||||
@@ -63,6 +71,56 @@ Item {
|
||||
}
|
||||
Component.onDestruction: {
|
||||
WeatherService.removeRef()
|
||||
if (CompositorService.isHyprland) {
|
||||
hyprlandLayoutUpdateTimer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
hyprlandKeyboard = mainKeyboard.name
|
||||
if (mainKeyboard && mainKeyboard.active_keymap) {
|
||||
const parts = mainKeyboard.active_keymap.split(" ")
|
||||
if (parts.length > 0) {
|
||||
hyprlandCurrentLayout = parts[0].substring(0, 2).toUpperCase()
|
||||
} else {
|
||||
hyprlandCurrentLayout = mainKeyboard.active_keymap.substring(0, 2).toUpperCase()
|
||||
}
|
||||
} else {
|
||||
hyprlandCurrentLayout = ""
|
||||
}
|
||||
if (mainKeyboard && mainKeyboard.layout_names) {
|
||||
hyprlandLayoutCount = mainKeyboard.layout_names.length
|
||||
} else {
|
||||
hyprlandLayoutCount = 0
|
||||
}
|
||||
} catch (e) {
|
||||
hyprlandCurrentLayout = ""
|
||||
hyprlandLayoutCount = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hyprlandLayoutUpdateTimer
|
||||
interval: 1000
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: updateHyprlandLayout()
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -520,7 +578,7 @@ Item {
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.pamState ? 20 : 0
|
||||
Layout.preferredHeight: 20
|
||||
text: {
|
||||
if (root.pamState === "error") {
|
||||
return "Authentication error - try again"
|
||||
@@ -536,7 +594,6 @@ Item {
|
||||
color: Theme.error
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: root.pamState !== ""
|
||||
opacity: root.pamState !== "" ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -545,13 +602,6 @@ Item {
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on Layout.preferredHeight {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,6 +622,92 @@ Item {
|
||||
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
|
||||
enabled: !demoMode
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
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: MprisController.activePlayer
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
visible: MprisController.activePlayer
|
||||
@@ -1036,6 +1172,8 @@ Item {
|
||||
return
|
||||
}
|
||||
console.log("Authentication failed:", res)
|
||||
passwordField.text = ""
|
||||
root.passwordBuffer = ""
|
||||
if (res === PamResult.Error)
|
||||
root.pamState = "error"
|
||||
else if (res === PamResult.MaxTries)
|
||||
|
||||
Reference in New Issue
Block a user