mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-29 07:52:50 -05:00
osd/audio: bind audio change to pipewire, suppress OSDs on startup and
resume from suspend
This commit is contained in:
@@ -21,6 +21,22 @@ Singleton {
|
|||||||
property bool isLightMode: false
|
property bool isLightMode: false
|
||||||
property bool doNotDisturb: false
|
property bool doNotDisturb: false
|
||||||
property bool isSwitchingMode: false
|
property bool isSwitchingMode: false
|
||||||
|
property bool suppressOSD: true
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: osdSuppressTimer
|
||||||
|
interval: 2000
|
||||||
|
running: true
|
||||||
|
onTriggered: root.suppressOSD = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SessionService
|
||||||
|
function onSessionResumed() {
|
||||||
|
root.suppressOSD = true;
|
||||||
|
osdSuppressTimer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property string wallpaperPath: ""
|
property string wallpaperPath: ""
|
||||||
property bool perMonitorWallpaper: false
|
property bool perMonitorWallpaper: false
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtCore
|
import QtCore
|
||||||
@@ -15,7 +14,6 @@ Singleton {
|
|||||||
readonly property PwNode sink: Pipewire.defaultAudioSink
|
readonly property PwNode sink: Pipewire.defaultAudioSink
|
||||||
readonly property PwNode source: Pipewire.defaultAudioSource
|
readonly property PwNode source: Pipewire.defaultAudioSource
|
||||||
|
|
||||||
property bool suppressOSD: true
|
|
||||||
property bool soundsAvailable: false
|
property bool soundsAvailable: false
|
||||||
property bool gsettingsAvailable: false
|
property bool gsettingsAvailable: false
|
||||||
property var availableSoundThemes: []
|
property var availableSoundThemes: []
|
||||||
@@ -33,12 +31,14 @@ Singleton {
|
|||||||
|
|
||||||
signal micMuteChanged
|
signal micMuteChanged
|
||||||
|
|
||||||
Timer {
|
Connections {
|
||||||
id: startupTimer
|
target: root.sink?.audio ?? null
|
||||||
interval: 500
|
|
||||||
repeat: false
|
function onVolumeChanged() {
|
||||||
running: true
|
if (SessionData.suppressOSD)
|
||||||
onTriggered: root.suppressOSD = false
|
return;
|
||||||
|
root.playVolumeChangeSoundIfEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectSoundsAvailability() {
|
function detectSoundsAvailability() {
|
||||||
@@ -47,35 +47,33 @@ Singleton {
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtMultimedia
|
import QtMultimedia
|
||||||
Item {}
|
Item {}
|
||||||
`, root, "AudioService.TestComponent")
|
`, root, "AudioService.TestComponent");
|
||||||
if (testObj) {
|
if (testObj) {
|
||||||
testObj.destroy()
|
testObj.destroy();
|
||||||
}
|
}
|
||||||
soundsAvailable = true
|
soundsAvailable = true;
|
||||||
return true
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
soundsAvailable = false
|
soundsAvailable = false;
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkGsettings() {
|
function checkGsettings() {
|
||||||
Proc.runCommand("checkGsettings", ["sh", "-c", "gsettings get org.gnome.desktop.sound theme-name 2>/dev/null"], (output, exitCode) => {
|
Proc.runCommand("checkGsettings", ["sh", "-c", "gsettings get org.gnome.desktop.sound theme-name 2>/dev/null"], (output, exitCode) => {
|
||||||
gsettingsAvailable = (exitCode === 0)
|
gsettingsAvailable = (exitCode === 0);
|
||||||
if (gsettingsAvailable) {
|
if (gsettingsAvailable) {
|
||||||
scanSoundThemes()
|
scanSoundThemes();
|
||||||
getCurrentSoundTheme()
|
getCurrentSoundTheme();
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scanSoundThemes() {
|
function scanSoundThemes() {
|
||||||
const xdgDataDirs = Quickshell.env("XDG_DATA_DIRS")
|
const xdgDataDirs = Quickshell.env("XDG_DATA_DIRS");
|
||||||
const searchPaths = xdgDataDirs && xdgDataDirs.trim() !== ""
|
const searchPaths = xdgDataDirs && xdgDataDirs.trim() !== "" ? xdgDataDirs.split(":").concat(Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation))) : ["/usr/share", "/usr/local/share", Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation))];
|
||||||
? xdgDataDirs.split(":").concat(Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation)))
|
|
||||||
: ["/usr/share", "/usr/local/share", Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation))]
|
|
||||||
|
|
||||||
const basePaths = searchPaths.map(p => p + "/sounds").join(" ")
|
const basePaths = searchPaths.map(p => p + "/sounds").join(" ");
|
||||||
const script = `
|
const script = `
|
||||||
for base_dir in ${basePaths}; do
|
for base_dir in ${basePaths}; do
|
||||||
[ -d "$base_dir" ] || continue
|
[ -d "$base_dir" ] || continue
|
||||||
@@ -84,65 +82,63 @@ Singleton {
|
|||||||
basename "$theme_dir"
|
basename "$theme_dir"
|
||||||
done
|
done
|
||||||
done | sort -u
|
done | sort -u
|
||||||
`
|
`;
|
||||||
|
|
||||||
Proc.runCommand("scanSoundThemes", ["sh", "-c", script], (output, exitCode) => {
|
Proc.runCommand("scanSoundThemes", ["sh", "-c", script], (output, exitCode) => {
|
||||||
if (exitCode === 0 && output.trim()) {
|
if (exitCode === 0 && output.trim()) {
|
||||||
const themes = output.trim().split('\n').filter(t => t && t.length > 0)
|
const themes = output.trim().split('\n').filter(t => t && t.length > 0);
|
||||||
availableSoundThemes = themes
|
availableSoundThemes = themes;
|
||||||
} else {
|
} else {
|
||||||
availableSoundThemes = []
|
availableSoundThemes = [];
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentSoundTheme() {
|
function getCurrentSoundTheme() {
|
||||||
Proc.runCommand("getCurrentSoundTheme", ["sh", "-c", "gsettings get org.gnome.desktop.sound theme-name 2>/dev/null | sed \"s/'//g\""], (output, exitCode) => {
|
Proc.runCommand("getCurrentSoundTheme", ["sh", "-c", "gsettings get org.gnome.desktop.sound theme-name 2>/dev/null | sed \"s/'//g\""], (output, exitCode) => {
|
||||||
if (exitCode === 0 && output.trim()) {
|
if (exitCode === 0 && output.trim()) {
|
||||||
currentSoundTheme = output.trim()
|
currentSoundTheme = output.trim();
|
||||||
console.log("AudioService: Current system sound theme:", currentSoundTheme)
|
console.log("AudioService: Current system sound theme:", currentSoundTheme);
|
||||||
if (SettingsData.useSystemSoundTheme) {
|
if (SettingsData.useSystemSoundTheme) {
|
||||||
discoverSoundFiles(currentSoundTheme)
|
discoverSoundFiles(currentSoundTheme);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentSoundTheme = ""
|
currentSoundTheme = "";
|
||||||
console.log("AudioService: No system sound theme found")
|
console.log("AudioService: No system sound theme found");
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSoundTheme(themeName) {
|
function setSoundTheme(themeName) {
|
||||||
if (!themeName || themeName === currentSoundTheme) {
|
if (!themeName || themeName === currentSoundTheme) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Proc.runCommand("setSoundTheme", ["sh", "-c", `gsettings set org.gnome.desktop.sound theme-name '${themeName}'`], (output, exitCode) => {
|
Proc.runCommand("setSoundTheme", ["sh", "-c", `gsettings set org.gnome.desktop.sound theme-name '${themeName}'`], (output, exitCode) => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
currentSoundTheme = themeName
|
currentSoundTheme = themeName;
|
||||||
if (SettingsData.useSystemSoundTheme) {
|
if (SettingsData.useSystemSoundTheme) {
|
||||||
discoverSoundFiles(themeName)
|
discoverSoundFiles(themeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function discoverSoundFiles(themeName) {
|
function discoverSoundFiles(themeName) {
|
||||||
if (!themeName) {
|
if (!themeName) {
|
||||||
soundFilePaths = {}
|
soundFilePaths = {};
|
||||||
if (soundsAvailable) {
|
if (soundsAvailable) {
|
||||||
destroySoundPlayers()
|
destroySoundPlayers();
|
||||||
createSoundPlayers()
|
createSoundPlayers();
|
||||||
}
|
}
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const xdgDataDirs = Quickshell.env("XDG_DATA_DIRS")
|
const xdgDataDirs = Quickshell.env("XDG_DATA_DIRS");
|
||||||
const searchPaths = xdgDataDirs && xdgDataDirs.trim() !== ""
|
const searchPaths = xdgDataDirs && xdgDataDirs.trim() !== "" ? xdgDataDirs.split(":").concat(Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation))) : ["/usr/share", "/usr/local/share", Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation))];
|
||||||
? xdgDataDirs.split(":").concat(Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation)))
|
|
||||||
: ["/usr/share", "/usr/local/share", Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation))]
|
|
||||||
|
|
||||||
const extensions = ["oga", "ogg", "wav", "mp3", "flac"]
|
const extensions = ["oga", "ogg", "wav", "mp3", "flac"];
|
||||||
const themesToSearch = themeName !== "freedesktop" ? `${themeName} freedesktop` : themeName
|
const themesToSearch = themeName !== "freedesktop" ? `${themeName} freedesktop` : themeName;
|
||||||
|
|
||||||
const script = `
|
const script = `
|
||||||
for event_key in audio-volume-change power-plug power-unplug message message-new-instant; do
|
for event_key in audio-volume-change power-plug power-unplug message message-new-instant; do
|
||||||
@@ -179,26 +175,26 @@ Singleton {
|
|||||||
[ $found -eq 1 ] && break
|
[ $found -eq 1 ] && break
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
`
|
`;
|
||||||
|
|
||||||
Proc.runCommand("discoverSoundFiles", ["sh", "-c", script], (output, exitCode) => {
|
Proc.runCommand("discoverSoundFiles", ["sh", "-c", script], (output, exitCode) => {
|
||||||
const paths = {}
|
const paths = {};
|
||||||
if (exitCode === 0 && output.trim()) {
|
if (exitCode === 0 && output.trim()) {
|
||||||
const lines = output.trim().split('\n')
|
const lines = output.trim().split('\n');
|
||||||
for (let line of lines) {
|
for (let line of lines) {
|
||||||
const parts = line.split('=')
|
const parts = line.split('=');
|
||||||
if (parts.length === 2) {
|
if (parts.length === 2) {
|
||||||
paths[parts[0]] = "file://" + parts[1]
|
paths[parts[0]] = "file://" + parts[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
soundFilePaths = paths
|
soundFilePaths = paths;
|
||||||
|
|
||||||
if (soundsAvailable) {
|
if (soundsAvailable) {
|
||||||
destroySoundPlayers()
|
destroySoundPlayers();
|
||||||
createSoundPlayers()
|
createSoundPlayers();
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSoundPath(soundEvent) {
|
function getSoundPath(soundEvent) {
|
||||||
@@ -208,45 +204,45 @@ Singleton {
|
|||||||
"power-unplug": "../assets/sounds/plasma/power-unplug.wav",
|
"power-unplug": "../assets/sounds/plasma/power-unplug.wav",
|
||||||
"message": "../assets/sounds/freedesktop/message.wav",
|
"message": "../assets/sounds/freedesktop/message.wav",
|
||||||
"message-new-instant": "../assets/sounds/freedesktop/message-new-instant.wav"
|
"message-new-instant": "../assets/sounds/freedesktop/message-new-instant.wav"
|
||||||
}
|
};
|
||||||
|
|
||||||
const specialConditions = {
|
const specialConditions = {
|
||||||
"smooth": ["audio-volume-change"]
|
"smooth": ["audio-volume-change"]
|
||||||
}
|
};
|
||||||
|
|
||||||
const themeLower = currentSoundTheme.toLowerCase()
|
const themeLower = currentSoundTheme.toLowerCase();
|
||||||
if (SettingsData.useSystemSoundTheme && specialConditions[themeLower]?.includes(soundEvent)) {
|
if (SettingsData.useSystemSoundTheme && specialConditions[themeLower]?.includes(soundEvent)) {
|
||||||
const bundledPath = Qt.resolvedUrl(soundMap[soundEvent] || "../assets/sounds/freedesktop/message.wav")
|
const bundledPath = Qt.resolvedUrl(soundMap[soundEvent] || "../assets/sounds/freedesktop/message.wav");
|
||||||
console.log("AudioService: Using bundled sound (special condition) for", soundEvent, ":", bundledPath)
|
console.log("AudioService: Using bundled sound (special condition) for", soundEvent, ":", bundledPath);
|
||||||
return bundledPath
|
return bundledPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SettingsData.useSystemSoundTheme && soundFilePaths[soundEvent]) {
|
if (SettingsData.useSystemSoundTheme && soundFilePaths[soundEvent]) {
|
||||||
console.log("AudioService: Using system sound for", soundEvent, ":", soundFilePaths[soundEvent])
|
console.log("AudioService: Using system sound for", soundEvent, ":", soundFilePaths[soundEvent]);
|
||||||
return soundFilePaths[soundEvent]
|
return soundFilePaths[soundEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
const bundledPath = Qt.resolvedUrl(soundMap[soundEvent] || "../assets/sounds/freedesktop/message.wav")
|
const bundledPath = Qt.resolvedUrl(soundMap[soundEvent] || "../assets/sounds/freedesktop/message.wav");
|
||||||
console.log("AudioService: Using bundled sound for", soundEvent, ":", bundledPath)
|
console.log("AudioService: Using bundled sound for", soundEvent, ":", bundledPath);
|
||||||
return bundledPath
|
return bundledPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadSounds() {
|
function reloadSounds() {
|
||||||
console.log("AudioService: Reloading sounds, useSystemSoundTheme:", SettingsData.useSystemSoundTheme, "currentSoundTheme:", currentSoundTheme)
|
console.log("AudioService: Reloading sounds, useSystemSoundTheme:", SettingsData.useSystemSoundTheme, "currentSoundTheme:", currentSoundTheme);
|
||||||
if (SettingsData.useSystemSoundTheme && currentSoundTheme) {
|
if (SettingsData.useSystemSoundTheme && currentSoundTheme) {
|
||||||
discoverSoundFiles(currentSoundTheme)
|
discoverSoundFiles(currentSoundTheme);
|
||||||
} else {
|
} else {
|
||||||
soundFilePaths = {}
|
soundFilePaths = {};
|
||||||
if (soundsAvailable) {
|
if (soundsAvailable) {
|
||||||
destroySoundPlayers()
|
destroySoundPlayers();
|
||||||
createSoundPlayers()
|
createSoundPlayers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupMediaDevices() {
|
function setupMediaDevices() {
|
||||||
if (!soundsAvailable || mediaDevices) {
|
if (!soundsAvailable || mediaDevices) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -259,7 +255,7 @@ Singleton {
|
|||||||
console.log("AudioService: MediaDevices initialized, default output:", defaultAudioOutput?.description)
|
console.log("AudioService: MediaDevices initialized, default output:", defaultAudioOutput?.description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.MediaDevices")
|
`, root, "AudioService.MediaDevices");
|
||||||
|
|
||||||
if (mediaDevices) {
|
if (mediaDevices) {
|
||||||
mediaDevicesConnections = Qt.createQmlObject(`
|
mediaDevicesConnections = Qt.createQmlObject(`
|
||||||
@@ -272,48 +268,48 @@ Singleton {
|
|||||||
root.createSoundPlayers()
|
root.createSoundPlayers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.MediaDevicesConnections")
|
`, root, "AudioService.MediaDevicesConnections");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("AudioService: MediaDevices not available, using default audio output")
|
console.log("AudioService: MediaDevices not available, using default audio output");
|
||||||
mediaDevices = null
|
mediaDevices = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroySoundPlayers() {
|
function destroySoundPlayers() {
|
||||||
if (volumeChangeSound) {
|
if (volumeChangeSound) {
|
||||||
volumeChangeSound.destroy()
|
volumeChangeSound.destroy();
|
||||||
volumeChangeSound = null
|
volumeChangeSound = null;
|
||||||
}
|
}
|
||||||
if (powerPlugSound) {
|
if (powerPlugSound) {
|
||||||
powerPlugSound.destroy()
|
powerPlugSound.destroy();
|
||||||
powerPlugSound = null
|
powerPlugSound = null;
|
||||||
}
|
}
|
||||||
if (powerUnplugSound) {
|
if (powerUnplugSound) {
|
||||||
powerUnplugSound.destroy()
|
powerUnplugSound.destroy();
|
||||||
powerUnplugSound = null
|
powerUnplugSound = null;
|
||||||
}
|
}
|
||||||
if (normalNotificationSound) {
|
if (normalNotificationSound) {
|
||||||
normalNotificationSound.destroy()
|
normalNotificationSound.destroy();
|
||||||
normalNotificationSound = null
|
normalNotificationSound = null;
|
||||||
}
|
}
|
||||||
if (criticalNotificationSound) {
|
if (criticalNotificationSound) {
|
||||||
criticalNotificationSound.destroy()
|
criticalNotificationSound.destroy();
|
||||||
criticalNotificationSound = null
|
criticalNotificationSound = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSoundPlayers() {
|
function createSoundPlayers() {
|
||||||
if (!soundsAvailable) {
|
if (!soundsAvailable) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMediaDevices()
|
setupMediaDevices();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const deviceProperty = mediaDevices ? `device: root.mediaDevices.defaultAudioOutput\n ` : ""
|
const deviceProperty = mediaDevices ? `device: root.mediaDevices.defaultAudioOutput\n ` : "";
|
||||||
|
|
||||||
const volumeChangePath = getSoundPath("audio-volume-change")
|
const volumeChangePath = getSoundPath("audio-volume-change");
|
||||||
volumeChangeSound = Qt.createQmlObject(`
|
volumeChangeSound = Qt.createQmlObject(`
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtMultimedia
|
import QtMultimedia
|
||||||
@@ -323,9 +319,9 @@ Singleton {
|
|||||||
${deviceProperty}volume: 1.0
|
${deviceProperty}volume: 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.VolumeChangeSound")
|
`, root, "AudioService.VolumeChangeSound");
|
||||||
|
|
||||||
const powerPlugPath = getSoundPath("power-plug")
|
const powerPlugPath = getSoundPath("power-plug");
|
||||||
powerPlugSound = Qt.createQmlObject(`
|
powerPlugSound = Qt.createQmlObject(`
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtMultimedia
|
import QtMultimedia
|
||||||
@@ -335,9 +331,9 @@ Singleton {
|
|||||||
${deviceProperty}volume: 1.0
|
${deviceProperty}volume: 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.PowerPlugSound")
|
`, root, "AudioService.PowerPlugSound");
|
||||||
|
|
||||||
const powerUnplugPath = getSoundPath("power-unplug")
|
const powerUnplugPath = getSoundPath("power-unplug");
|
||||||
powerUnplugSound = Qt.createQmlObject(`
|
powerUnplugSound = Qt.createQmlObject(`
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtMultimedia
|
import QtMultimedia
|
||||||
@@ -347,9 +343,9 @@ Singleton {
|
|||||||
${deviceProperty}volume: 1.0
|
${deviceProperty}volume: 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.PowerUnplugSound")
|
`, root, "AudioService.PowerUnplugSound");
|
||||||
|
|
||||||
const messagePath = getSoundPath("message")
|
const messagePath = getSoundPath("message");
|
||||||
normalNotificationSound = Qt.createQmlObject(`
|
normalNotificationSound = Qt.createQmlObject(`
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtMultimedia
|
import QtMultimedia
|
||||||
@@ -359,9 +355,9 @@ Singleton {
|
|||||||
${deviceProperty}volume: 1.0
|
${deviceProperty}volume: 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.NormalNotificationSound")
|
`, root, "AudioService.NormalNotificationSound");
|
||||||
|
|
||||||
const messageNewInstantPath = getSoundPath("message-new-instant")
|
const messageNewInstantPath = getSoundPath("message-new-instant");
|
||||||
criticalNotificationSound = Qt.createQmlObject(`
|
criticalNotificationSound = Qt.createQmlObject(`
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtMultimedia
|
import QtMultimedia
|
||||||
@@ -371,114 +367,114 @@ Singleton {
|
|||||||
${deviceProperty}volume: 1.0
|
${deviceProperty}volume: 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, root, "AudioService.CriticalNotificationSound")
|
`, root, "AudioService.CriticalNotificationSound");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("AudioService: Error creating sound players:", e)
|
console.warn("AudioService: Error creating sound players:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playVolumeChangeSound() {
|
function playVolumeChangeSound() {
|
||||||
if (soundsAvailable && volumeChangeSound) {
|
if (soundsAvailable && volumeChangeSound) {
|
||||||
volumeChangeSound.play()
|
volumeChangeSound.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playPowerPlugSound() {
|
function playPowerPlugSound() {
|
||||||
if (soundsAvailable && powerPlugSound) {
|
if (soundsAvailable && powerPlugSound) {
|
||||||
powerPlugSound.play()
|
powerPlugSound.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playPowerUnplugSound() {
|
function playPowerUnplugSound() {
|
||||||
if (soundsAvailable && powerUnplugSound) {
|
if (soundsAvailable && powerUnplugSound) {
|
||||||
powerUnplugSound.play()
|
powerUnplugSound.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playNormalNotificationSound() {
|
function playNormalNotificationSound() {
|
||||||
if (soundsAvailable && normalNotificationSound && !SessionData.doNotDisturb) {
|
if (soundsAvailable && normalNotificationSound && !SessionData.doNotDisturb) {
|
||||||
normalNotificationSound.play()
|
normalNotificationSound.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playCriticalNotificationSound() {
|
function playCriticalNotificationSound() {
|
||||||
if (soundsAvailable && criticalNotificationSound && !SessionData.doNotDisturb) {
|
if (soundsAvailable && criticalNotificationSound && !SessionData.doNotDisturb) {
|
||||||
criticalNotificationSound.play()
|
criticalNotificationSound.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playVolumeChangeSoundIfEnabled() {
|
function playVolumeChangeSoundIfEnabled() {
|
||||||
if (SettingsData.soundsEnabled && SettingsData.soundVolumeChanged) {
|
if (SettingsData.soundsEnabled && SettingsData.soundVolumeChanged) {
|
||||||
playVolumeChangeSound()
|
playVolumeChangeSound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayName(node) {
|
function displayName(node) {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.properties && node.properties["device.description"]) {
|
if (node.properties && node.properties["device.description"]) {
|
||||||
return node.properties["device.description"]
|
return node.properties["device.description"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.description && node.description !== node.name) {
|
if (node.description && node.description !== node.name) {
|
||||||
return node.description
|
return node.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.nickname && node.nickname !== node.name) {
|
if (node.nickname && node.nickname !== node.name) {
|
||||||
return node.nickname
|
return node.nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.name.includes("analog-stereo")) {
|
if (node.name.includes("analog-stereo")) {
|
||||||
return "Built-in Speakers"
|
return "Built-in Speakers";
|
||||||
}
|
}
|
||||||
if (node.name.includes("bluez")) {
|
if (node.name.includes("bluez")) {
|
||||||
return "Bluetooth Audio"
|
return "Bluetooth Audio";
|
||||||
}
|
}
|
||||||
if (node.name.includes("usb")) {
|
if (node.name.includes("usb")) {
|
||||||
return "USB Audio"
|
return "USB Audio";
|
||||||
}
|
}
|
||||||
if (node.name.includes("hdmi")) {
|
if (node.name.includes("hdmi")) {
|
||||||
return "HDMI Audio"
|
return "HDMI Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.name
|
return node.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function subtitle(name) {
|
function subtitle(name) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name.includes('usb-')) {
|
if (name.includes('usb-')) {
|
||||||
if (name.includes('SteelSeries')) {
|
if (name.includes('SteelSeries')) {
|
||||||
return "USB Gaming Headset"
|
return "USB Gaming Headset";
|
||||||
}
|
}
|
||||||
if (name.includes('Generic')) {
|
if (name.includes('Generic')) {
|
||||||
return "USB Audio Device"
|
return "USB Audio Device";
|
||||||
}
|
}
|
||||||
return "USB Audio"
|
return "USB Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name.includes('pci-')) {
|
if (name.includes('pci-')) {
|
||||||
if (name.includes('01_00.1') || name.includes('01:00.1')) {
|
if (name.includes('01_00.1') || name.includes('01:00.1')) {
|
||||||
return "NVIDIA GPU Audio"
|
return "NVIDIA GPU Audio";
|
||||||
}
|
}
|
||||||
return "PCI Audio"
|
return "PCI Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name.includes('bluez')) {
|
if (name.includes('bluez')) {
|
||||||
return "Bluetooth Audio"
|
return "Bluetooth Audio";
|
||||||
}
|
}
|
||||||
if (name.includes('analog')) {
|
if (name.includes('analog')) {
|
||||||
return "Built-in Audio"
|
return "Built-in Audio";
|
||||||
}
|
}
|
||||||
if (name.includes('hdmi')) {
|
if (name.includes('hdmi')) {
|
||||||
return "HDMI Audio"
|
return "HDMI Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
PwObjectTracker {
|
PwObjectTracker {
|
||||||
@@ -487,136 +483,134 @@ Singleton {
|
|||||||
|
|
||||||
function setVolume(percentage) {
|
function setVolume(percentage) {
|
||||||
if (!root.sink?.audio) {
|
if (!root.sink?.audio) {
|
||||||
return "No audio sink available"
|
return "No audio sink available";
|
||||||
}
|
}
|
||||||
|
|
||||||
const clampedVolume = Math.max(0, Math.min(100, percentage))
|
const clampedVolume = Math.max(0, Math.min(100, percentage));
|
||||||
root.sink.audio.volume = clampedVolume / 100
|
root.sink.audio.volume = clampedVolume / 100;
|
||||||
return `Volume set to ${clampedVolume}%`
|
return `Volume set to ${clampedVolume}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMute() {
|
function toggleMute() {
|
||||||
if (!root.sink?.audio) {
|
if (!root.sink?.audio) {
|
||||||
return "No audio sink available"
|
return "No audio sink available";
|
||||||
}
|
}
|
||||||
|
|
||||||
root.sink.audio.muted = !root.sink.audio.muted
|
root.sink.audio.muted = !root.sink.audio.muted;
|
||||||
return root.sink.audio.muted ? "Audio muted" : "Audio unmuted"
|
return root.sink.audio.muted ? "Audio muted" : "Audio unmuted";
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMicVolume(percentage) {
|
function setMicVolume(percentage) {
|
||||||
if (!root.source?.audio) {
|
if (!root.source?.audio) {
|
||||||
return "No audio source available"
|
return "No audio source available";
|
||||||
}
|
}
|
||||||
|
|
||||||
const clampedVolume = Math.max(0, Math.min(100, percentage))
|
const clampedVolume = Math.max(0, Math.min(100, percentage));
|
||||||
root.source.audio.volume = clampedVolume / 100
|
root.source.audio.volume = clampedVolume / 100;
|
||||||
return `Microphone volume set to ${clampedVolume}%`
|
return `Microphone volume set to ${clampedVolume}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMicMute() {
|
function toggleMicMute() {
|
||||||
if (!root.source?.audio) {
|
if (!root.source?.audio) {
|
||||||
return "No audio source available"
|
return "No audio source available";
|
||||||
}
|
}
|
||||||
|
|
||||||
root.source.audio.muted = !root.source.audio.muted
|
root.source.audio.muted = !root.source.audio.muted;
|
||||||
return root.source.audio.muted ? "Microphone muted" : "Microphone unmuted"
|
return root.source.audio.muted ? "Microphone muted" : "Microphone unmuted";
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
target: "audio"
|
target: "audio"
|
||||||
|
|
||||||
function setvolume(percentage: string): string {
|
function setvolume(percentage: string): string {
|
||||||
return root.setVolume(parseInt(percentage))
|
return root.setVolume(parseInt(percentage));
|
||||||
}
|
}
|
||||||
|
|
||||||
function increment(step: string): string {
|
function increment(step: string): string {
|
||||||
if (!root.sink?.audio) {
|
if (!root.sink?.audio) {
|
||||||
return "No audio sink available"
|
return "No audio sink available";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.sink.audio.muted) {
|
if (root.sink.audio.muted) {
|
||||||
root.sink.audio.muted = false
|
root.sink.audio.muted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentVolume = Math.round(root.sink.audio.volume * 100)
|
const currentVolume = Math.round(root.sink.audio.volume * 100);
|
||||||
const stepValue = parseInt(step || "5")
|
const stepValue = parseInt(step || "5");
|
||||||
const newVolume = Math.max(0, Math.min(100, currentVolume + stepValue))
|
const newVolume = Math.max(0, Math.min(100, currentVolume + stepValue));
|
||||||
|
|
||||||
root.sink.audio.volume = newVolume / 100
|
root.sink.audio.volume = newVolume / 100;
|
||||||
root.playVolumeChangeSoundIfEnabled()
|
return `Volume increased to ${newVolume}%`;
|
||||||
return `Volume increased to ${newVolume}%`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function decrement(step: string): string {
|
function decrement(step: string): string {
|
||||||
if (!root.sink?.audio) {
|
if (!root.sink?.audio) {
|
||||||
return "No audio sink available"
|
return "No audio sink available";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.sink.audio.muted) {
|
if (root.sink.audio.muted) {
|
||||||
root.sink.audio.muted = false
|
root.sink.audio.muted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentVolume = Math.round(root.sink.audio.volume * 100)
|
const currentVolume = Math.round(root.sink.audio.volume * 100);
|
||||||
const stepValue = parseInt(step || "5")
|
const stepValue = parseInt(step || "5");
|
||||||
const newVolume = Math.max(0, Math.min(100, currentVolume - stepValue))
|
const newVolume = Math.max(0, Math.min(100, currentVolume - stepValue));
|
||||||
|
|
||||||
root.sink.audio.volume = newVolume / 100
|
root.sink.audio.volume = newVolume / 100;
|
||||||
root.playVolumeChangeSoundIfEnabled()
|
return `Volume decreased to ${newVolume}%`;
|
||||||
return `Volume decreased to ${newVolume}%`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mute(): string {
|
function mute(): string {
|
||||||
return root.toggleMute()
|
return root.toggleMute();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setmic(percentage: string): string {
|
function setmic(percentage: string): string {
|
||||||
return root.setMicVolume(parseInt(percentage))
|
return root.setMicVolume(parseInt(percentage));
|
||||||
}
|
}
|
||||||
|
|
||||||
function micmute(): string {
|
function micmute(): string {
|
||||||
const result = root.toggleMicMute()
|
const result = root.toggleMicMute();
|
||||||
root.micMuteChanged()
|
root.micMuteChanged();
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function status(): string {
|
function status(): string {
|
||||||
let result = "Audio Status:\n"
|
let result = "Audio Status:\n";
|
||||||
|
|
||||||
if (root.sink?.audio) {
|
if (root.sink?.audio) {
|
||||||
const volume = Math.round(root.sink.audio.volume * 100)
|
const volume = Math.round(root.sink.audio.volume * 100);
|
||||||
const muteStatus = root.sink.audio.muted ? " (muted)" : ""
|
const muteStatus = root.sink.audio.muted ? " (muted)" : "";
|
||||||
result += `Output: ${volume}%${muteStatus}\n`
|
result += `Output: ${volume}%${muteStatus}\n`;
|
||||||
} else {
|
} else {
|
||||||
result += "Output: No sink available\n"
|
result += "Output: No sink available\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.source?.audio) {
|
if (root.source?.audio) {
|
||||||
const micVolume = Math.round(root.source.audio.volume * 100)
|
const micVolume = Math.round(root.source.audio.volume * 100);
|
||||||
const muteStatus = root.source.audio.muted ? " (muted)" : ""
|
const muteStatus = root.source.audio.muted ? " (muted)" : "";
|
||||||
result += `Input: ${micVolume}%${muteStatus}`
|
result += `Input: ${micVolume}%${muteStatus}`;
|
||||||
} else {
|
} else {
|
||||||
result += "Input: No source available"
|
result += "Input: No source available";
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SettingsData
|
target: SettingsData
|
||||||
function onUseSystemSoundThemeChanged() {
|
function onUseSystemSoundThemeChanged() {
|
||||||
reloadSounds()
|
reloadSounds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!detectSoundsAvailability()) {
|
if (!detectSoundsAvailability()) {
|
||||||
console.warn("AudioService: QtMultimedia not available - sound effects disabled")
|
console.warn("AudioService: QtMultimedia not available - sound effects disabled");
|
||||||
} else {
|
} else {
|
||||||
console.info("AudioService: Sound effects enabled")
|
console.info("AudioService: Sound effects enabled");
|
||||||
checkGsettings()
|
checkGsettings();
|
||||||
Qt.callLater(createSoundPlayers)
|
Qt.callLater(createSoundPlayers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -23,9 +22,9 @@ Singleton {
|
|||||||
|
|
||||||
readonly property bool nativeInhibitorAvailable: {
|
readonly property bool nativeInhibitorAvailable: {
|
||||||
try {
|
try {
|
||||||
return typeof IdleInhibitor !== "undefined"
|
return typeof IdleInhibitor !== "undefined";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,10 +41,10 @@ Singleton {
|
|||||||
property string seat: ""
|
property string seat: ""
|
||||||
property string display: ""
|
property string display: ""
|
||||||
|
|
||||||
signal sessionLocked()
|
signal sessionLocked
|
||||||
signal sessionUnlocked()
|
signal sessionUnlocked
|
||||||
signal prepareForSleep()
|
signal sessionResumed
|
||||||
signal loginctlStateChanged()
|
signal loginctlStateChanged
|
||||||
|
|
||||||
property bool stateInitialized: false
|
property bool stateInitialized: false
|
||||||
|
|
||||||
@@ -57,30 +56,29 @@ Singleton {
|
|||||||
running: true
|
running: true
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
detectElogindProcess.running = true
|
detectElogindProcess.running = true;
|
||||||
detectHibernateProcess.running = true
|
detectHibernateProcess.running = true;
|
||||||
detectPrimeRunProcess.running = true
|
detectPrimeRunProcess.running = true;
|
||||||
console.info("SessionService: Native inhibitor available:", nativeInhibitorAvailable)
|
console.info("SessionService: Native inhibitor available:", nativeInhibitorAvailable);
|
||||||
if (!SettingsData.loginctlLockIntegration) {
|
if (!SettingsData.loginctlLockIntegration) {
|
||||||
console.log("SessionService: loginctl lock integration disabled by user")
|
console.log("SessionService: loginctl lock integration disabled by user");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (socketPath && socketPath.length > 0) {
|
if (socketPath && socketPath.length > 0) {
|
||||||
checkDMSCapabilities()
|
checkDMSCapabilities();
|
||||||
} else {
|
} else {
|
||||||
console.log("SessionService: DMS_SOCKET not set")
|
console.log("SessionService: DMS_SOCKET not set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: detectUwsmProcess
|
id: detectUwsmProcess
|
||||||
running: false
|
running: false
|
||||||
command: ["which", "uwsm"]
|
command: ["which", "uwsm"]
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
hasUwsm = (exitCode === 0)
|
hasUwsm = (exitCode === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +88,8 @@ Singleton {
|
|||||||
command: ["sh", "-c", "ps -eo comm= | grep -E '^(elogind|elogind-daemon)$'"]
|
command: ["sh", "-c", "ps -eo comm= | grep -E '^(elogind|elogind-daemon)$'"]
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
console.log("SessionService: Elogind detection exited with code", exitCode)
|
console.log("SessionService: Elogind detection exited with code", exitCode);
|
||||||
isElogind = (exitCode === 0)
|
isElogind = (exitCode === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +99,7 @@ Singleton {
|
|||||||
command: ["grep", "-q", "disk", "/sys/power/state"]
|
command: ["grep", "-q", "disk", "/sys/power/state"]
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
hibernateSupported = (exitCode === 0)
|
hibernateSupported = (exitCode === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +109,7 @@ Singleton {
|
|||||||
command: ["which", "prime-run"]
|
command: ["which", "prime-run"]
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
hasPrimeRun = (exitCode === 0)
|
hasPrimeRun = (exitCode === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,164 +122,167 @@ Singleton {
|
|||||||
splitMarker: "\n"
|
splitMarker: "\n"
|
||||||
onRead: data => {
|
onRead: data => {
|
||||||
if (data.trim().toLowerCase().includes("not running")) {
|
if (data.trim().toLowerCase().includes("not running")) {
|
||||||
_logout()
|
_logout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
_logout()
|
_logout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeShellArg(arg) {
|
function escapeShellArg(arg) {
|
||||||
return "'" + arg.replace(/'/g, "'\\''") + "'"
|
return "'" + arg.replace(/'/g, "'\\''") + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
function needsShellExecution(prefix) {
|
function needsShellExecution(prefix) {
|
||||||
if (!prefix || prefix.length === 0) return false
|
if (!prefix || prefix.length === 0)
|
||||||
return /[;&|<>()$`\\"']/.test(prefix)
|
return false;
|
||||||
|
return /[;&|<>()$`\\"']/.test(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchDesktopEntry(desktopEntry, usePrimeRun) {
|
function launchDesktopEntry(desktopEntry, usePrimeRun) {
|
||||||
let cmd = desktopEntry.command
|
let cmd = desktopEntry.command;
|
||||||
if (usePrimeRun && hasPrimeRun) {
|
if (usePrimeRun && hasPrimeRun) {
|
||||||
cmd = ["prime-run"].concat(cmd)
|
cmd = ["prime-run"].concat(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userPrefix = SettingsData.launchPrefix?.trim() || ""
|
const userPrefix = SettingsData.launchPrefix?.trim() || "";
|
||||||
const defaultPrefix = Quickshell.env("DMS_DEFAULT_LAUNCH_PREFIX") || ""
|
const defaultPrefix = Quickshell.env("DMS_DEFAULT_LAUNCH_PREFIX") || "";
|
||||||
const prefix = userPrefix.length > 0 ? userPrefix : defaultPrefix
|
const prefix = userPrefix.length > 0 ? userPrefix : defaultPrefix;
|
||||||
|
|
||||||
if (prefix.length > 0 && needsShellExecution(prefix)) {
|
if (prefix.length > 0 && needsShellExecution(prefix)) {
|
||||||
const escapedCmd = cmd.map(arg => escapeShellArg(arg)).join(" ")
|
const escapedCmd = cmd.map(arg => escapeShellArg(arg)).join(" ");
|
||||||
const shellCmd = `${prefix} ${escapedCmd}`
|
const shellCmd = `${prefix} ${escapedCmd}`;
|
||||||
|
|
||||||
Quickshell.execDetached({
|
Quickshell.execDetached({
|
||||||
command: ["sh", "-c", shellCmd],
|
command: ["sh", "-c", shellCmd],
|
||||||
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME"),
|
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME")
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
if (prefix.length > 0) {
|
if (prefix.length > 0) {
|
||||||
const launchPrefix = prefix.split(" ")
|
const launchPrefix = prefix.split(" ");
|
||||||
cmd = launchPrefix.concat(cmd)
|
cmd = launchPrefix.concat(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quickshell.execDetached({
|
Quickshell.execDetached({
|
||||||
command: cmd,
|
command: cmd,
|
||||||
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME"),
|
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME")
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchDesktopAction(desktopEntry, action, usePrimeRun) {
|
function launchDesktopAction(desktopEntry, action, usePrimeRun) {
|
||||||
let cmd = action.command
|
let cmd = action.command;
|
||||||
if (usePrimeRun && hasPrimeRun) {
|
if (usePrimeRun && hasPrimeRun) {
|
||||||
cmd = ["prime-run"].concat(cmd)
|
cmd = ["prime-run"].concat(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userPrefix = SettingsData.launchPrefix?.trim() || ""
|
const userPrefix = SettingsData.launchPrefix?.trim() || "";
|
||||||
const defaultPrefix = Quickshell.env("DMS_DEFAULT_LAUNCH_PREFIX") || ""
|
const defaultPrefix = Quickshell.env("DMS_DEFAULT_LAUNCH_PREFIX") || "";
|
||||||
const prefix = userPrefix.length > 0 ? userPrefix : defaultPrefix
|
const prefix = userPrefix.length > 0 ? userPrefix : defaultPrefix;
|
||||||
|
|
||||||
if (prefix.length > 0 && needsShellExecution(prefix)) {
|
if (prefix.length > 0 && needsShellExecution(prefix)) {
|
||||||
const escapedCmd = cmd.map(arg => escapeShellArg(arg)).join(" ")
|
const escapedCmd = cmd.map(arg => escapeShellArg(arg)).join(" ");
|
||||||
const shellCmd = `${prefix} ${escapedCmd}`
|
const shellCmd = `${prefix} ${escapedCmd}`;
|
||||||
|
|
||||||
Quickshell.execDetached({
|
Quickshell.execDetached({
|
||||||
command: ["sh", "-c", shellCmd],
|
command: ["sh", "-c", shellCmd],
|
||||||
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME"),
|
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME")
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
if (prefix.length > 0) {
|
if (prefix.length > 0) {
|
||||||
const launchPrefix = prefix.split(" ")
|
const launchPrefix = prefix.split(" ");
|
||||||
cmd = launchPrefix.concat(cmd)
|
cmd = launchPrefix.concat(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quickshell.execDetached({
|
Quickshell.execDetached({
|
||||||
command: cmd,
|
command: cmd,
|
||||||
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME"),
|
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME")
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// * Session management
|
// * Session management
|
||||||
function logout() {
|
function logout() {
|
||||||
if (hasUwsm) {
|
if (hasUwsm) {
|
||||||
uwsmLogout.running = true
|
uwsmLogout.running = true;
|
||||||
}
|
}
|
||||||
_logout()
|
_logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _logout() {
|
function _logout() {
|
||||||
if (SettingsData.customPowerActionLogout.length === 0) {
|
if (SettingsData.customPowerActionLogout.length === 0) {
|
||||||
if (CompositorService.isNiri) {
|
if (CompositorService.isNiri) {
|
||||||
NiriService.quit()
|
NiriService.quit();
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CompositorService.isDwl) {
|
if (CompositorService.isDwl) {
|
||||||
DwlService.quit()
|
DwlService.quit();
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CompositorService.isSway) {
|
if (CompositorService.isSway) {
|
||||||
try { I3.dispatch("exit") } catch(_){}
|
try {
|
||||||
return
|
I3.dispatch("exit");
|
||||||
|
} catch (_) {}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hyprland.dispatch("exit")
|
Hyprland.dispatch("exit");
|
||||||
} else {
|
} else {
|
||||||
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionLogout])
|
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionLogout]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function suspend() {
|
function suspend() {
|
||||||
if (SettingsData.customPowerActionSuspend.length === 0) {
|
if (SettingsData.customPowerActionSuspend.length === 0) {
|
||||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "suspend"])
|
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "suspend"]);
|
||||||
} else {
|
} else {
|
||||||
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionSuspend])
|
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionSuspend]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hibernate() {
|
function hibernate() {
|
||||||
if (SettingsData.customPowerActionHibernate.length === 0) {
|
if (SettingsData.customPowerActionHibernate.length === 0) {
|
||||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "hibernate"])
|
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "hibernate"]);
|
||||||
} else {
|
} else {
|
||||||
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionHibernate])
|
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionHibernate]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function suspendThenHibernate() {
|
function suspendThenHibernate() {
|
||||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "suspend-then-hibernate"])
|
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "suspend-then-hibernate"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function suspendWithBehavior(behavior) {
|
function suspendWithBehavior(behavior) {
|
||||||
if (behavior === SettingsData.SuspendBehavior.Hibernate) {
|
if (behavior === SettingsData.SuspendBehavior.Hibernate) {
|
||||||
hibernate()
|
hibernate();
|
||||||
} else if (behavior === SettingsData.SuspendBehavior.SuspendThenHibernate) {
|
} else if (behavior === SettingsData.SuspendBehavior.SuspendThenHibernate) {
|
||||||
suspendThenHibernate()
|
suspendThenHibernate();
|
||||||
} else {
|
} else {
|
||||||
suspend()
|
suspend();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reboot() {
|
function reboot() {
|
||||||
if (SettingsData.customPowerActionReboot.length === 0) {
|
if (SettingsData.customPowerActionReboot.length === 0) {
|
||||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "reboot"])
|
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "reboot"]);
|
||||||
} else {
|
} else {
|
||||||
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionReboot])
|
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionReboot]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function poweroff() {
|
function poweroff() {
|
||||||
if (SettingsData.customPowerActionPowerOff.length === 0) {
|
if (SettingsData.customPowerActionPowerOff.length === 0) {
|
||||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "poweroff"])
|
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "poweroff"]);
|
||||||
} else {
|
} else {
|
||||||
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionPowerOff])
|
Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionPowerOff]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,42 +291,42 @@ Singleton {
|
|||||||
|
|
||||||
function enableIdleInhibit() {
|
function enableIdleInhibit() {
|
||||||
if (idleInhibited) {
|
if (idleInhibited) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
console.log("SessionService: Enabling idle inhibit (native:", nativeInhibitorAvailable, ")")
|
console.log("SessionService: Enabling idle inhibit (native:", nativeInhibitorAvailable, ")");
|
||||||
idleInhibited = true
|
idleInhibited = true;
|
||||||
inhibitorChanged()
|
inhibitorChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableIdleInhibit() {
|
function disableIdleInhibit() {
|
||||||
if (!idleInhibited) {
|
if (!idleInhibited) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
console.log("SessionService: Disabling idle inhibit (native:", nativeInhibitorAvailable, ")")
|
console.log("SessionService: Disabling idle inhibit (native:", nativeInhibitorAvailable, ")");
|
||||||
idleInhibited = false
|
idleInhibited = false;
|
||||||
inhibitorChanged()
|
inhibitorChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleIdleInhibit() {
|
function toggleIdleInhibit() {
|
||||||
if (idleInhibited) {
|
if (idleInhibited) {
|
||||||
disableIdleInhibit()
|
disableIdleInhibit();
|
||||||
} else {
|
} else {
|
||||||
enableIdleInhibit()
|
enableIdleInhibit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setInhibitReason(reason) {
|
function setInhibitReason(reason) {
|
||||||
inhibitReason = reason
|
inhibitReason = reason;
|
||||||
|
|
||||||
if (idleInhibited && !nativeInhibitorAvailable) {
|
if (idleInhibited && !nativeInhibitorAvailable) {
|
||||||
const wasActive = idleInhibited
|
const wasActive = idleInhibited;
|
||||||
idleInhibited = false
|
idleInhibited = false;
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (wasActive) {
|
if (wasActive) {
|
||||||
idleInhibited = true
|
idleInhibited = true;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,24 +335,24 @@ Singleton {
|
|||||||
|
|
||||||
command: {
|
command: {
|
||||||
if (!idleInhibited || nativeInhibitorAvailable) {
|
if (!idleInhibited || nativeInhibitorAvailable) {
|
||||||
return ["true"]
|
return ["true"];
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("SessionService: Starting systemd/elogind inhibit process")
|
console.log("SessionService: Starting systemd/elogind inhibit process");
|
||||||
return [isElogind ? "elogind-inhibit" : "systemd-inhibit", "--what=idle", "--who=quickshell", `--why=${inhibitReason}`, "--mode=block", "sleep", "infinity"]
|
return [isElogind ? "elogind-inhibit" : "systemd-inhibit", "--what=idle", "--who=quickshell", `--why=${inhibitReason}`, "--mode=block", "sleep", "infinity"];
|
||||||
}
|
}
|
||||||
|
|
||||||
running: idleInhibited && !nativeInhibitorAvailable
|
running: idleInhibited && !nativeInhibitorAvailable
|
||||||
|
|
||||||
onRunningChanged: {
|
onRunningChanged: {
|
||||||
console.log("SessionService: Inhibit process running:", running, "(native:", nativeInhibitorAvailable, ")")
|
console.log("SessionService: Inhibit process running:", running, "(native:", nativeInhibitorAvailable, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
if (idleInhibited && exitCode !== 0 && !nativeInhibitorAvailable) {
|
if (idleInhibited && exitCode !== 0 && !nativeInhibitorAvailable) {
|
||||||
console.warn("SessionService: Inhibitor process crashed with exit code:", exitCode)
|
console.warn("SessionService: Inhibitor process crashed with exit code:", exitCode);
|
||||||
idleInhibited = false
|
idleInhibited = false;
|
||||||
ToastService.showWarning("Idle inhibitor failed")
|
ToastService.showWarning("Idle inhibitor failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,12 +362,12 @@ Singleton {
|
|||||||
|
|
||||||
function onConnectionStateChanged() {
|
function onConnectionStateChanged() {
|
||||||
if (DMSService.isConnected) {
|
if (DMSService.isConnected) {
|
||||||
checkDMSCapabilities()
|
checkDMSCapabilities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCapabilitiesReceived() {
|
function onCapabilitiesReceived() {
|
||||||
syncSleepInhibitor()
|
syncSleepInhibitor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +376,7 @@ Singleton {
|
|||||||
enabled: DMSService.isConnected
|
enabled: DMSService.isConnected
|
||||||
|
|
||||||
function onCapabilitiesChanged() {
|
function onCapabilitiesChanged() {
|
||||||
checkDMSCapabilities()
|
checkDMSCapabilities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,22 +387,22 @@ Singleton {
|
|||||||
if (SettingsData.loginctlLockIntegration) {
|
if (SettingsData.loginctlLockIntegration) {
|
||||||
if (socketPath && socketPath.length > 0 && loginctlAvailable) {
|
if (socketPath && socketPath.length > 0 && loginctlAvailable) {
|
||||||
if (!stateInitialized) {
|
if (!stateInitialized) {
|
||||||
stateInitialized = true
|
stateInitialized = true;
|
||||||
getLoginctlState()
|
getLoginctlState();
|
||||||
syncLockBeforeSuspend()
|
syncLockBeforeSuspend();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stateInitialized = false
|
stateInitialized = false;
|
||||||
}
|
}
|
||||||
syncSleepInhibitor()
|
syncSleepInhibitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLockBeforeSuspendChanged() {
|
function onLockBeforeSuspendChanged() {
|
||||||
if (SettingsData.loginctlLockIntegration) {
|
if (SettingsData.loginctlLockIntegration) {
|
||||||
syncLockBeforeSuspend()
|
syncLockBeforeSuspend();
|
||||||
}
|
}
|
||||||
syncSleepInhibitor()
|
syncSleepInhibitor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,109 +411,114 @@ Singleton {
|
|||||||
enabled: SettingsData.loginctlLockIntegration
|
enabled: SettingsData.loginctlLockIntegration
|
||||||
|
|
||||||
function onLoginctlStateUpdate(data) {
|
function onLoginctlStateUpdate(data) {
|
||||||
updateLoginctlState(data)
|
updateLoginctlState(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLoginctlEvent(event) {
|
function onLoginctlEvent(event) {
|
||||||
handleLoginctlEvent(event)
|
handleLoginctlEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDMSCapabilities() {
|
function checkDMSCapabilities() {
|
||||||
if (!DMSService.isConnected) {
|
if (!DMSService.isConnected) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DMSService.capabilities.length === 0) {
|
if (DMSService.capabilities.length === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DMSService.capabilities.includes("loginctl")) {
|
if (DMSService.capabilities.includes("loginctl")) {
|
||||||
loginctlAvailable = true
|
loginctlAvailable = true;
|
||||||
if (SettingsData.loginctlLockIntegration && !stateInitialized) {
|
if (SettingsData.loginctlLockIntegration && !stateInitialized) {
|
||||||
stateInitialized = true
|
stateInitialized = true;
|
||||||
getLoginctlState()
|
getLoginctlState();
|
||||||
syncLockBeforeSuspend()
|
syncLockBeforeSuspend();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loginctlAvailable = false
|
loginctlAvailable = false;
|
||||||
console.log("SessionService: loginctl capability not available in DMS")
|
console.log("SessionService: loginctl capability not available in DMS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLoginctlState() {
|
function getLoginctlState() {
|
||||||
if (!loginctlAvailable) return
|
if (!loginctlAvailable)
|
||||||
|
return;
|
||||||
DMSService.sendRequest("loginctl.getState", null, response => {
|
DMSService.sendRequest("loginctl.getState", null, response => {
|
||||||
if (response.result) {
|
if (response.result) {
|
||||||
updateLoginctlState(response.result)
|
updateLoginctlState(response.result);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncLockBeforeSuspend() {
|
function syncLockBeforeSuspend() {
|
||||||
if (!loginctlAvailable) return
|
if (!loginctlAvailable)
|
||||||
|
return;
|
||||||
DMSService.sendRequest("loginctl.setLockBeforeSuspend", {
|
DMSService.sendRequest("loginctl.setLockBeforeSuspend", {
|
||||||
enabled: SettingsData.lockBeforeSuspend
|
enabled: SettingsData.lockBeforeSuspend
|
||||||
}, response => {
|
}, response => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.warn("SessionService: Failed to sync lock before suspend:", response.error)
|
console.warn("SessionService: Failed to sync lock before suspend:", response.error);
|
||||||
} else {
|
} else {
|
||||||
console.log("SessionService: Synced lock before suspend:", SettingsData.lockBeforeSuspend)
|
console.log("SessionService: Synced lock before suspend:", SettingsData.lockBeforeSuspend);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncSleepInhibitor() {
|
function syncSleepInhibitor() {
|
||||||
if (!loginctlAvailable) return
|
if (!loginctlAvailable)
|
||||||
|
return;
|
||||||
if (!DMSService.apiVersion || DMSService.apiVersion < 4) return
|
if (!DMSService.apiVersion || DMSService.apiVersion < 4)
|
||||||
|
return;
|
||||||
DMSService.sendRequest("loginctl.setSleepInhibitorEnabled", {
|
DMSService.sendRequest("loginctl.setSleepInhibitorEnabled", {
|
||||||
enabled: SettingsData.loginctlLockIntegration && SettingsData.lockBeforeSuspend
|
enabled: SettingsData.loginctlLockIntegration && SettingsData.lockBeforeSuspend
|
||||||
}, response => {
|
}, response => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.warn("SessionService: Failed to sync sleep inhibitor:", response.error)
|
console.warn("SessionService: Failed to sync sleep inhibitor:", response.error);
|
||||||
} else {
|
} else {
|
||||||
console.log("SessionService: Synced sleep inhibitor:", SettingsData.loginctlLockIntegration)
|
console.log("SessionService: Synced sleep inhibitor:", SettingsData.loginctlLockIntegration);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLoginctlState(state) {
|
function updateLoginctlState(state) {
|
||||||
const wasLocked = locked
|
const wasLocked = locked;
|
||||||
|
const wasSleeping = preparingForSleep;
|
||||||
|
|
||||||
sessionId = state.sessionId || ""
|
sessionId = state.sessionId || "";
|
||||||
sessionPath = state.sessionPath || ""
|
sessionPath = state.sessionPath || "";
|
||||||
locked = state.locked || false
|
locked = state.locked || false;
|
||||||
active = state.active || false
|
active = state.active || false;
|
||||||
idleHint = state.idleHint || false
|
idleHint = state.idleHint || false;
|
||||||
lockedHint = state.lockedHint || false
|
lockedHint = state.lockedHint || false;
|
||||||
sessionType = state.sessionType || ""
|
preparingForSleep = state.preparingForSleep || false;
|
||||||
userName = state.userName || ""
|
sessionType = state.sessionType || "";
|
||||||
seat = state.seat || ""
|
userName = state.userName || "";
|
||||||
display = state.display || ""
|
seat = state.seat || "";
|
||||||
|
display = state.display || "";
|
||||||
|
|
||||||
if (locked && !wasLocked) {
|
if (locked && !wasLocked) {
|
||||||
sessionLocked()
|
sessionLocked();
|
||||||
} else if (!locked && wasLocked) {
|
} else if (!locked && wasLocked) {
|
||||||
sessionUnlocked()
|
sessionUnlocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
loginctlStateChanged()
|
if (wasSleeping && !preparingForSleep) {
|
||||||
|
sessionResumed();
|
||||||
|
}
|
||||||
|
|
||||||
|
loginctlStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLoginctlEvent(event) {
|
function handleLoginctlEvent(event) {
|
||||||
if (event.event === "Lock") {
|
if (event.event === "Lock") {
|
||||||
locked = true
|
locked = true;
|
||||||
lockedHint = true
|
lockedHint = true;
|
||||||
sessionLocked()
|
sessionLocked();
|
||||||
} else if (event.event === "Unlock") {
|
} else if (event.event === "Unlock") {
|
||||||
locked = false
|
locked = false;
|
||||||
lockedHint = false
|
lockedHint = false;
|
||||||
sessionUnlocked()
|
sessionUnlocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,39 +27,41 @@ PanelWindow {
|
|||||||
signal osdHidden
|
signal osdHidden
|
||||||
|
|
||||||
function show() {
|
function show() {
|
||||||
OSDManager.showOSD(root)
|
if (SessionData.suppressOSD)
|
||||||
closeTimer.stop()
|
return;
|
||||||
shouldBeVisible = true
|
OSDManager.showOSD(root);
|
||||||
visible = true
|
closeTimer.stop();
|
||||||
hideTimer.restart()
|
shouldBeVisible = true;
|
||||||
osdShown()
|
visible = true;
|
||||||
|
hideTimer.restart();
|
||||||
|
osdShown();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
shouldBeVisible = false
|
shouldBeVisible = false;
|
||||||
closeTimer.restart()
|
closeTimer.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetHideTimer() {
|
function resetHideTimer() {
|
||||||
if (shouldBeVisible) {
|
if (shouldBeVisible) {
|
||||||
hideTimer.restart()
|
hideTimer.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateHoverState() {
|
function updateHoverState() {
|
||||||
let isHovered = (enableMouseInteraction && mouseArea.containsMouse) || osdContainer.childHovered
|
let isHovered = (enableMouseInteraction && mouseArea.containsMouse) || osdContainer.childHovered;
|
||||||
if (enableMouseInteraction) {
|
if (enableMouseInteraction) {
|
||||||
if (isHovered) {
|
if (isHovered) {
|
||||||
hideTimer.stop()
|
hideTimer.stop();
|
||||||
} else if (shouldBeVisible) {
|
} else if (shouldBeVisible) {
|
||||||
hideTimer.restart()
|
hideTimer.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setChildHovered(hovered) {
|
function setChildHovered(hovered) {
|
||||||
osdContainer.childHovered = hovered
|
osdContainer.childHovered = hovered;
|
||||||
updateHoverState()
|
updateHoverState();
|
||||||
}
|
}
|
||||||
|
|
||||||
screen: modelData
|
screen: modelData
|
||||||
@@ -78,88 +80,92 @@ PanelWindow {
|
|||||||
readonly property bool isVerticalLayout: SettingsData.osdPosition === SettingsData.Position.LeftCenter || SettingsData.osdPosition === SettingsData.Position.RightCenter
|
readonly property bool isVerticalLayout: SettingsData.osdPosition === SettingsData.Position.LeftCenter || SettingsData.osdPosition === SettingsData.Position.RightCenter
|
||||||
|
|
||||||
readonly property real barThickness: {
|
readonly property real barThickness: {
|
||||||
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default")
|
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default");
|
||||||
if (!defaultBar || !(defaultBar.visible ?? true)) return 0
|
if (!defaultBar || !(defaultBar.visible ?? true))
|
||||||
const innerPadding = defaultBar.innerPadding ?? 4
|
return 0;
|
||||||
const widgetThickness = Math.max(20, 26 + innerPadding * 0.6)
|
const innerPadding = defaultBar.innerPadding ?? 4;
|
||||||
return Math.max(widgetThickness + innerPadding + 4, Theme.barHeight - 4 - (8 - innerPadding))
|
const widgetThickness = Math.max(20, 26 + innerPadding * 0.6);
|
||||||
|
return Math.max(widgetThickness + innerPadding + 4, Theme.barHeight - 4 - (8 - innerPadding));
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real barOffset: {
|
readonly property real barOffset: {
|
||||||
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default")
|
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default");
|
||||||
if (!defaultBar || !(defaultBar.visible ?? true)) return 0
|
if (!defaultBar || !(defaultBar.visible ?? true))
|
||||||
const spacing = defaultBar.spacing ?? 4
|
return 0;
|
||||||
const bottomGap = defaultBar.bottomGap ?? 0
|
const spacing = defaultBar.spacing ?? 4;
|
||||||
return barThickness + spacing + bottomGap
|
const bottomGap = defaultBar.bottomGap ?? 0;
|
||||||
|
return barThickness + spacing + bottomGap;
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real dockThickness: {
|
readonly property real dockThickness: {
|
||||||
if (!SettingsData.showDock) return 0
|
if (!SettingsData.showDock)
|
||||||
return SettingsData.dockIconSize + SettingsData.dockSpacing * 2 + 10
|
return 0;
|
||||||
|
return SettingsData.dockIconSize + SettingsData.dockSpacing * 2 + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real dockOffset: {
|
readonly property real dockOffset: {
|
||||||
if (!SettingsData.showDock || SettingsData.dockAutoHide) return 0
|
if (!SettingsData.showDock || SettingsData.dockAutoHide)
|
||||||
return dockThickness + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin
|
return 0;
|
||||||
|
return dockThickness + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real alignedX: {
|
readonly property real alignedX: {
|
||||||
const margin = Theme.spacingM
|
const margin = Theme.spacingM;
|
||||||
const centerX = (screenWidth - alignedWidth) / 2
|
const centerX = (screenWidth - alignedWidth) / 2;
|
||||||
|
|
||||||
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default")
|
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default");
|
||||||
const barPos = defaultBar?.position ?? SettingsData.Position.Top
|
const barPos = defaultBar?.position ?? SettingsData.Position.Top;
|
||||||
|
|
||||||
switch (SettingsData.osdPosition) {
|
switch (SettingsData.osdPosition) {
|
||||||
case SettingsData.Position.Left:
|
case SettingsData.Position.Left:
|
||||||
case SettingsData.Position.Bottom:
|
case SettingsData.Position.Bottom:
|
||||||
const leftBarOffset = barPos === SettingsData.Position.Left ? barOffset : 0
|
const leftBarOffset = barPos === SettingsData.Position.Left ? barOffset : 0;
|
||||||
const leftDockOffset = SettingsData.dockPosition === SettingsData.Position.Left ? dockOffset : 0
|
const leftDockOffset = SettingsData.dockPosition === SettingsData.Position.Left ? dockOffset : 0;
|
||||||
return Theme.snap(margin + Math.max(leftBarOffset, leftDockOffset), dpr)
|
return Theme.snap(margin + Math.max(leftBarOffset, leftDockOffset), dpr);
|
||||||
case SettingsData.Position.Top:
|
case SettingsData.Position.Top:
|
||||||
case SettingsData.Position.Right:
|
case SettingsData.Position.Right:
|
||||||
const rightBarOffset = barPos === SettingsData.Position.Right ? barOffset : 0
|
const rightBarOffset = barPos === SettingsData.Position.Right ? barOffset : 0;
|
||||||
const rightDockOffset = SettingsData.dockPosition === SettingsData.Position.Right ? dockOffset : 0
|
const rightDockOffset = SettingsData.dockPosition === SettingsData.Position.Right ? dockOffset : 0;
|
||||||
return Theme.snap(screenWidth - alignedWidth - margin - Math.max(rightBarOffset, rightDockOffset), dpr)
|
return Theme.snap(screenWidth - alignedWidth - margin - Math.max(rightBarOffset, rightDockOffset), dpr);
|
||||||
case SettingsData.Position.LeftCenter:
|
case SettingsData.Position.LeftCenter:
|
||||||
const leftCenterBarOffset = barPos === SettingsData.Position.Left ? barOffset : 0
|
const leftCenterBarOffset = barPos === SettingsData.Position.Left ? barOffset : 0;
|
||||||
const leftCenterDockOffset = SettingsData.dockPosition === SettingsData.Position.Left ? dockOffset : 0
|
const leftCenterDockOffset = SettingsData.dockPosition === SettingsData.Position.Left ? dockOffset : 0;
|
||||||
return Theme.snap(margin + Math.max(leftCenterBarOffset, leftCenterDockOffset), dpr)
|
return Theme.snap(margin + Math.max(leftCenterBarOffset, leftCenterDockOffset), dpr);
|
||||||
case SettingsData.Position.RightCenter:
|
case SettingsData.Position.RightCenter:
|
||||||
const rightCenterBarOffset = barPos === SettingsData.Position.Right ? barOffset : 0
|
const rightCenterBarOffset = barPos === SettingsData.Position.Right ? barOffset : 0;
|
||||||
const rightCenterDockOffset = SettingsData.dockPosition === SettingsData.Position.Right ? dockOffset : 0
|
const rightCenterDockOffset = SettingsData.dockPosition === SettingsData.Position.Right ? dockOffset : 0;
|
||||||
return Theme.snap(screenWidth - alignedWidth - margin - Math.max(rightCenterBarOffset, rightCenterDockOffset), dpr)
|
return Theme.snap(screenWidth - alignedWidth - margin - Math.max(rightCenterBarOffset, rightCenterDockOffset), dpr);
|
||||||
case SettingsData.Position.TopCenter:
|
case SettingsData.Position.TopCenter:
|
||||||
case SettingsData.Position.BottomCenter:
|
case SettingsData.Position.BottomCenter:
|
||||||
default:
|
default:
|
||||||
return Theme.snap(centerX, dpr)
|
return Theme.snap(centerX, dpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real alignedY: {
|
readonly property real alignedY: {
|
||||||
const margin = Theme.spacingM
|
const margin = Theme.spacingM;
|
||||||
const centerY = (screenHeight - alignedHeight) / 2
|
const centerY = (screenHeight - alignedHeight) / 2;
|
||||||
|
|
||||||
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default")
|
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default");
|
||||||
const barPos = defaultBar?.position ?? SettingsData.Position.Top
|
const barPos = defaultBar?.position ?? SettingsData.Position.Top;
|
||||||
|
|
||||||
switch (SettingsData.osdPosition) {
|
switch (SettingsData.osdPosition) {
|
||||||
case SettingsData.Position.Top:
|
case SettingsData.Position.Top:
|
||||||
case SettingsData.Position.Left:
|
case SettingsData.Position.Left:
|
||||||
case SettingsData.Position.TopCenter:
|
case SettingsData.Position.TopCenter:
|
||||||
const topBarOffset = barPos === SettingsData.Position.Top ? barOffset : 0
|
const topBarOffset = barPos === SettingsData.Position.Top ? barOffset : 0;
|
||||||
const topDockOffset = SettingsData.dockPosition === SettingsData.Position.Top ? dockOffset : 0
|
const topDockOffset = SettingsData.dockPosition === SettingsData.Position.Top ? dockOffset : 0;
|
||||||
return Theme.snap(margin + Math.max(topBarOffset, topDockOffset), dpr)
|
return Theme.snap(margin + Math.max(topBarOffset, topDockOffset), dpr);
|
||||||
case SettingsData.Position.Right:
|
case SettingsData.Position.Right:
|
||||||
case SettingsData.Position.Bottom:
|
case SettingsData.Position.Bottom:
|
||||||
case SettingsData.Position.BottomCenter:
|
case SettingsData.Position.BottomCenter:
|
||||||
const bottomBarOffset = barPos === SettingsData.Position.Bottom ? barOffset : 0
|
const bottomBarOffset = barPos === SettingsData.Position.Bottom ? barOffset : 0;
|
||||||
const bottomDockOffset = SettingsData.dockPosition === SettingsData.Position.Bottom ? dockOffset : 0
|
const bottomDockOffset = SettingsData.dockPosition === SettingsData.Position.Bottom ? dockOffset : 0;
|
||||||
return Theme.snap(screenHeight - alignedHeight - margin - Math.max(bottomBarOffset, bottomDockOffset), dpr)
|
return Theme.snap(screenHeight - alignedHeight - margin - Math.max(bottomBarOffset, bottomDockOffset), dpr);
|
||||||
case SettingsData.Position.LeftCenter:
|
case SettingsData.Position.LeftCenter:
|
||||||
case SettingsData.Position.RightCenter:
|
case SettingsData.Position.RightCenter:
|
||||||
default:
|
default:
|
||||||
return Theme.snap(centerY, dpr)
|
return Theme.snap(centerY, dpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,9 +183,9 @@ PanelWindow {
|
|||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (!enableMouseInteraction || !mouseArea.containsMouse) {
|
if (!enableMouseInteraction || !mouseArea.containsMouse) {
|
||||||
hide()
|
hide();
|
||||||
} else {
|
} else {
|
||||||
hideTimer.restart()
|
hideTimer.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,8 +195,8 @@ PanelWindow {
|
|||||||
interval: animationDuration + 50
|
interval: animationDuration + 50
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (!shouldBeVisible) {
|
if (!shouldBeVisible) {
|
||||||
visible = false
|
visible = false;
|
||||||
osdHidden()
|
osdHidden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,8 +245,8 @@ PanelWindow {
|
|||||||
shadowBlur: Math.max(0, Math.min(1, osdContainer.shadowBlurPx / bgShadowLayer.blurMax))
|
shadowBlur: Math.max(0, Math.min(1, osdContainer.shadowBlurPx / bgShadowLayer.blurMax))
|
||||||
shadowScale: 1 + (2 * osdContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
|
shadowScale: 1 + (2 * osdContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
|
||||||
shadowColor: {
|
shadowColor: {
|
||||||
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
return Theme.withAlpha(baseColor, osdContainer.effectiveShadowAlpha)
|
return Theme.withAlpha(baseColor, osdContainer.effectiveShadowAlpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user