mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-30 00:12:50 -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 screenName: ""
|
||||||
property string randomFact: ""
|
property string randomFact: ""
|
||||||
|
property string hyprlandCurrentLayout: ""
|
||||||
|
property string hyprlandKeyboard: ""
|
||||||
|
property int hyprlandLayoutCount: 0
|
||||||
property bool isPrimaryScreen: {
|
property bool isPrimaryScreen: {
|
||||||
if (!Qt.application.screens || Qt.application.screens.length === 0)
|
if (!Qt.application.screens || Qt.application.screens.length === 0)
|
||||||
return true
|
return true
|
||||||
@@ -61,6 +64,11 @@ Item {
|
|||||||
sessionListProc.running = true
|
sessionListProc.running = true
|
||||||
applyLastSuccessfulUser()
|
applyLastSuccessfulUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CompositorService.isHyprland) {
|
||||||
|
updateHyprlandLayout()
|
||||||
|
hyprlandLayoutUpdateTimer.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyLastSuccessfulUser() {
|
function applyLastSuccessfulUser() {
|
||||||
@@ -75,6 +83,56 @@ Item {
|
|||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
WeatherService.removeRef()
|
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.
|
// ! This was for development and testing, just leaving so people can see how I did it.
|
||||||
@@ -438,6 +496,8 @@ Item {
|
|||||||
StyledText {
|
StyledText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 20
|
Layout.preferredHeight: 20
|
||||||
|
Layout.topMargin: -Theme.spacingS
|
||||||
|
Layout.bottomMargin: -Theme.spacingS
|
||||||
text: {
|
text: {
|
||||||
if (GreeterState.pamState === "error")
|
if (GreeterState.pamState === "error")
|
||||||
return "Authentication error - try again"
|
return "Authentication error - try again"
|
||||||
@@ -448,7 +508,6 @@ Item {
|
|||||||
color: Theme.error
|
color: Theme.error
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
visible: GreeterState.pamState !== ""
|
|
||||||
opacity: GreeterState.pamState !== "" ? 1 : 0
|
opacity: GreeterState.pamState !== "" ? 1 : 0
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
@@ -461,7 +520,7 @@ Item {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.topMargin: Theme.spacingS
|
Layout.topMargin: 0
|
||||||
Layout.preferredWidth: switchUserRow.width + Theme.spacingL * 2
|
Layout.preferredWidth: switchUserRow.width + Theme.spacingL * 2
|
||||||
Layout.preferredHeight: 40
|
Layout.preferredHeight: 40
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
@@ -516,6 +575,91 @@ Item {
|
|||||||
anchors.margins: Theme.spacingXL
|
anchors.margins: Theme.spacingXL
|
||||||
spacing: Theme.spacingL
|
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 {
|
Row {
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: MprisController.activePlayer
|
visible: MprisController.activePlayer
|
||||||
@@ -1106,9 +1250,8 @@ Item {
|
|||||||
|
|
||||||
function onAuthFailure(message) {
|
function onAuthFailure(message) {
|
||||||
GreeterState.pamState = "fail"
|
GreeterState.pamState = "fail"
|
||||||
GreeterState.reset()
|
GreeterState.passwordBuffer = ""
|
||||||
inputField.text = ""
|
inputField.text = ""
|
||||||
PortalService.profileImage = ""
|
|
||||||
placeholderDelay.restart()
|
placeholderDelay.restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Manual installation:
|
|||||||
1. Install `greetd` (in most distro's standard repositories)
|
1. Install `greetd` (in most distro's standard repositories)
|
||||||
2. Copy `assets/dms-niri.kdl` or `assets/dms-hypr.conf` to `/etc/greetd`
|
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
|
- 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`
|
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`
|
5. Edit or create `/etc/greetd/config.toml`
|
||||||
```toml
|
```toml
|
||||||
@@ -38,7 +38,7 @@ vt = 1
|
|||||||
# in the `video` group.
|
# in the `video` group.
|
||||||
user = "greeter"
|
user = "greeter"
|
||||||
|
|
||||||
command = "/etc/greetd/start-dms.sh"%
|
command = "/usr/local/bin/start-dms-greetd.sh"
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable the greeter with `sudo systemctl enable greetd`
|
Enable the greeter with `sudo systemctl enable greetd`
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ Item {
|
|||||||
property bool unlocking: false
|
property bool unlocking: false
|
||||||
property string pamState: ""
|
property string pamState: ""
|
||||||
property string randomFact: ""
|
property string randomFact: ""
|
||||||
|
property string hyprlandCurrentLayout: ""
|
||||||
|
property string hyprlandKeyboard: ""
|
||||||
|
property int hyprlandLayoutCount: 0
|
||||||
|
|
||||||
signal unlockRequested
|
signal unlockRequested
|
||||||
|
|
||||||
@@ -55,6 +58,11 @@ Item {
|
|||||||
|
|
||||||
WeatherService.addRef()
|
WeatherService.addRef()
|
||||||
UserInfoService.refreshUserInfo()
|
UserInfoService.refreshUserInfo()
|
||||||
|
|
||||||
|
if (CompositorService.isHyprland) {
|
||||||
|
updateHyprlandLayout()
|
||||||
|
hyprlandLayoutUpdateTimer.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onDemoModeChanged: {
|
onDemoModeChanged: {
|
||||||
if (demoMode) {
|
if (demoMode) {
|
||||||
@@ -63,6 +71,56 @@ Item {
|
|||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
WeatherService.removeRef()
|
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 {
|
Loader {
|
||||||
@@ -520,7 +578,7 @@ Item {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: root.pamState ? 20 : 0
|
Layout.preferredHeight: 20
|
||||||
text: {
|
text: {
|
||||||
if (root.pamState === "error") {
|
if (root.pamState === "error") {
|
||||||
return "Authentication error - try again"
|
return "Authentication error - try again"
|
||||||
@@ -536,7 +594,6 @@ Item {
|
|||||||
color: Theme.error
|
color: Theme.error
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
visible: root.pamState !== ""
|
|
||||||
opacity: root.pamState !== "" ? 1 : 0
|
opacity: root.pamState !== "" ? 1 : 0
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
@@ -545,13 +602,6 @@ Item {
|
|||||||
easing.type: Theme.standardEasing
|
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
|
anchors.margins: Theme.spacingXL
|
||||||
spacing: Theme.spacingL
|
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 {
|
Row {
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
visible: MprisController.activePlayer
|
visible: MprisController.activePlayer
|
||||||
@@ -1036,6 +1172,8 @@ Item {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log("Authentication failed:", res)
|
console.log("Authentication failed:", res)
|
||||||
|
passwordField.text = ""
|
||||||
|
root.passwordBuffer = ""
|
||||||
if (res === PamResult.Error)
|
if (res === PamResult.Error)
|
||||||
root.pamState = "error"
|
root.pamState = "error"
|
||||||
else if (res === PamResult.MaxTries)
|
else if (res === PamResult.MaxTries)
|
||||||
|
|||||||
Reference in New Issue
Block a user