mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
Merge branch 'master' of github.com:bbedward/DankMaterialShell into wip/plugins
This commit is contained in:
@@ -1353,7 +1353,7 @@ Singleton {
|
||||
id: settingsFile
|
||||
|
||||
path: isGreeterMode ? "" : StandardPaths.writableLocation(StandardPaths.ConfigLocation) + "/DankMaterialShell/settings.json"
|
||||
blockLoading: isGreeterMode
|
||||
blockLoading: true
|
||||
blockWrites: true
|
||||
atomicWrites: true
|
||||
watchChanges: !isGreeterMode
|
||||
|
||||
@@ -333,9 +333,10 @@ Item {
|
||||
bottom: barWindow.isVertical ? parent.bottom : undefined
|
||||
}
|
||||
// Only enable mouse handling while hidden (for reveal-on-edge logic).
|
||||
hoverEnabled: SettingsData.dankBarAutoHide && !topBarCore.reveal
|
||||
readonly property bool inOverview: CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview
|
||||
hoverEnabled: SettingsData.dankBarAutoHide && !topBarCore.reveal && !inOverview
|
||||
acceptedButtons: Qt.NoButton
|
||||
enabled: SettingsData.dankBarAutoHide && !topBarCore.reveal
|
||||
enabled: SettingsData.dankBarAutoHide && !topBarCore.reveal && !inOverview
|
||||
|
||||
Item {
|
||||
id: topBarContainer
|
||||
|
||||
@@ -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
|
||||
@@ -970,7 +1114,7 @@ Item {
|
||||
if (idx >= 0) {
|
||||
GreeterState.currentSessionIndex = idx
|
||||
GreeterState.selectedSession = GreeterState.sessionExecs[idx]
|
||||
GreetdMemory.setLastSessionId(GreeterState.sessionExecs[idx].split(" ")[0])
|
||||
GreetdMemory.setLastSessionId(GreeterState.sessionPaths[idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -987,6 +1131,7 @@ Item {
|
||||
property string currentSessionName: GreeterState.sessionList[GreeterState.currentSessionIndex] || ""
|
||||
property int pendingParsers: 0
|
||||
|
||||
|
||||
function finalizeSessionSelection() {
|
||||
if (GreeterState.sessionList.length === 0) {
|
||||
return
|
||||
@@ -997,8 +1142,8 @@ Item {
|
||||
const savedSession = GreetdMemory.lastSessionId
|
||||
let foundSaved = false
|
||||
if (savedSession) {
|
||||
for (var i = 0; i < GreeterState.sessionExecs.length; i++) {
|
||||
if (GreeterState.sessionExecs[i].toLowerCase().includes(savedSession.toLowerCase()) || GreeterState.sessionList[i].toLowerCase().includes(savedSession.toLowerCase())) {
|
||||
for (var i = 0; i < GreeterState.sessionPaths.length; i++) {
|
||||
if (GreeterState.sessionPaths[i] === savedSession) {
|
||||
GreeterState.currentSessionIndex = i
|
||||
foundSaved = true
|
||||
break
|
||||
@@ -1059,10 +1204,13 @@ Item {
|
||||
if (!GreeterState.sessionList.includes(name)) {
|
||||
let newList = GreeterState.sessionList.slice()
|
||||
let newExecs = GreeterState.sessionExecs.slice()
|
||||
let newPaths = GreeterState.sessionPaths.slice()
|
||||
newList.push(name)
|
||||
newExecs.push(exec)
|
||||
newPaths.push(desktopPath)
|
||||
GreeterState.sessionList = newList
|
||||
GreeterState.sessionExecs = newExecs
|
||||
GreeterState.sessionPaths = newPaths
|
||||
root.sessionCount = GreeterState.sessionList.length
|
||||
}
|
||||
}
|
||||
@@ -1098,17 +1246,16 @@ Item {
|
||||
GreeterState.unlocking = true
|
||||
const sessionCmd = GreeterState.selectedSession || GreeterState.sessionExecs[GreeterState.currentSessionIndex]
|
||||
if (sessionCmd) {
|
||||
GreetdMemory.setLastSessionId(sessionCmd.split(" ")[0])
|
||||
GreetdMemory.setLastSessionId(GreeterState.sessionPaths[GreeterState.currentSessionIndex])
|
||||
GreetdMemory.setLastSuccessfulUser(GreeterState.username)
|
||||
Greetd.launch(sessionCmd.split(" "), [], true)
|
||||
Greetd.launch(sessionCmd.split(" "), ["XDG_SESSION_TYPE=wayland"], true)
|
||||
}
|
||||
}
|
||||
|
||||
function onAuthFailure(message) {
|
||||
GreeterState.pamState = "fail"
|
||||
GreeterState.reset()
|
||||
GreeterState.passwordBuffer = ""
|
||||
inputField.text = ""
|
||||
PortalService.profileImage = ""
|
||||
placeholderDelay.restart()
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ Singleton {
|
||||
|
||||
property var sessionList: []
|
||||
property var sessionExecs: []
|
||||
property var sessionPaths: []
|
||||
property int currentSessionIndex: 0
|
||||
|
||||
function reset() {
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
env = DMS_RUN_GREETER,1
|
||||
env = QT_QPA_PLATFORM,wayland
|
||||
env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1
|
||||
env = EGL_PLATFORM,gbm
|
||||
|
||||
exec = sh -c "qs -p _DMS_PATH_; hyprctl dispatch exit"
|
||||
|
||||
@@ -4,8 +4,6 @@ hotkey-overlay {
|
||||
|
||||
environment {
|
||||
DMS_RUN_GREETER "1"
|
||||
QT_QPA_PLATFORM "wayland"
|
||||
QT_WAYLAND_DISABLE_WINDOWDECORATION "1"
|
||||
}
|
||||
|
||||
spawn-at-startup "sh" "-c" "qs -p _DMS_PATH_; niri msg action quit --skip-confirmation"
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
EGL_PLATFORM=gbm Hyprland -c /etc/greetd/dms-hypr.conf
|
||||
export XDG_SESSION_TYPE=wayland
|
||||
export QT_QPA_PLATFORM=wayland
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
|
||||
export EGL_PLATFORM=gbm
|
||||
|
||||
exec Hyprland -c /etc/greetd/dms-hypr.conf
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
EGL_PLATFORM=gbm niri -c /etc/greetd/dms-niri.kdl
|
||||
export XDG_SESSION_TYPE=wayland
|
||||
export QT_QPA_PLATFORM=wayland
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
|
||||
export EGL_PLATFORM=gbm
|
||||
|
||||
exec niri -c /etc/greetd/dms-niri.kdl
|
||||
@@ -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