mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-12 16:38:28 -04:00
settings: diff-only configs, machine-state split, backup CLI
- settings.json/session.json now store only values that differ from spec defaults - Machine-specific state moves out of settings.json into session.json - Add dms backup create/restore: tar.gz of ~/.config/DankMaterialShell fixes #3027
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/backup"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var backupOutputPath string
|
||||||
|
|
||||||
|
var backupCmd = &cobra.Command{
|
||||||
|
Use: "backup",
|
||||||
|
Short: "Backup and restore DMS configuration",
|
||||||
|
}
|
||||||
|
|
||||||
|
var backupCreateCmd = &cobra.Command{
|
||||||
|
Use: "create",
|
||||||
|
Short: "Create a tar.gz backup of ~/.config/DankMaterialShell (settings, plugins, themes)",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
Run: runBackupCreate,
|
||||||
|
}
|
||||||
|
|
||||||
|
var backupRestoreCmd = &cobra.Command{
|
||||||
|
Use: "restore <archive>",
|
||||||
|
Short: "Restore a DMS configuration backup; the current configuration is moved aside first",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: runBackupRestore,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
backupCreateCmd.Flags().StringVarP(&backupOutputPath, "output", "o", "", "Output archive path (default dms-backup-<timestamp>.tar.gz)")
|
||||||
|
backupCmd.AddCommand(backupCreateCmd, backupRestoreCmd)
|
||||||
|
rootCmd.AddCommand(backupCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runBackupCreate(cmd *cobra.Command, args []string) {
|
||||||
|
output := backupOutputPath
|
||||||
|
if output == "" {
|
||||||
|
output = backup.DefaultArchiveName()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := backup.Create(output); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Println(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runBackupRestore(cmd *cobra.Command, args []string) {
|
||||||
|
previous, err := backup.Restore(args[0])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if previous != "" {
|
||||||
|
fmt.Printf("Previous configuration moved to %s\n", previous)
|
||||||
|
}
|
||||||
|
fmt.Println("Restore complete. Restart the shell to apply.")
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
package backup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dirName = "DankMaterialShell"
|
||||||
|
|
||||||
|
func ConfigDir() (string, error) {
|
||||||
|
configDir, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Join(configDir, dirName), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultArchiveName() string {
|
||||||
|
return fmt.Sprintf("dms-backup-%s.tar.gz", time.Now().Format("20060102-150405"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Create(outputPath string) error {
|
||||||
|
srcDir, err := ConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(srcDir); err != nil {
|
||||||
|
return fmt.Errorf("no DMS configuration found at %s: %w", srcDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := os.Create(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
gz := gzip.NewWriter(out)
|
||||||
|
defer gz.Close()
|
||||||
|
tw := tar.NewWriter(gz)
|
||||||
|
defer tw.Close()
|
||||||
|
|
||||||
|
return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rel, err := filepath.Rel(srcDir, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rel == "." {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var link string
|
||||||
|
if info.Mode()&os.ModeSymlink != 0 {
|
||||||
|
if link, err = os.Readlink(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header, err := tar.FileInfoHeader(info, link)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
header.Name = filepath.ToSlash(filepath.Join(dirName, rel))
|
||||||
|
|
||||||
|
if err := tw.WriteHeader(header); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !info.Mode().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
_, err = io.Copy(tw, f)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Restore(archivePath string) (string, error) {
|
||||||
|
dstDir, err := ConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateArchive(archivePath); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
previous := ""
|
||||||
|
if _, err := os.Stat(dstDir); err == nil {
|
||||||
|
previous = dstDir + ".pre-restore-" + time.Now().Format("20060102-150405")
|
||||||
|
if err := os.Rename(dstDir, previous); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to move existing configuration aside: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := extract(archivePath, filepath.Dir(dstDir)); err != nil {
|
||||||
|
if previous != "" {
|
||||||
|
os.RemoveAll(dstDir)
|
||||||
|
os.Rename(previous, dstDir)
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return previous, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateArchive(archivePath string) error {
|
||||||
|
hasSettings := false
|
||||||
|
err := walkArchive(archivePath, func(header *tar.Header, _ *tar.Reader) error {
|
||||||
|
name := filepath.ToSlash(filepath.Clean(header.Name))
|
||||||
|
if strings.HasPrefix(name, "..") || filepath.IsAbs(header.Name) {
|
||||||
|
return fmt.Errorf("unsafe path in archive: %s", header.Name)
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(name, dirName+"/") && name != dirName {
|
||||||
|
return fmt.Errorf("not a DMS backup: unexpected entry %s", header.Name)
|
||||||
|
}
|
||||||
|
if name == dirName+"/settings.json" {
|
||||||
|
hasSettings = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !hasSettings {
|
||||||
|
return fmt.Errorf("not a DMS backup: settings.json missing from archive")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extract(archivePath, destParent string) error {
|
||||||
|
return walkArchive(archivePath, func(header *tar.Header, tr *tar.Reader) error {
|
||||||
|
target := filepath.Join(destParent, filepath.Clean(header.Name))
|
||||||
|
|
||||||
|
switch header.Typeflag {
|
||||||
|
case tar.TypeDir:
|
||||||
|
return os.MkdirAll(target, os.FileMode(header.Mode))
|
||||||
|
case tar.TypeSymlink:
|
||||||
|
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Symlink(header.Linkname, target)
|
||||||
|
case tar.TypeReg:
|
||||||
|
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(header.Mode))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
_, err = io.Copy(f, tr)
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkArchive(archivePath string, visit func(*tar.Header, *tar.Reader) error) error {
|
||||||
|
f, err := os.Open(archivePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
gz, err := gzip.NewReader(f)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("not a gzip archive: %w", err)
|
||||||
|
}
|
||||||
|
defer gz.Close()
|
||||||
|
|
||||||
|
tr := tar.NewReader(gz)
|
||||||
|
for {
|
||||||
|
header, err := tr.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := visit(header, tr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
readonly property var log: Log.scoped("CacheData")
|
readonly property var log: Log.scoped("CacheData")
|
||||||
|
|
||||||
readonly property int cacheConfigVersion: 2
|
readonly property int cacheConfigVersion: 3
|
||||||
|
|
||||||
readonly property string _stateUrl: StandardPaths.writableLocation(StandardPaths.GenericCacheLocation)
|
readonly property string _stateUrl: StandardPaths.writableLocation(StandardPaths.GenericCacheLocation)
|
||||||
readonly property string _stateDir: Paths.strip(_stateUrl)
|
readonly property string _stateDir: Paths.strip(_stateUrl)
|
||||||
@@ -21,11 +21,15 @@ Singleton {
|
|||||||
property int _loadedCacheVersion: 0
|
property int _loadedCacheVersion: 0
|
||||||
|
|
||||||
readonly property var _pinKeys: ["brightnessDevicePins", "wifiNetworkPins", "bluetoothDevicePins", "audioInputDevicePins", "audioOutputDevicePins"]
|
readonly property var _pinKeys: ["brightnessDevicePins", "wifiNetworkPins", "bluetoothDevicePins", "audioInputDevicePins", "audioOutputDevicePins"]
|
||||||
readonly property var _dataKeys: ["wallpaperLastPath", "profileLastPath", "fileBrowserSettings"].concat(_pinKeys)
|
readonly property var _historyKeys: ["browserUsageHistory", "filePickerUsageHistory"]
|
||||||
|
readonly property var _dataKeys: ["wallpaperLastPath", "profileLastPath", "fileBrowserSettings"].concat(_pinKeys, _historyKeys)
|
||||||
|
|
||||||
property string wallpaperLastPath: ""
|
property string wallpaperLastPath: ""
|
||||||
property string profileLastPath: ""
|
property string profileLastPath: ""
|
||||||
|
|
||||||
|
property var browserUsageHistory: ({})
|
||||||
|
property var filePickerUsageHistory: ({})
|
||||||
|
|
||||||
property var brightnessDevicePins: ({})
|
property var brightnessDevicePins: ({})
|
||||||
property var wifiNetworkPins: ({})
|
property var wifiNetworkPins: ({})
|
||||||
property var bluetoothDevicePins: ({})
|
property var bluetoothDevicePins: ({})
|
||||||
@@ -131,6 +135,29 @@ Singleton {
|
|||||||
saveCache();
|
saveCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function migrateUsageHistories(histories) {
|
||||||
|
if (!histories)
|
||||||
|
return;
|
||||||
|
if (!_hasLoaded)
|
||||||
|
loadCache();
|
||||||
|
|
||||||
|
let migrated = false;
|
||||||
|
for (const key of _historyKeys) {
|
||||||
|
const legacy = histories[key];
|
||||||
|
if (!legacy || Object.keys(legacy).length === 0)
|
||||||
|
continue;
|
||||||
|
if (Object.keys(root[key] || {}).length > 0)
|
||||||
|
continue;
|
||||||
|
root[key] = legacy;
|
||||||
|
migrated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!migrated)
|
||||||
|
return;
|
||||||
|
log.info("Migrated usage histories from settings.json");
|
||||||
|
saveCache();
|
||||||
|
}
|
||||||
|
|
||||||
function parseCache(content) {
|
function parseCache(content) {
|
||||||
_loading = true;
|
_loading = true;
|
||||||
try {
|
try {
|
||||||
@@ -172,7 +199,7 @@ Singleton {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const key of _pinKeys) {
|
for (const key of _pinKeys.concat(_historyKeys)) {
|
||||||
root[key] = cache[key] !== undefined ? cache[key] : {};
|
root[key] = cache[key] !== undefined ? cache[key] : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +225,7 @@ Singleton {
|
|||||||
"fileBrowserSettings": fileBrowserSettings,
|
"fileBrowserSettings": fileBrowserSettings,
|
||||||
"configVersion": cacheConfigVersion
|
"configVersion": cacheConfigVersion
|
||||||
};
|
};
|
||||||
for (const key of _pinKeys) {
|
for (const key of _pinKeys.concat(_historyKeys)) {
|
||||||
data[key] = root[key];
|
data[key] = root[key];
|
||||||
}
|
}
|
||||||
cacheFile.setText(JSON.stringify(data, null, 2));
|
cacheFile.setText(JSON.stringify(data, null, 2));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
readonly property var log: Log.scoped("SessionData")
|
readonly property var log: Log.scoped("SessionData")
|
||||||
|
|
||||||
readonly property int sessionConfigVersion: 3
|
readonly property int sessionConfigVersion: 4
|
||||||
|
|
||||||
signal loaded
|
signal loaded
|
||||||
signal brightnessDisplayHintChanged(string deviceName)
|
signal brightnessDisplayHintChanged(string deviceName)
|
||||||
@@ -221,6 +221,17 @@ Singleton {
|
|||||||
|
|
||||||
property string notepadLastMode: ""
|
property string notepadLastMode: ""
|
||||||
|
|
||||||
|
property var niriOutputSettings: ({})
|
||||||
|
property var hyprlandOutputSettings: ({})
|
||||||
|
property var activeDisplayProfile: ({})
|
||||||
|
property var activeDisplayProfileModes: ({})
|
||||||
|
property var desktopWidgetGridSettings: ({})
|
||||||
|
property var desktopWidgetInstancePositions: ({})
|
||||||
|
property var builtInPluginState: ({})
|
||||||
|
property bool greeterSyncPending: false
|
||||||
|
property var greeterSyncBaseline: ({})
|
||||||
|
property string lastAppliedIconTheme: ""
|
||||||
|
|
||||||
property string launcherLastMode: "all"
|
property string launcherLastMode: "all"
|
||||||
property string launcherLastFileSearchType: "all"
|
property string launcherLastFileSearchType: "all"
|
||||||
property string launcherLastQuery: ""
|
property string launcherLastQuery: ""
|
||||||
@@ -393,6 +404,161 @@ Singleton {
|
|||||||
Spec.set(root, key, value, saveSettings, _hooks);
|
Spec.set(root, key, value, saveSettings, _hooks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function importFromSettings(payload) {
|
||||||
|
if (!payload)
|
||||||
|
return;
|
||||||
|
if (!_hasLoaded)
|
||||||
|
loadSettings();
|
||||||
|
if (_parseError)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let imported = false;
|
||||||
|
for (const key in payload) {
|
||||||
|
if (!(key in Spec.SPEC))
|
||||||
|
continue;
|
||||||
|
const current = root[key];
|
||||||
|
const isEmpty = current === Spec.SPEC[key].def || (typeof current === "object" && current !== null && Object.keys(current).length === 0);
|
||||||
|
if (!isEmpty)
|
||||||
|
continue;
|
||||||
|
root[key] = payload[key];
|
||||||
|
imported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imported) {
|
||||||
|
log.info("Imported machine-specific state from settings.json");
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNiriOutputSetting(outputId, key, defaultValue) {
|
||||||
|
if (!niriOutputSettings[outputId])
|
||||||
|
return defaultValue;
|
||||||
|
return niriOutputSettings[outputId][key] !== undefined ? niriOutputSettings[outputId][key] : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNiriOutputSetting(outputId, key, value) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
|
||||||
|
if (!updated[outputId])
|
||||||
|
updated[outputId] = {};
|
||||||
|
updated[outputId][key] = value;
|
||||||
|
niriOutputSettings = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNiriOutputSettings(outputId) {
|
||||||
|
const settings = niriOutputSettings[outputId];
|
||||||
|
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHyprlandOutputSetting(outputId, key, defaultValue) {
|
||||||
|
if (!hyprlandOutputSettings[outputId])
|
||||||
|
return defaultValue;
|
||||||
|
return hyprlandOutputSettings[outputId][key] !== undefined ? hyprlandOutputSettings[outputId][key] : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHyprlandOutputSetting(outputId, key, value) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(hyprlandOutputSettings));
|
||||||
|
if (!updated[outputId])
|
||||||
|
updated[outputId] = {};
|
||||||
|
updated[outputId][key] = value;
|
||||||
|
hyprlandOutputSettings = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeHyprlandOutputSetting(outputId, key) {
|
||||||
|
if (!hyprlandOutputSettings[outputId] || !(key in hyprlandOutputSettings[outputId]))
|
||||||
|
return;
|
||||||
|
const updated = JSON.parse(JSON.stringify(hyprlandOutputSettings));
|
||||||
|
delete updated[outputId][key];
|
||||||
|
hyprlandOutputSettings = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActiveDisplayProfile(compositor) {
|
||||||
|
return activeDisplayProfile[compositor] || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setActiveDisplayProfile(compositor, profileId) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(activeDisplayProfile));
|
||||||
|
updated[compositor] = profileId;
|
||||||
|
activeDisplayProfile = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setActiveDisplayProfileModes(compositor, modes) {
|
||||||
|
if (JSON.stringify(activeDisplayProfileModes[compositor] || {}) === JSON.stringify(modes || {}))
|
||||||
|
return;
|
||||||
|
const updated = JSON.parse(JSON.stringify(activeDisplayProfileModes));
|
||||||
|
updated[compositor] = modes;
|
||||||
|
activeDisplayProfileModes = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDesktopWidgetGridSetting(screenKey, property, defaultValue) {
|
||||||
|
const val = desktopWidgetGridSettings?.[screenKey]?.[property];
|
||||||
|
return val !== undefined ? val : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDesktopWidgetGridSetting(screenKey, property, value) {
|
||||||
|
const allSettings = JSON.parse(JSON.stringify(desktopWidgetGridSettings || {}));
|
||||||
|
if (!allSettings[screenKey])
|
||||||
|
allSettings[screenKey] = {};
|
||||||
|
allSettings[screenKey][property] = value;
|
||||||
|
desktopWidgetGridSettings = allSettings;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDesktopWidgetInstancePosition(instanceId, screenKey, positionUpdates) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(desktopWidgetInstancePositions));
|
||||||
|
if (!updated[instanceId])
|
||||||
|
updated[instanceId] = {};
|
||||||
|
updated[instanceId][screenKey] = Object.assign({}, updated[instanceId][screenKey] || {}, positionUpdates);
|
||||||
|
desktopWidgetInstancePositions = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncDesktopWidgetPositionToAllScreens(instanceId) {
|
||||||
|
const positions = desktopWidgetInstancePositions[instanceId] || {};
|
||||||
|
const screenKeys = Object.keys(positions).filter(k => k !== "_synced");
|
||||||
|
if (screenKeys.length === 0)
|
||||||
|
return;
|
||||||
|
const sourcePos = positions[screenKeys[0]];
|
||||||
|
if (!sourcePos)
|
||||||
|
return;
|
||||||
|
const screen = Array.from(Quickshell.screens.values()).find(s => SettingsData.getScreenDisplayName(s) === screenKeys[0]);
|
||||||
|
if (!screen)
|
||||||
|
return;
|
||||||
|
const synced = {};
|
||||||
|
if (sourcePos.x !== undefined)
|
||||||
|
synced.x = sourcePos.x / screen.width;
|
||||||
|
if (sourcePos.y !== undefined)
|
||||||
|
synced.y = sourcePos.y / screen.height;
|
||||||
|
if (sourcePos.width !== undefined)
|
||||||
|
synced.width = sourcePos.width;
|
||||||
|
if (sourcePos.height !== undefined)
|
||||||
|
synced.height = sourcePos.height;
|
||||||
|
const updated = JSON.parse(JSON.stringify(desktopWidgetInstancePositions));
|
||||||
|
updated[instanceId]["_synced"] = synced;
|
||||||
|
desktopWidgetInstancePositions = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeDesktopWidgetInstancePositions(instanceId) {
|
||||||
|
if (!(instanceId in desktopWidgetInstancePositions))
|
||||||
|
return;
|
||||||
|
const updated = JSON.parse(JSON.stringify(desktopWidgetInstancePositions));
|
||||||
|
delete updated[instanceId];
|
||||||
|
desktopWidgetInstancePositions = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBuiltInPluginState(pluginId, state) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(builtInPluginState));
|
||||||
|
updated[pluginId] = state;
|
||||||
|
builtInPluginState = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
function migrateFromUndefinedToV1(settings) {
|
function migrateFromUndefinedToV1(settings) {
|
||||||
if (typeof SettingsData !== "undefined") {
|
if (typeof SettingsData !== "undefined") {
|
||||||
if (settings.acMonitorTimeout !== undefined) {
|
if (settings.acMonitorTimeout !== undefined) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
readonly property var log: Log.scoped("SettingsData")
|
readonly property var log: Log.scoped("SettingsData")
|
||||||
|
|
||||||
readonly property int settingsConfigVersion: 13
|
readonly property int settingsConfigVersion: 15
|
||||||
|
|
||||||
enum Position {
|
enum Position {
|
||||||
Top,
|
Top,
|
||||||
@@ -102,6 +102,10 @@ Singleton {
|
|||||||
updated[pluginId] = {};
|
updated[pluginId] = {};
|
||||||
updated[pluginId][key] = value;
|
updated[pluginId][key] = value;
|
||||||
builtInPluginSettings = updated;
|
builtInPluginSettings = updated;
|
||||||
|
if (Store.SESSION_BACKED_PLUGIN_IDS.includes(pluginId)) {
|
||||||
|
SessionData.setBuiltInPluginState(pluginId, updated[pluginId]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,16 +540,12 @@ Singleton {
|
|||||||
property string greeterLockDateFormat: ""
|
property string greeterLockDateFormat: ""
|
||||||
property string greeterFontFamily: ""
|
property string greeterFontFamily: ""
|
||||||
property string greeterWallpaperFillMode: ""
|
property string greeterWallpaperFillMode: ""
|
||||||
property bool greeterSyncPending: false
|
|
||||||
property var greeterSyncBaseline: ({})
|
|
||||||
property int mediaSize: 1
|
property int mediaSize: 1
|
||||||
|
|
||||||
property string appLauncherViewMode: "list"
|
property string appLauncherViewMode: "list"
|
||||||
property string spotlightModalViewMode: "list"
|
property string spotlightModalViewMode: "list"
|
||||||
property string browserPickerViewMode: "grid"
|
property string browserPickerViewMode: "grid"
|
||||||
property var browserUsageHistory: ({})
|
|
||||||
property string appPickerViewMode: "grid"
|
property string appPickerViewMode: "grid"
|
||||||
property var filePickerUsageHistory: ({})
|
|
||||||
property bool sortAppsAlphabetically: false
|
property bool sortAppsAlphabetically: false
|
||||||
property int appLauncherGridColumns: 4
|
property int appLauncherGridColumns: 4
|
||||||
property bool spotlightCloseNiriOverview: true
|
property bool spotlightCloseNiriOverview: true
|
||||||
@@ -673,7 +673,6 @@ Singleton {
|
|||||||
property string iconThemeDark: "System Default"
|
property string iconThemeDark: "System Default"
|
||||||
property string iconThemeLight: "System Default"
|
property string iconThemeLight: "System Default"
|
||||||
property bool iconThemePerMode: false
|
property bool iconThemePerMode: false
|
||||||
property string lastAppliedIconTheme: ""
|
|
||||||
readonly property string iconTheme: resolveIconTheme()
|
readonly property string iconTheme: resolveIconTheme()
|
||||||
property var availableIconThemes: ["System Default"]
|
property var availableIconThemes: ["System Default"]
|
||||||
property string systemDefaultIconTheme: ""
|
property string systemDefaultIconTheme: ""
|
||||||
@@ -1006,11 +1005,7 @@ Singleton {
|
|||||||
property string displayNameMode: "system"
|
property string displayNameMode: "system"
|
||||||
property var screenPreferences: ({})
|
property var screenPreferences: ({})
|
||||||
property var showOnLastDisplay: ({})
|
property var showOnLastDisplay: ({})
|
||||||
property var niriOutputSettings: ({})
|
|
||||||
property var hyprlandOutputSettings: ({})
|
|
||||||
property var displayProfiles: ({})
|
property var displayProfiles: ({})
|
||||||
property var activeDisplayProfile: ({})
|
|
||||||
property var activeDisplayProfileModes: ({})
|
|
||||||
property var displayPreviousRefreshModes: ({})
|
property var displayPreviousRefreshModes: ({})
|
||||||
property bool displayProfileAutoSelect: false
|
property bool displayProfileAutoSelect: false
|
||||||
property bool displayShowDisconnected: false
|
property bool displayShowDisconnected: false
|
||||||
@@ -1117,24 +1112,9 @@ Singleton {
|
|||||||
property var systemMonitorDisplayPreferences: ["all"]
|
property var systemMonitorDisplayPreferences: ["all"]
|
||||||
property var systemMonitorVariants: []
|
property var systemMonitorVariants: []
|
||||||
property var desktopWidgetPositions: ({})
|
property var desktopWidgetPositions: ({})
|
||||||
property var desktopWidgetGridSettings: ({})
|
|
||||||
property var desktopWidgetInstances: []
|
property var desktopWidgetInstances: []
|
||||||
property var desktopWidgetGroups: []
|
property var desktopWidgetGroups: []
|
||||||
|
|
||||||
function getDesktopWidgetGridSetting(screenKey, property, defaultValue) {
|
|
||||||
const val = desktopWidgetGridSettings?.[screenKey]?.[property];
|
|
||||||
return val !== undefined ? val : defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDesktopWidgetGridSetting(screenKey, property, value) {
|
|
||||||
const allSettings = JSON.parse(JSON.stringify(desktopWidgetGridSettings || {}));
|
|
||||||
if (!allSettings[screenKey])
|
|
||||||
allSettings[screenKey] = {};
|
|
||||||
allSettings[screenKey][property] = value;
|
|
||||||
desktopWidgetGridSettings = allSettings;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDesktopWidgetPosition(pluginId, screenKey, property, defaultValue) {
|
function getDesktopWidgetPosition(pluginId, screenKey, property, defaultValue) {
|
||||||
const pos = desktopWidgetPositions?.[pluginId]?.[screenKey]?.[property];
|
const pos = desktopWidgetPositions?.[pluginId]?.[screenKey]?.[property];
|
||||||
return pos !== undefined ? pos : defaultValue;
|
return pos !== undefined ? pos : defaultValue;
|
||||||
@@ -1185,8 +1165,7 @@ Singleton {
|
|||||||
widgetType: widgetType,
|
widgetType: widgetType,
|
||||||
name: name || widgetType,
|
name: name || widgetType,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
config: config || {},
|
config: config || {}
|
||||||
positions: {}
|
|
||||||
};
|
};
|
||||||
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
|
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
|
||||||
instances.push(instance);
|
instances.push(instance);
|
||||||
@@ -1215,53 +1194,10 @@ Singleton {
|
|||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDesktopWidgetInstancePosition(instanceId, screenKey, positionUpdates) {
|
|
||||||
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
|
|
||||||
const idx = instances.findIndex(inst => inst.id === instanceId);
|
|
||||||
if (idx === -1)
|
|
||||||
return;
|
|
||||||
if (!instances[idx].positions)
|
|
||||||
instances[idx].positions = {};
|
|
||||||
instances[idx].positions[screenKey] = Object.assign({}, instances[idx].positions[screenKey] || {}, positionUpdates);
|
|
||||||
desktopWidgetInstances = instances;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeDesktopWidgetInstance(instanceId) {
|
function removeDesktopWidgetInstance(instanceId) {
|
||||||
const instances = (desktopWidgetInstances || []).filter(inst => inst.id !== instanceId);
|
const instances = (desktopWidgetInstances || []).filter(inst => inst.id !== instanceId);
|
||||||
desktopWidgetInstances = instances;
|
desktopWidgetInstances = instances;
|
||||||
saveSettings();
|
SessionData.removeDesktopWidgetInstancePositions(instanceId);
|
||||||
}
|
|
||||||
|
|
||||||
function syncDesktopWidgetPositionToAllScreens(instanceId) {
|
|
||||||
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
|
|
||||||
const idx = instances.findIndex(inst => inst.id === instanceId);
|
|
||||||
if (idx === -1)
|
|
||||||
return;
|
|
||||||
const positions = instances[idx].positions || {};
|
|
||||||
const screenKeys = Object.keys(positions).filter(k => k !== "_synced");
|
|
||||||
if (screenKeys.length === 0)
|
|
||||||
return;
|
|
||||||
const sourceKey = screenKeys[0];
|
|
||||||
const sourcePos = positions[sourceKey];
|
|
||||||
if (!sourcePos)
|
|
||||||
return;
|
|
||||||
const screen = Array.from(Quickshell.screens.values()).find(s => getScreenDisplayName(s) === sourceKey);
|
|
||||||
if (!screen)
|
|
||||||
return;
|
|
||||||
const screenW = screen.width;
|
|
||||||
const screenH = screen.height;
|
|
||||||
const synced = {};
|
|
||||||
if (sourcePos.x !== undefined)
|
|
||||||
synced.x = sourcePos.x / screenW;
|
|
||||||
if (sourcePos.y !== undefined)
|
|
||||||
synced.y = sourcePos.y / screenH;
|
|
||||||
if (sourcePos.width !== undefined)
|
|
||||||
synced.width = sourcePos.width;
|
|
||||||
if (sourcePos.height !== undefined)
|
|
||||||
synced.height = sourcePos.height;
|
|
||||||
instances[idx].positions["_synced"] = synced;
|
|
||||||
desktopWidgetInstances = instances;
|
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,8 +1211,7 @@ Singleton {
|
|||||||
widgetType: source.widgetType,
|
widgetType: source.widgetType,
|
||||||
name: source.name + " (Copy)",
|
name: source.name + " (Copy)",
|
||||||
enabled: source.enabled,
|
enabled: source.enabled,
|
||||||
config: JSON.parse(JSON.stringify(source.config || {})),
|
config: JSON.parse(JSON.stringify(source.config || {}))
|
||||||
positions: {}
|
|
||||||
};
|
};
|
||||||
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
|
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
|
||||||
instances.push(instance);
|
instances.push(instance);
|
||||||
@@ -1424,14 +1359,15 @@ Singleton {
|
|||||||
iconThemePerMode = false;
|
iconThemePerMode = false;
|
||||||
iconThemeDark = "System Default";
|
iconThemeDark = "System Default";
|
||||||
iconThemeLight = "System Default";
|
iconThemeLight = "System Default";
|
||||||
lastAppliedIconTheme = "";
|
SessionData.lastAppliedIconTheme = "";
|
||||||
|
SessionData.saveSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIconThemeDrift() {
|
function checkIconThemeDrift() {
|
||||||
if (resolveIconTheme() === "System Default")
|
if (resolveIconTheme() === "System Default")
|
||||||
return;
|
return;
|
||||||
if (!lastAppliedIconTheme)
|
if (!SessionData.lastAppliedIconTheme)
|
||||||
return;
|
return;
|
||||||
const script = `if command -v gsettings >/dev/null 2>&1; then
|
const script = `if command -v gsettings >/dev/null 2>&1; then
|
||||||
gsettings get org.gnome.desktop.interface icon-theme 2>/dev/null | sed "s/'//g"
|
gsettings get org.gnome.desktop.interface icon-theme 2>/dev/null | sed "s/'//g"
|
||||||
@@ -1443,7 +1379,7 @@ Singleton {
|
|||||||
const platform = (output || "").trim();
|
const platform = (output || "").trim();
|
||||||
if (!platform)
|
if (!platform)
|
||||||
return;
|
return;
|
||||||
if (platform === root.lastAppliedIconTheme || platform === root.iconThemeDark || platform === root.iconThemeLight)
|
if (platform === SessionData.lastAppliedIconTheme || platform === root.iconThemeDark || platform === root.iconThemeLight)
|
||||||
return;
|
return;
|
||||||
root.setIconThemeUnmanaged();
|
root.setIconThemeUnmanaged();
|
||||||
ToastService.showWarning(I18n.tr("Icon theme changed outside DMS; switched to System Default", "shown when an external tool overrides the icon theme DMS applied"));
|
ToastService.showWarning(I18n.tr("Icon theme changed outside DMS; switched to System Default", "shown when an external tool overrides the icon theme DMS applied"));
|
||||||
@@ -1515,7 +1451,8 @@ Singleton {
|
|||||||
const gtkThemeName = (resolved === "System Default") ? systemDefaultIconTheme : resolved;
|
const gtkThemeName = (resolved === "System Default") ? systemDefaultIconTheme : resolved;
|
||||||
if (gtkThemeName === "System Default" || gtkThemeName === "")
|
if (gtkThemeName === "System Default" || gtkThemeName === "")
|
||||||
return;
|
return;
|
||||||
lastAppliedIconTheme = gtkThemeName;
|
SessionData.lastAppliedIconTheme = gtkThemeName;
|
||||||
|
SessionData.saveSettings();
|
||||||
if (typeof DMSService !== "undefined" && DMSService.apiVersion >= 3 && typeof PortalService !== "undefined") {
|
if (typeof DMSService !== "undefined" && DMSService.apiVersion >= 3 && typeof PortalService !== "undefined") {
|
||||||
PortalService.setSystemIconTheme(gtkThemeName);
|
PortalService.setSystemIconTheme(gtkThemeName);
|
||||||
}
|
}
|
||||||
@@ -1598,26 +1535,28 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function markGreeterSyncPending(who, key, oldValue) {
|
function markGreeterSyncPending(who, key, oldValue) {
|
||||||
if (!(key in greeterSyncBaseline)) {
|
if (!(key in SessionData.greeterSyncBaseline)) {
|
||||||
var baseline = greeterSyncBaseline;
|
var baseline = Object.assign({}, SessionData.greeterSyncBaseline);
|
||||||
baseline[key] = oldValue;
|
baseline[key] = oldValue;
|
||||||
greeterSyncBaseline = baseline;
|
SessionData.greeterSyncBaseline = baseline;
|
||||||
}
|
}
|
||||||
greeterSyncPending = true;
|
SessionData.greeterSyncPending = true;
|
||||||
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearGreeterSyncPending() {
|
function clearGreeterSyncPending() {
|
||||||
greeterSyncBaseline = {};
|
SessionData.greeterSyncBaseline = {};
|
||||||
greeterSyncPending = false;
|
SessionData.greeterSyncPending = false;
|
||||||
saveSettings();
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
function revertGreeterSyncPending() {
|
function revertGreeterSyncPending() {
|
||||||
for (var key in greeterSyncBaseline) {
|
for (var key in SessionData.greeterSyncBaseline) {
|
||||||
root[key] = greeterSyncBaseline[key];
|
root[key] = SessionData.greeterSyncBaseline[key];
|
||||||
}
|
}
|
||||||
greeterSyncBaseline = {};
|
SessionData.greeterSyncBaseline = {};
|
||||||
greeterSyncPending = false;
|
SessionData.greeterSyncPending = false;
|
||||||
|
SessionData.saveSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1650,6 +1589,8 @@ Singleton {
|
|||||||
|
|
||||||
const oldVersion = obj?.configVersion ?? 0;
|
const oldVersion = obj?.configVersion ?? 0;
|
||||||
const legacyPins = oldVersion < 13 ? Store.extractPins(obj) : null;
|
const legacyPins = oldVersion < 13 ? Store.extractPins(obj) : null;
|
||||||
|
const sessionPayload = oldVersion < 15 ? Store.extractSessionPayload(obj) : null;
|
||||||
|
const cachePayload = oldVersion < 15 ? Store.extractCachePayload(obj) : null;
|
||||||
if (oldVersion < settingsConfigVersion) {
|
if (oldVersion < settingsConfigVersion) {
|
||||||
const migrated = Store.migrateToVersion(obj, settingsConfigVersion);
|
const migrated = Store.migrateToVersion(obj, settingsConfigVersion);
|
||||||
if (migrated) {
|
if (migrated) {
|
||||||
@@ -1659,6 +1600,14 @@ Singleton {
|
|||||||
}
|
}
|
||||||
if (legacyPins)
|
if (legacyPins)
|
||||||
Qt.callLater(() => CacheData.migratePins(legacyPins));
|
Qt.callLater(() => CacheData.migratePins(legacyPins));
|
||||||
|
if (cachePayload)
|
||||||
|
Qt.callLater(() => CacheData.migrateUsageHistories(cachePayload));
|
||||||
|
if (sessionPayload) {
|
||||||
|
Qt.callLater(() => {
|
||||||
|
SessionData.importFromSettings(sessionPayload);
|
||||||
|
_mergeSessionState();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (obj?.lockScreenActiveMonitor !== undefined) {
|
if (obj?.lockScreenActiveMonitor !== undefined) {
|
||||||
var oldVal = obj.lockScreenActiveMonitor;
|
var oldVal = obj.lockScreenActiveMonitor;
|
||||||
@@ -1697,6 +1646,7 @@ Singleton {
|
|||||||
|
|
||||||
_loadedSettingsSnapshot = JSON.stringify(Store.toJson(root));
|
_loadedSettingsSnapshot = JSON.stringify(Store.toJson(root));
|
||||||
_hasLoaded = true;
|
_hasLoaded = true;
|
||||||
|
_mergeSessionState();
|
||||||
applyStoredTheme();
|
applyStoredTheme();
|
||||||
updateCompositorCursor();
|
updateCompositorCursor();
|
||||||
Qt.callLater(checkIconThemeDrift);
|
Qt.callLater(checkIconThemeDrift);
|
||||||
@@ -1717,6 +1667,28 @@ Singleton {
|
|||||||
|
|
||||||
property var _pendingMigration: null
|
property var _pendingMigration: null
|
||||||
|
|
||||||
|
function _mergeSessionState() {
|
||||||
|
if (!_hasLoaded || !SessionData._hasLoaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const pluginState = SessionData.builtInPluginState || {};
|
||||||
|
if (Object.keys(pluginState).length > 0) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(builtInPluginSettings));
|
||||||
|
for (const id in pluginState) {
|
||||||
|
updated[id] = pluginState[id];
|
||||||
|
}
|
||||||
|
builtInPluginSettings = updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SessionData
|
||||||
|
|
||||||
|
function onLoaded() {
|
||||||
|
root._mergeSessionState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _checkSettingsWritable() {
|
function _checkSettingsWritable() {
|
||||||
settingsWritableCheckProcess.running = true;
|
settingsWritableCheckProcess.running = true;
|
||||||
}
|
}
|
||||||
@@ -3144,50 +3116,6 @@ Singleton {
|
|||||||
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNiriOutputSetting(outputId, key, defaultValue) {
|
|
||||||
if (!niriOutputSettings[outputId])
|
|
||||||
return defaultValue;
|
|
||||||
return niriOutputSettings[outputId][key] !== undefined ? niriOutputSettings[outputId][key] : defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setNiriOutputSetting(outputId, key, value) {
|
|
||||||
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
|
|
||||||
if (!updated[outputId])
|
|
||||||
updated[outputId] = {};
|
|
||||||
updated[outputId][key] = value;
|
|
||||||
niriOutputSettings = updated;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNiriOutputSettings(outputId) {
|
|
||||||
const settings = niriOutputSettings[outputId];
|
|
||||||
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHyprlandOutputSetting(outputId, key, defaultValue) {
|
|
||||||
if (!hyprlandOutputSettings[outputId])
|
|
||||||
return defaultValue;
|
|
||||||
return hyprlandOutputSettings[outputId][key] !== undefined ? hyprlandOutputSettings[outputId][key] : defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setHyprlandOutputSetting(outputId, key, value) {
|
|
||||||
const updated = JSON.parse(JSON.stringify(hyprlandOutputSettings));
|
|
||||||
if (!updated[outputId])
|
|
||||||
updated[outputId] = {};
|
|
||||||
updated[outputId][key] = value;
|
|
||||||
hyprlandOutputSettings = updated;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeHyprlandOutputSetting(outputId, key) {
|
|
||||||
if (!hyprlandOutputSettings[outputId] || !(key in hyprlandOutputSettings[outputId]))
|
|
||||||
return;
|
|
||||||
const updated = JSON.parse(JSON.stringify(hyprlandOutputSettings));
|
|
||||||
delete updated[outputId][key];
|
|
||||||
hyprlandOutputSettings = updated;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeDisplayProfile(compositor, profileId) {
|
function removeDisplayProfile(compositor, profileId) {
|
||||||
if (!displayProfiles[compositor] || !displayProfiles[compositor][profileId])
|
if (!displayProfiles[compositor] || !displayProfiles[compositor][profileId])
|
||||||
return;
|
return;
|
||||||
@@ -3197,26 +3125,6 @@ Singleton {
|
|||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActiveDisplayProfile(compositor) {
|
|
||||||
return activeDisplayProfile[compositor] || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function setActiveDisplayProfile(compositor, profileId) {
|
|
||||||
const updated = JSON.parse(JSON.stringify(activeDisplayProfile));
|
|
||||||
updated[compositor] = profileId;
|
|
||||||
activeDisplayProfile = updated;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setActiveDisplayProfileModes(compositor, modes) {
|
|
||||||
if (JSON.stringify(activeDisplayProfileModes[compositor] || {}) === JSON.stringify(modes || {}))
|
|
||||||
return;
|
|
||||||
const updated = JSON.parse(JSON.stringify(activeDisplayProfileModes));
|
|
||||||
updated[compositor] = modes;
|
|
||||||
activeDisplayProfileModes = updated;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDisplayPreviousRefreshModes(compositor, modes) {
|
function setDisplayPreviousRefreshModes(compositor, modes) {
|
||||||
if (JSON.stringify(displayPreviousRefreshModes[compositor] || {}) === JSON.stringify(modes || {}))
|
if (JSON.stringify(displayPreviousRefreshModes[compositor] || {}) === JSON.stringify(modes || {}))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -367,8 +367,7 @@ Singleton {
|
|||||||
|
|
||||||
function deferGreeterAutoLoginSyncToPill(details) {
|
function deferGreeterAutoLoginSyncToPill(details) {
|
||||||
toastCategoryDismissed("greeter-autologin-sync");
|
toastCategoryDismissed("greeter-autologin-sync");
|
||||||
if (settingsRoot)
|
SessionData.set("greeterSyncPending", true);
|
||||||
settingsRoot.set("greeterSyncPending", true);
|
|
||||||
toastRequested(1, I18n.tr("Auto-login change needs a sync"), I18n.tr("Administrator access is required. Use the Sync button in Settings → Greeter to apply.") + (details ? "\n\n" + details : ""), "dms-greeter sync --autologin", "greeter-autologin-sync");
|
toastRequested(1, I18n.tr("Auto-login change needs a sync"), I18n.tr("Administrator access is required. Use the Sync button in Settings → Greeter to apply.") + (details ? "\n\n" + details : ""), "dms-greeter sync --autologin", "greeter-autologin-sync");
|
||||||
finishGreeterAutoLoginSync();
|
finishGreeterAutoLoginSync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,17 @@ var SPEC = {
|
|||||||
|
|
||||||
notepadLastMode: { def: "" },
|
notepadLastMode: { def: "" },
|
||||||
|
|
||||||
|
niriOutputSettings: { def: {} },
|
||||||
|
hyprlandOutputSettings: { def: {} },
|
||||||
|
activeDisplayProfile: { def: {} },
|
||||||
|
activeDisplayProfileModes: { def: {} },
|
||||||
|
desktopWidgetGridSettings: { def: {} },
|
||||||
|
desktopWidgetInstancePositions: { def: {} },
|
||||||
|
builtInPluginState: { def: {} },
|
||||||
|
greeterSyncPending: { def: false },
|
||||||
|
greeterSyncBaseline: { def: {} },
|
||||||
|
lastAppliedIconTheme: { def: "" },
|
||||||
|
|
||||||
launcherLastMode: { def: "all" },
|
launcherLastMode: { def: "all" },
|
||||||
launcherLastFileSearchType: { def: "all" },
|
launcherLastFileSearchType: { def: "all" },
|
||||||
launcherLastQuery: { def: "" },
|
launcherLastQuery: { def: "" },
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
.pragma library
|
.pragma library
|
||||||
|
|
||||||
.import "./SessionSpec.js" as SpecModule
|
.import "./SessionSpec.js" as SpecModule
|
||||||
|
.import "./SpecUtil.js" as Util
|
||||||
|
|
||||||
function parse(root, jsonObj) {
|
function parse(root, jsonObj) {
|
||||||
var SPEC = SpecModule.SPEC;
|
var SPEC = SpecModule.SPEC;
|
||||||
@@ -9,7 +10,7 @@ function parse(root, jsonObj) {
|
|||||||
|
|
||||||
for (var k in SPEC) {
|
for (var k in SPEC) {
|
||||||
if (!(k in jsonObj)) {
|
if (!(k in jsonObj)) {
|
||||||
root[k] = SPEC[k].def;
|
root[k] = Util.cloneDef(SPEC[k].def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ function toJson(root) {
|
|||||||
var out = {};
|
var out = {};
|
||||||
for (var k in SPEC) {
|
for (var k in SPEC) {
|
||||||
if (SPEC[k].persist === false) continue;
|
if (SPEC[k].persist === false) continue;
|
||||||
|
if (Util.isDefault(root[k], SPEC[k].def)) continue;
|
||||||
out[k] = root[k];
|
out[k] = root[k];
|
||||||
}
|
}
|
||||||
out.configVersion = root.sessionConfigVersion;
|
out.configVersion = root.sessionConfigVersion;
|
||||||
@@ -73,5 +75,13 @@ function migrateToVersion(obj, targetVersion, settingsData) {
|
|||||||
session.configVersion = 3;
|
session.configVersion = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentVersion < 4) {
|
||||||
|
console.info("SessionData: Migrating session to version 4");
|
||||||
|
console.info("SessionData: Dropping keys that match defaults; session.json now stores only changed values");
|
||||||
|
|
||||||
|
Util.stripDefaults(session, SpecModule.SPEC);
|
||||||
|
session.configVersion = 4;
|
||||||
|
}
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
.pragma library
|
.pragma library
|
||||||
|
|
||||||
|
.import "./SpecUtil.js" as Util
|
||||||
|
|
||||||
function percentToUnit(v) {
|
function percentToUnit(v) {
|
||||||
if (v === undefined || v === null) return undefined;
|
if (v === undefined || v === null) return undefined;
|
||||||
return v > 1 ? v / 100 : v;
|
return v > 1 ? v / 100 : v;
|
||||||
@@ -270,16 +272,12 @@ var SPEC = {
|
|||||||
greeterFontFamily: { def: "", onChange: "markGreeterSyncPending" },
|
greeterFontFamily: { def: "", onChange: "markGreeterSyncPending" },
|
||||||
greeterWallpaperFillMode: { def: "", onChange: "markGreeterSyncPending" },
|
greeterWallpaperFillMode: { def: "", onChange: "markGreeterSyncPending" },
|
||||||
greeterPamExternallyManaged: { def: false, onChange: "markGreeterSyncPending" },
|
greeterPamExternallyManaged: { def: false, onChange: "markGreeterSyncPending" },
|
||||||
greeterSyncPending: { def: false },
|
|
||||||
greeterSyncBaseline: { def: {} },
|
|
||||||
mediaSize: { def: 1 },
|
mediaSize: { def: 1 },
|
||||||
|
|
||||||
appLauncherViewMode: { def: "list" },
|
appLauncherViewMode: { def: "list" },
|
||||||
spotlightModalViewMode: { def: "list" },
|
spotlightModalViewMode: { def: "list" },
|
||||||
browserPickerViewMode: { def: "grid" },
|
browserPickerViewMode: { def: "grid" },
|
||||||
browserUsageHistory: { def: {} },
|
|
||||||
appPickerViewMode: { def: "grid" },
|
appPickerViewMode: { def: "grid" },
|
||||||
filePickerUsageHistory: { def: {} },
|
|
||||||
sortAppsAlphabetically: { def: false },
|
sortAppsAlphabetically: { def: false },
|
||||||
appLauncherGridColumns: { def: 4 },
|
appLauncherGridColumns: { def: 4 },
|
||||||
spotlightCloseNiriOverview: { def: true },
|
spotlightCloseNiriOverview: { def: true },
|
||||||
@@ -312,7 +310,6 @@ var SPEC = {
|
|||||||
iconThemeDark: { def: "System Default", onChange: "applyStoredIconTheme" },
|
iconThemeDark: { def: "System Default", onChange: "applyStoredIconTheme" },
|
||||||
iconThemeLight: { def: "System Default", onChange: "applyStoredIconTheme" },
|
iconThemeLight: { def: "System Default", onChange: "applyStoredIconTheme" },
|
||||||
iconThemePerMode: { def: false, onChange: "applyStoredIconTheme" },
|
iconThemePerMode: { def: false, onChange: "applyStoredIconTheme" },
|
||||||
lastAppliedIconTheme: { def: "" },
|
|
||||||
availableIconThemes: { def: ["System Default"], persist: false },
|
availableIconThemes: { def: ["System Default"], persist: false },
|
||||||
systemDefaultIconTheme: { def: "", persist: false },
|
systemDefaultIconTheme: { def: "", persist: false },
|
||||||
|
|
||||||
@@ -558,11 +555,7 @@ var SPEC = {
|
|||||||
displayNameMode: { def: "system" },
|
displayNameMode: { def: "system" },
|
||||||
screenPreferences: { def: {} },
|
screenPreferences: { def: {} },
|
||||||
showOnLastDisplay: { def: {} },
|
showOnLastDisplay: { def: {} },
|
||||||
niriOutputSettings: { def: {} },
|
|
||||||
hyprlandOutputSettings: { def: {} },
|
|
||||||
displayProfiles: { def: {} },
|
displayProfiles: { def: {} },
|
||||||
activeDisplayProfile: { def: {} },
|
|
||||||
activeDisplayProfileModes: { def: {} },
|
|
||||||
displayPreviousRefreshModes: { def: {} },
|
displayPreviousRefreshModes: { def: {} },
|
||||||
displayProfileAutoSelect: { def: false },
|
displayProfileAutoSelect: { def: false },
|
||||||
displayShowDisconnected: { def: false },
|
displayShowDisconnected: { def: false },
|
||||||
@@ -668,7 +661,6 @@ var SPEC = {
|
|||||||
systemMonitorDisplayPreferences: { def: ["all"] },
|
systemMonitorDisplayPreferences: { def: ["all"] },
|
||||||
systemMonitorVariants: { def: [] },
|
systemMonitorVariants: { def: [] },
|
||||||
desktopWidgetPositions: { def: {} },
|
desktopWidgetPositions: { def: {} },
|
||||||
desktopWidgetGridSettings: { def: {} },
|
|
||||||
|
|
||||||
desktopWidgetInstances: { def: [] },
|
desktopWidgetInstances: { def: [] },
|
||||||
|
|
||||||
@@ -710,7 +702,7 @@ function getValidKeys() {
|
|||||||
|
|
||||||
function set(root, key, value, saveFn, hooks) {
|
function set(root, key, value, saveFn, hooks) {
|
||||||
if (!(key in SPEC)) return;
|
if (!(key in SPEC)) return;
|
||||||
if (value === undefined || value === null) value = SPEC[key].def;
|
if (value === undefined || value === null) value = Util.cloneDef(SPEC[key].def);
|
||||||
var oldValue = root[key];
|
var oldValue = root[key];
|
||||||
root[key] = value;
|
root[key] = value;
|
||||||
var hookName = SPEC[key].onChange;
|
var hookName = SPEC[key].onChange;
|
||||||
|
|||||||
@@ -1,9 +1,78 @@
|
|||||||
.pragma library
|
.pragma library
|
||||||
|
|
||||||
.import "./SettingsSpec.js" as SpecModule
|
.import "./SettingsSpec.js" as SpecModule
|
||||||
|
.import "./SpecUtil.js" as Util
|
||||||
|
|
||||||
var PIN_KEYS = ["brightnessDevicePins", "wifiNetworkPins", "bluetoothDevicePins", "audioInputDevicePins", "audioOutputDevicePins"];
|
var PIN_KEYS = ["brightnessDevicePins", "wifiNetworkPins", "bluetoothDevicePins", "audioInputDevicePins", "audioOutputDevicePins"];
|
||||||
|
|
||||||
|
var SESSION_MOVED_KEYS = ["niriOutputSettings", "hyprlandOutputSettings", "activeDisplayProfile", "activeDisplayProfileModes", "desktopWidgetGridSettings", "greeterSyncPending", "greeterSyncBaseline", "lastAppliedIconTheme"];
|
||||||
|
var CACHE_MOVED_KEYS = ["browserUsageHistory", "filePickerUsageHistory"];
|
||||||
|
var SESSION_BACKED_PLUGIN_IDS = ["dankNotepadModule"];
|
||||||
|
|
||||||
|
// Superseded by desktopWidgetInstances at v4; nothing has written them since
|
||||||
|
var STALE_WIDGET_KEYS = ["desktopClockEnabled", "desktopClockStyle", "desktopClockTransparency", "desktopClockColorMode", "desktopClockCustomColor", "desktopClockShowDate", "desktopClockShowAnalogNumbers", "desktopClockShowAnalogSeconds", "desktopClockX", "desktopClockY", "desktopClockWidth", "desktopClockHeight", "desktopClockDisplayPreferences", "systemMonitorEnabled", "systemMonitorShowHeader", "systemMonitorTransparency", "systemMonitorColorMode", "systemMonitorCustomColor", "systemMonitorShowCpu", "systemMonitorShowCpuGraph", "systemMonitorShowCpuTemp", "systemMonitorShowGpuTemp", "systemMonitorGpuPciId", "systemMonitorShowMemory", "systemMonitorShowMemoryGraph", "systemMonitorShowNetwork", "systemMonitorShowNetworkGraph", "systemMonitorShowDisk", "systemMonitorShowTopProcesses", "systemMonitorTopProcessCount", "systemMonitorTopProcessSortBy", "systemMonitorGraphInterval", "systemMonitorLayoutMode", "systemMonitorX", "systemMonitorY", "systemMonitorWidth", "systemMonitorHeight", "systemMonitorDisplayPreferences", "systemMonitorVariants", "desktopWidgetPositions"];
|
||||||
|
|
||||||
|
function withoutInstancePositions(instances) {
|
||||||
|
if (!Array.isArray(instances)) return instances;
|
||||||
|
return instances.map(function (inst) {
|
||||||
|
if (!inst || !inst.positions) return inst;
|
||||||
|
var copy = Object.assign({}, inst);
|
||||||
|
delete copy.positions;
|
||||||
|
return copy;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function withoutSessionBackedPluginState(pluginSettings) {
|
||||||
|
if (!pluginSettings) return pluginSettings;
|
||||||
|
var copy = Object.assign({}, pluginSettings);
|
||||||
|
for (var i = 0; i < SESSION_BACKED_PLUGIN_IDS.length; i++) {
|
||||||
|
delete copy[SESSION_BACKED_PLUGIN_IDS[i]];
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractSessionPayload(obj) {
|
||||||
|
if (!obj) return null;
|
||||||
|
|
||||||
|
var payload = {};
|
||||||
|
for (var i = 0; i < SESSION_MOVED_KEYS.length; i++) {
|
||||||
|
var key = SESSION_MOVED_KEYS[i];
|
||||||
|
if (key in obj) payload[key] = obj[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var positions = {};
|
||||||
|
var instances = Array.isArray(obj.desktopWidgetInstances) ? obj.desktopWidgetInstances : [];
|
||||||
|
for (var i = 0; i < instances.length; i++) {
|
||||||
|
var inst = instances[i];
|
||||||
|
if (inst && inst.id && inst.positions && Object.keys(inst.positions).length > 0) {
|
||||||
|
positions[inst.id] = inst.positions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(positions).length > 0) payload.desktopWidgetInstancePositions = positions;
|
||||||
|
|
||||||
|
var pluginState = {};
|
||||||
|
for (var i = 0; i < SESSION_BACKED_PLUGIN_IDS.length; i++) {
|
||||||
|
var id = SESSION_BACKED_PLUGIN_IDS[i];
|
||||||
|
if (obj.builtInPluginSettings && obj.builtInPluginSettings[id]) {
|
||||||
|
pluginState[id] = obj.builtInPluginSettings[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(pluginState).length > 0) payload.builtInPluginState = pluginState;
|
||||||
|
|
||||||
|
return Object.keys(payload).length > 0 ? payload : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractCachePayload(obj) {
|
||||||
|
if (!obj) return null;
|
||||||
|
|
||||||
|
var payload = {};
|
||||||
|
for (var i = 0; i < CACHE_MOVED_KEYS.length; i++) {
|
||||||
|
var key = CACHE_MOVED_KEYS[i];
|
||||||
|
if (obj[key] && Object.keys(obj[key]).length > 0) payload[key] = obj[key];
|
||||||
|
}
|
||||||
|
return Object.keys(payload).length > 0 ? payload : null;
|
||||||
|
}
|
||||||
|
|
||||||
function extractPins(obj) {
|
function extractPins(obj) {
|
||||||
if (!obj) return null;
|
if (!obj) return null;
|
||||||
|
|
||||||
@@ -28,7 +97,7 @@ function parse(root, jsonObj) {
|
|||||||
// would wipe values set by detection processes on every reload.
|
// would wipe values set by detection processes on every reload.
|
||||||
if (SPEC[k].persist === false) continue;
|
if (SPEC[k].persist === false) continue;
|
||||||
if (!(k in jsonObj)) {
|
if (!(k in jsonObj)) {
|
||||||
root[k] = SPEC[k].def;
|
root[k] = Util.cloneDef(SPEC[k].def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +117,11 @@ function toJson(root) {
|
|||||||
for (var k in SPEC) {
|
for (var k in SPEC) {
|
||||||
if (SPEC[k].persist === false) continue;
|
if (SPEC[k].persist === false) continue;
|
||||||
if (k === "pluginSettings") continue;
|
if (k === "pluginSettings") continue;
|
||||||
out[k] = root[k];
|
var value = root[k];
|
||||||
|
if (k === "desktopWidgetInstances") value = withoutInstancePositions(value);
|
||||||
|
if (k === "builtInPluginSettings") value = withoutSessionBackedPluginState(value);
|
||||||
|
if (Util.isDefault(value, SPEC[k].def)) continue;
|
||||||
|
out[k] = value;
|
||||||
}
|
}
|
||||||
out.configVersion = root.settingsConfigVersion;
|
out.configVersion = root.settingsConfigVersion;
|
||||||
return out;
|
return out;
|
||||||
@@ -289,5 +362,32 @@ function migrateToVersion(obj, targetVersion) {
|
|||||||
settings.configVersion = 13;
|
settings.configVersion = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentVersion < 14) {
|
||||||
|
console.info("Migrating settings from version", currentVersion, "to version 14");
|
||||||
|
console.info("Dropping keys that match defaults; settings.json now stores only changed values");
|
||||||
|
|
||||||
|
Util.stripDefaults(settings, SpecModule.SPEC);
|
||||||
|
settings.configVersion = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentVersion < 15) {
|
||||||
|
console.info("Migrating settings from version", currentVersion, "to version 15");
|
||||||
|
console.info("Moving machine-specific state to session.json and usage histories to cache.json");
|
||||||
|
|
||||||
|
var movedKeys = SESSION_MOVED_KEYS.concat(CACHE_MOVED_KEYS, STALE_WIDGET_KEYS);
|
||||||
|
for (var i = 0; i < movedKeys.length; i++) {
|
||||||
|
delete settings[movedKeys[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(settings.desktopWidgetInstances)) {
|
||||||
|
settings.desktopWidgetInstances = withoutInstancePositions(settings.desktopWidgetInstances);
|
||||||
|
}
|
||||||
|
if (settings.builtInPluginSettings) {
|
||||||
|
settings.builtInPluginSettings = withoutSessionBackedPluginState(settings.builtInPluginSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.configVersion = 15;
|
||||||
|
}
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
.pragma library
|
||||||
|
|
||||||
|
function stableStringify(value) {
|
||||||
|
if (value === null || typeof value !== "object")
|
||||||
|
return JSON.stringify(value);
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return "[" + value.map(stableStringify).join(",") + "]";
|
||||||
|
return "{" + Object.keys(value).sort().map(function (k) {
|
||||||
|
return JSON.stringify(k) + ":" + stableStringify(value[k]);
|
||||||
|
}).join(",") + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDefault(value, def) {
|
||||||
|
return stableStringify(value) === stableStringify(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneDef(def) {
|
||||||
|
if (def === null || typeof def !== "object")
|
||||||
|
return def;
|
||||||
|
return JSON.parse(JSON.stringify(def));
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripDefaults(obj, SPEC) {
|
||||||
|
for (var k in SPEC) {
|
||||||
|
if (!(k in obj))
|
||||||
|
continue;
|
||||||
|
if (isDefault(obj[k], SPEC[k].def))
|
||||||
|
delete obj[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1897,7 +1897,7 @@ Item {
|
|||||||
IpcHandler {
|
IpcHandler {
|
||||||
function listProfiles(): string {
|
function listProfiles(): string {
|
||||||
const profiles = DisplayConfigState.validatedProfiles;
|
const profiles = DisplayConfigState.validatedProfiles;
|
||||||
const activeId = SettingsData.getActiveDisplayProfile(CompositorService.compositor);
|
const activeId = SessionData.getActiveDisplayProfile(CompositorService.compositor);
|
||||||
const matchedId = DisplayConfigState.matchedProfile;
|
const matchedId = DisplayConfigState.matchedProfile;
|
||||||
const lines = [];
|
const lines = [];
|
||||||
|
|
||||||
@@ -1952,7 +1952,7 @@ Item {
|
|||||||
if (ids.length === 0)
|
if (ids.length === 0)
|
||||||
return "ERROR: No profiles configured";
|
return "ERROR: No profiles configured";
|
||||||
|
|
||||||
const activeId = SettingsData.getActiveDisplayProfile(CompositorService.compositor);
|
const activeId = SessionData.getActiveDisplayProfile(CompositorService.compositor);
|
||||||
const idx = ids.indexOf(activeId);
|
const idx = ids.indexOf(activeId);
|
||||||
const nextId = ids[(idx + 1) % ids.length];
|
const nextId = ids[(idx + 1) % ids.length];
|
||||||
DisplayConfigState.activateProfile(nextId);
|
DisplayConfigState.activateProfile(nextId);
|
||||||
@@ -1969,7 +1969,7 @@ Item {
|
|||||||
|
|
||||||
function status(): string {
|
function status(): string {
|
||||||
const auto = SettingsData.displayProfileAutoSelect ? "on" : "off";
|
const auto = SettingsData.displayProfileAutoSelect ? "on" : "off";
|
||||||
const activeId = SettingsData.getActiveDisplayProfile(CompositorService.compositor);
|
const activeId = SessionData.getActiveDisplayProfile(CompositorService.compositor);
|
||||||
const matchedId = DisplayConfigState.matchedProfile;
|
const matchedId = DisplayConfigState.matchedProfile;
|
||||||
const profiles = DisplayConfigState.validatedProfiles;
|
const profiles = DisplayConfigState.validatedProfiles;
|
||||||
const activeName = profiles[activeId]?.name || "none";
|
const activeName = profiles[activeId]?.name || "none";
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ DankModal {
|
|||||||
function updateApplicationList() {
|
function updateApplicationList() {
|
||||||
applicationsModel.clear();
|
applicationsModel.clear();
|
||||||
const apps = AppSearchService.applications;
|
const apps = AppSearchService.applications;
|
||||||
const usageHistory = usageHistoryKey && SettingsData[usageHistoryKey] ? SettingsData[usageHistoryKey] : {};
|
const usageHistory = usageHistoryKey && CacheData[usageHistoryKey] ? CacheData[usageHistoryKey] : {};
|
||||||
const hasCategoryFilter = categoryFilter.length > 0;
|
const hasCategoryFilter = categoryFilter.length > 0;
|
||||||
const hasMime = mimeType.length > 0;
|
const hasMime = mimeType.length > 0;
|
||||||
const hasMimeMatches = mimeMatchedAppIds.length > 0;
|
const hasMimeMatches = mimeMatchedAppIds.length > 0;
|
||||||
@@ -557,14 +557,14 @@ DankModal {
|
|||||||
root.applicationSelected(app, root.targetData);
|
root.applicationSelected(app, root.targetData);
|
||||||
|
|
||||||
if (usageHistoryKey && app.appId) {
|
if (usageHistoryKey && app.appId) {
|
||||||
const usageHistory = SettingsData[usageHistoryKey] || {};
|
const usageHistory = CacheData[usageHistoryKey] || {};
|
||||||
const currentCount = usageHistory[app.appId] ? usageHistory[app.appId].count : 0;
|
const currentCount = usageHistory[app.appId] ? usageHistory[app.appId].count : 0;
|
||||||
usageHistory[app.appId] = {
|
usageHistory[app.appId] = {
|
||||||
count: currentCount + 1,
|
count: currentCount + 1,
|
||||||
lastUsed: Date.now(),
|
lastUsed: Date.now(),
|
||||||
name: app.name
|
name: app.name
|
||||||
};
|
};
|
||||||
SettingsData.set(usageHistoryKey, usageHistory);
|
CacheData.set(usageHistoryKey, usageHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
root.close();
|
root.close();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ PluginComponent {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
readonly property bool autoMode: SettingsData.displayProfileAutoSelect
|
readonly property bool autoMode: SettingsData.displayProfileAutoSelect
|
||||||
readonly property string activeProfileId: SettingsData.getActiveDisplayProfile(CompositorService.compositor)
|
readonly property string activeProfileId: SessionData.getActiveDisplayProfile(CompositorService.compositor)
|
||||||
readonly property var activeProfile: allProfiles[activeProfileId] || null
|
readonly property var activeProfile: allProfiles[activeProfileId] || null
|
||||||
readonly property string activeProfileName: activeProfile?.name ?? ""
|
readonly property string activeProfileName: activeProfile?.name ?? ""
|
||||||
readonly property string displayProfileLabel: {
|
readonly property string displayProfileLabel: {
|
||||||
@@ -44,7 +44,7 @@ PluginComponent {
|
|||||||
function setAutoMode(enabled) {
|
function setAutoMode(enabled) {
|
||||||
SettingsData.displayProfileAutoSelect = enabled;
|
SettingsData.displayProfileAutoSelect = enabled;
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
SettingsData.setActiveDisplayProfile(CompositorService.compositor, "");
|
SessionData.setActiveDisplayProfile(CompositorService.compositor, "");
|
||||||
SettingsData.saveSettings();
|
SettingsData.saveSettings();
|
||||||
if (enabled)
|
if (enabled)
|
||||||
DisplayConfigState.applyAutoConfig();
|
DisplayConfigState.applyAutoConfig();
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ Item {
|
|||||||
}
|
}
|
||||||
readonly property string screenKey: SettingsData.getScreenDisplayName(screen)
|
readonly property string screenKey: SettingsData.getScreenDisplayName(screen)
|
||||||
readonly property string positionKey: syncPositionAcrossScreens ? "_synced" : screenKey
|
readonly property string positionKey: syncPositionAcrossScreens ? "_synced" : screenKey
|
||||||
|
readonly property var storedPositions: SessionData.desktopWidgetInstancePositions[instanceId] ?? null
|
||||||
|
|
||||||
readonly property int screenWidth: screen?.width ?? 1920
|
readonly property int screenWidth: screen?.width ?? 1920
|
||||||
readonly property int screenHeight: screen?.height ?? 1080
|
readonly property int screenHeight: screen?.height ?? 1080
|
||||||
@@ -121,7 +122,7 @@ Item {
|
|||||||
|
|
||||||
readonly property bool hasSavedPosition: {
|
readonly property bool hasSavedPosition: {
|
||||||
if (isInstance)
|
if (isInstance)
|
||||||
return instanceData?.positions?.[positionKey]?.x !== undefined;
|
return storedPositions?.[positionKey]?.x !== undefined;
|
||||||
if (usePluginService)
|
if (usePluginService)
|
||||||
return pluginService.loadPluginData(pluginId, "desktopX_" + positionKey, null) !== null;
|
return pluginService.loadPluginData(pluginId, "desktopX_" + positionKey, null) !== null;
|
||||||
return SettingsData.getDesktopWidgetPosition(pluginId, positionKey, "x", null) !== null;
|
return SettingsData.getDesktopWidgetPosition(pluginId, positionKey, "x", null) !== null;
|
||||||
@@ -129,7 +130,7 @@ Item {
|
|||||||
|
|
||||||
readonly property bool hasSavedSize: {
|
readonly property bool hasSavedSize: {
|
||||||
if (isInstance)
|
if (isInstance)
|
||||||
return instanceData?.positions?.[positionKey]?.width !== undefined;
|
return storedPositions?.[positionKey]?.width !== undefined;
|
||||||
if (usePluginService)
|
if (usePluginService)
|
||||||
return pluginService.loadPluginData(pluginId, "desktopWidth_" + positionKey, null) !== null;
|
return pluginService.loadPluginData(pluginId, "desktopWidth_" + positionKey, null) !== null;
|
||||||
return SettingsData.getDesktopWidgetPosition(pluginId, positionKey, "width", null) !== null;
|
return SettingsData.getDesktopWidgetPosition(pluginId, positionKey, "width", null) !== null;
|
||||||
@@ -137,7 +138,7 @@ Item {
|
|||||||
|
|
||||||
property real savedX: {
|
property real savedX: {
|
||||||
if (isInstance) {
|
if (isInstance) {
|
||||||
const val = instanceData?.positions?.[positionKey]?.x;
|
const val = storedPositions?.[positionKey]?.x;
|
||||||
if (val === undefined)
|
if (val === undefined)
|
||||||
return screenWidth / 2 - savedWidth / 2;
|
return screenWidth / 2 - savedWidth / 2;
|
||||||
return syncPositionAcrossScreens ? val * screenWidth : val;
|
return syncPositionAcrossScreens ? val * screenWidth : val;
|
||||||
@@ -155,7 +156,7 @@ Item {
|
|||||||
}
|
}
|
||||||
property real savedY: {
|
property real savedY: {
|
||||||
if (isInstance) {
|
if (isInstance) {
|
||||||
const val = instanceData?.positions?.[positionKey]?.y;
|
const val = storedPositions?.[positionKey]?.y;
|
||||||
if (val === undefined)
|
if (val === undefined)
|
||||||
return screenHeight / 2 - savedHeight / 2;
|
return screenHeight / 2 - savedHeight / 2;
|
||||||
return syncPositionAcrossScreens ? val * screenHeight : val;
|
return syncPositionAcrossScreens ? val * screenHeight : val;
|
||||||
@@ -173,7 +174,7 @@ Item {
|
|||||||
}
|
}
|
||||||
property real savedWidth: {
|
property real savedWidth: {
|
||||||
if (isInstance) {
|
if (isInstance) {
|
||||||
const val = instanceData?.positions?.[positionKey]?.width;
|
const val = storedPositions?.[positionKey]?.width;
|
||||||
if (val === undefined)
|
if (val === undefined)
|
||||||
return 280;
|
return 280;
|
||||||
return val;
|
return val;
|
||||||
@@ -191,7 +192,7 @@ Item {
|
|||||||
}
|
}
|
||||||
property real savedHeight: {
|
property real savedHeight: {
|
||||||
if (isInstance) {
|
if (isInstance) {
|
||||||
const val = instanceData?.positions?.[positionKey]?.height;
|
const val = storedPositions?.[positionKey]?.height;
|
||||||
if (val === undefined)
|
if (val === undefined)
|
||||||
return forceSquare ? savedWidth : 180;
|
return forceSquare ? savedWidth : 180;
|
||||||
return forceSquare ? savedWidth : val;
|
return forceSquare ? savedWidth : val;
|
||||||
@@ -236,14 +237,14 @@ Item {
|
|||||||
property bool acceptsKeyboardFocus: contentLoader.item?.acceptsKeyboardFocus ?? false
|
property bool acceptsKeyboardFocus: contentLoader.item?.acceptsKeyboardFocus ?? false
|
||||||
property bool isInteracting: dragArea.pressed || resizeArea.pressed
|
property bool isInteracting: dragArea.pressed || resizeArea.pressed
|
||||||
|
|
||||||
property var _gridSettingsTrigger: SettingsData.desktopWidgetGridSettings
|
property var _gridSettingsTrigger: SessionData.desktopWidgetGridSettings
|
||||||
readonly property int gridSize: {
|
readonly property int gridSize: {
|
||||||
void _gridSettingsTrigger;
|
void _gridSettingsTrigger;
|
||||||
return SettingsData.getDesktopWidgetGridSetting(screenKey, "size", 40);
|
return SessionData.getDesktopWidgetGridSetting(screenKey, "size", 40);
|
||||||
}
|
}
|
||||||
readonly property bool gridEnabled: {
|
readonly property bool gridEnabled: {
|
||||||
void _gridSettingsTrigger;
|
void _gridSettingsTrigger;
|
||||||
return SettingsData.getDesktopWidgetGridSetting(screenKey, "enabled", false);
|
return SessionData.getDesktopWidgetGridSetting(screenKey, "enabled", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function snapToGrid(value) {
|
function snapToGrid(value) {
|
||||||
@@ -254,7 +255,7 @@ Item {
|
|||||||
const xVal = syncPositionAcrossScreens ? finalX / screenWidth : finalX;
|
const xVal = syncPositionAcrossScreens ? finalX / screenWidth : finalX;
|
||||||
const yVal = syncPositionAcrossScreens ? finalY / screenHeight : finalY;
|
const yVal = syncPositionAcrossScreens ? finalY / screenHeight : finalY;
|
||||||
if (isInstance && instanceData) {
|
if (isInstance && instanceData) {
|
||||||
SettingsData.updateDesktopWidgetInstancePosition(instanceId, positionKey, {
|
SessionData.updateDesktopWidgetInstancePosition(instanceId, positionKey, {
|
||||||
x: xVal,
|
x: xVal,
|
||||||
y: yVal
|
y: yVal
|
||||||
});
|
});
|
||||||
@@ -275,7 +276,7 @@ Item {
|
|||||||
const sizeVal = forceSquare ? Math.max(finalW, finalH) : finalW;
|
const sizeVal = forceSquare ? Math.max(finalW, finalH) : finalW;
|
||||||
const heightVal = forceSquare ? sizeVal : finalH;
|
const heightVal = forceSquare ? sizeVal : finalH;
|
||||||
if (isInstance && instanceData) {
|
if (isInstance && instanceData) {
|
||||||
SettingsData.updateDesktopWidgetInstancePosition(instanceId, positionKey, {
|
SessionData.updateDesktopWidgetInstancePosition(instanceId, positionKey, {
|
||||||
width: sizeVal,
|
width: sizeVal,
|
||||||
height: heightVal
|
height: heightVal
|
||||||
});
|
});
|
||||||
@@ -342,15 +343,15 @@ Item {
|
|||||||
return;
|
return;
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_G:
|
case Qt.Key_G:
|
||||||
SettingsData.setDesktopWidgetGridSetting(root.screenKey, "enabled", !root.gridEnabled);
|
SessionData.setDesktopWidgetGridSetting(root.screenKey, "enabled", !root.gridEnabled);
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
break;
|
break;
|
||||||
case Qt.Key_Z:
|
case Qt.Key_Z:
|
||||||
SettingsData.setDesktopWidgetGridSetting(root.screenKey, "size", Math.max(10, root.gridSize - 10));
|
SessionData.setDesktopWidgetGridSetting(root.screenKey, "size", Math.max(10, root.gridSize - 10));
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
break;
|
break;
|
||||||
case Qt.Key_X:
|
case Qt.Key_X:
|
||||||
SettingsData.setDesktopWidgetGridSetting(root.screenKey, "size", Math.min(200, root.gridSize + 10));
|
SessionData.setDesktopWidgetGridSetting(root.screenKey, "size", Math.min(200, root.gridSize + 10));
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ SettingsCard {
|
|||||||
if (!root.instanceId)
|
if (!root.instanceId)
|
||||||
return;
|
return;
|
||||||
if (isChecked)
|
if (isChecked)
|
||||||
SettingsData.syncDesktopWidgetPositionToAllScreens(root.instanceId);
|
SessionData.syncDesktopWidgetPositionToAllScreens(root.instanceId);
|
||||||
SettingsData.updateDesktopWidgetInstanceConfig(root.instanceId, {
|
SettingsData.updateDesktopWidgetInstanceConfig(root.instanceId, {
|
||||||
syncPositionAcrossScreens: isChecked
|
syncPositionAcrossScreens: isChecked
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -234,8 +234,8 @@ Singleton {
|
|||||||
default:
|
default:
|
||||||
parsed = {};
|
parsed = {};
|
||||||
}
|
}
|
||||||
const niriSettings = SettingsData.niriOutputSettings || {};
|
const niriSettings = SessionData.niriOutputSettings || {};
|
||||||
const hyprSettings = SettingsData.hyprlandOutputSettings || {};
|
const hyprSettings = SessionData.hyprlandOutputSettings || {};
|
||||||
const profileOutputs = {};
|
const profileOutputs = {};
|
||||||
for (const outputName in parsed) {
|
for (const outputName in parsed) {
|
||||||
const od = parsed[outputName];
|
const od = parsed[outputName];
|
||||||
@@ -267,7 +267,7 @@ Singleton {
|
|||||||
|
|
||||||
function publishActiveProfileModes() {
|
function publishActiveProfileModes() {
|
||||||
const compositor = CompositorService.compositor;
|
const compositor = CompositorService.compositor;
|
||||||
const profileId = SettingsData.getActiveDisplayProfile(compositor);
|
const profileId = SessionData.getActiveDisplayProfile(compositor);
|
||||||
const profile = profileId ? validatedProfiles[profileId] : null;
|
const profile = profileId ? validatedProfiles[profileId] : null;
|
||||||
const outputs = profile?.outputs || {};
|
const outputs = profile?.outputs || {};
|
||||||
const modes = {};
|
const modes = {};
|
||||||
@@ -280,7 +280,7 @@ Singleton {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsData.setActiveDisplayProfileModes(compositor, modes);
|
SessionData.setActiveDisplayProfileModes(compositor, modes);
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateProfileId() {
|
function generateProfileId() {
|
||||||
@@ -561,7 +561,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onWriteSuccess = () => {
|
const onWriteSuccess = () => {
|
||||||
SettingsData.setActiveDisplayProfile(CompositorService.compositor, configId);
|
SessionData.setActiveDisplayProfile(CompositorService.compositor, configId);
|
||||||
publishActiveProfileModes();
|
publishActiveProfileModes();
|
||||||
if (isManual) {
|
if (isManual) {
|
||||||
profilesLoading = false;
|
profilesLoading = false;
|
||||||
@@ -651,7 +651,7 @@ Singleton {
|
|||||||
validatedProfiles = updated;
|
validatedProfiles = updated;
|
||||||
currentOutputSet = buildCurrentOutputSet();
|
currentOutputSet = buildCurrentOutputSet();
|
||||||
matchedProfile = findMatchingProfile();
|
matchedProfile = findMatchingProfile();
|
||||||
SettingsData.setActiveDisplayProfile(CompositorService.compositor, id);
|
SessionData.setActiveDisplayProfile(CompositorService.compositor, id);
|
||||||
publishActiveProfileModes();
|
publishActiveProfileModes();
|
||||||
profileSaved(id, profileName);
|
profileSaved(id, profileName);
|
||||||
});
|
});
|
||||||
@@ -680,7 +680,7 @@ Singleton {
|
|||||||
|
|
||||||
function deleteProfile(profileId) {
|
function deleteProfile(profileId) {
|
||||||
const compositor = CompositorService.compositor;
|
const compositor = CompositorService.compositor;
|
||||||
const isActive = SettingsData.getActiveDisplayProfile(compositor) === profileId;
|
const isActive = SessionData.getActiveDisplayProfile(compositor) === profileId;
|
||||||
|
|
||||||
profilesLoading = true;
|
profilesLoading = true;
|
||||||
readMonitorsJson(data => {
|
readMonitorsJson(data => {
|
||||||
@@ -691,7 +691,7 @@ Singleton {
|
|||||||
profilesLoading = false;
|
profilesLoading = false;
|
||||||
SettingsData.removeDisplayProfile(compositor, profileId);
|
SettingsData.removeDisplayProfile(compositor, profileId);
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
SettingsData.setActiveDisplayProfile(compositor, "");
|
SessionData.setActiveDisplayProfile(compositor, "");
|
||||||
backendWriteOutputsConfig(allOutputs);
|
backendWriteOutputsConfig(allOutputs);
|
||||||
}
|
}
|
||||||
const updated = JSON.parse(JSON.stringify(validatedProfiles));
|
const updated = JSON.parse(JSON.stringify(validatedProfiles));
|
||||||
@@ -774,7 +774,7 @@ Singleton {
|
|||||||
const match = findConfigEntryByFingerprint(data, currentOutputSet, false);
|
const match = findConfigEntryByFingerprint(data, currentOutputSet, false);
|
||||||
if (match) {
|
if (match) {
|
||||||
if (configEntryMatchesLiveLayout(match.entry)) {
|
if (configEntryMatchesLiveLayout(match.entry)) {
|
||||||
SettingsData.setActiveDisplayProfile(CompositorService.compositor, match.entry.id);
|
SessionData.setActiveDisplayProfile(CompositorService.compositor, match.entry.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
applyConfigEntry(match.entry, match.entry.id, "", false);
|
applyConfigEntry(match.entry, match.entry.id, "", false);
|
||||||
@@ -968,7 +968,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initHyprlandSettingsFromConfig(parsedOutputs) {
|
function initHyprlandSettingsFromConfig(parsedOutputs) {
|
||||||
const current = JSON.parse(JSON.stringify(SettingsData.hyprlandOutputSettings));
|
const current = JSON.parse(JSON.stringify(SessionData.hyprlandOutputSettings));
|
||||||
let changed = false;
|
let changed = false;
|
||||||
|
|
||||||
for (const outputName in parsedOutputs) {
|
for (const outputName in parsedOutputs) {
|
||||||
@@ -997,13 +997,13 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
SettingsData.hyprlandOutputSettings = current;
|
SessionData.hyprlandOutputSettings = current;
|
||||||
SettingsData.saveSettings();
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncHyprlandVrrFromConfig(parsedOutputs) {
|
function syncHyprlandVrrFromConfig(parsedOutputs) {
|
||||||
const current = JSON.parse(JSON.stringify(SettingsData.hyprlandOutputSettings));
|
const current = JSON.parse(JSON.stringify(SessionData.hyprlandOutputSettings));
|
||||||
let changed = false;
|
let changed = false;
|
||||||
for (const outputName in parsedOutputs) {
|
for (const outputName in parsedOutputs) {
|
||||||
const settings = parsedOutputs[outputName]?.hyprlandSettings;
|
const settings = parsedOutputs[outputName]?.hyprlandSettings;
|
||||||
@@ -1020,28 +1020,24 @@ Singleton {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
SettingsData.hyprlandOutputSettings = current;
|
SessionData.hyprlandOutputSettings = current;
|
||||||
SettingsData.saveSettings();
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncNiriVrrFromConfig(parsedOutputs) {
|
function syncNiriVrrFromConfig(parsedOutputs) {
|
||||||
let changed = false;
|
|
||||||
for (const outputName in parsedOutputs) {
|
for (const outputName in parsedOutputs) {
|
||||||
const output = parsedOutputs[outputName];
|
const output = parsedOutputs[outputName];
|
||||||
const current = SettingsData.getNiriOutputSetting(outputName, "vrrOnDemand", false);
|
const current = SessionData.getNiriOutputSetting(outputName, "vrrOnDemand", false);
|
||||||
const fromConfig = output.vrr_on_demand ?? false;
|
const fromConfig = output.vrr_on_demand ?? false;
|
||||||
if (current === fromConfig)
|
if (current === fromConfig)
|
||||||
continue;
|
continue;
|
||||||
SettingsData.setNiriOutputSetting(outputName, "vrrOnDemand", fromConfig || undefined);
|
SessionData.setNiriOutputSetting(outputName, "vrrOnDemand", fromConfig || undefined);
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
if (changed)
|
|
||||||
SettingsData.saveSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncHyprlandDisabledFromConfig(parsedOutputs) {
|
function syncHyprlandDisabledFromConfig(parsedOutputs) {
|
||||||
const current = JSON.parse(JSON.stringify(SettingsData.hyprlandOutputSettings));
|
const current = JSON.parse(JSON.stringify(SessionData.hyprlandOutputSettings));
|
||||||
let changed = false;
|
let changed = false;
|
||||||
for (const outputName in parsedOutputs) {
|
for (const outputName in parsedOutputs) {
|
||||||
const settings = parsedOutputs[outputName]?.hyprlandSettings;
|
const settings = parsedOutputs[outputName]?.hyprlandSettings;
|
||||||
@@ -1058,24 +1054,20 @@ Singleton {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
SettingsData.hyprlandOutputSettings = current;
|
SessionData.hyprlandOutputSettings = current;
|
||||||
SettingsData.saveSettings();
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncNiriDisabledFromConfig(parsedOutputs) {
|
function syncNiriDisabledFromConfig(parsedOutputs) {
|
||||||
let changed = false;
|
|
||||||
for (const outputName in parsedOutputs) {
|
for (const outputName in parsedOutputs) {
|
||||||
const output = parsedOutputs[outputName];
|
const output = parsedOutputs[outputName];
|
||||||
const fromConfig = output.disabled ?? false;
|
const fromConfig = output.disabled ?? false;
|
||||||
const current = SettingsData.getNiriOutputSetting(outputName, "disabled", false);
|
const current = SessionData.getNiriOutputSetting(outputName, "disabled", false);
|
||||||
if (current === fromConfig)
|
if (current === fromConfig)
|
||||||
continue;
|
continue;
|
||||||
SettingsData.setNiriOutputSetting(outputName, "disabled", fromConfig || undefined);
|
SessionData.setNiriOutputSetting(outputName, "disabled", fromConfig || undefined);
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
if (changed)
|
|
||||||
SettingsData.saveSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterDisconnectedOnly(parsedOutputs) {
|
function filterDisconnectedOnly(parsedOutputs) {
|
||||||
@@ -1965,7 +1957,7 @@ Singleton {
|
|||||||
const pending = pendingNiriChanges[identifier];
|
const pending = pendingNiriChanges[identifier];
|
||||||
if (pending && pending[key] !== undefined)
|
if (pending && pending[key] !== undefined)
|
||||||
return pending[key];
|
return pending[key];
|
||||||
return SettingsData.getNiriOutputSetting(identifier, key, defaultValue);
|
return SessionData.getNiriOutputSetting(identifier, key, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNiriSetting(output, outputName, key, value) {
|
function setNiriSetting(output, outputName, key, value) {
|
||||||
@@ -1983,7 +1975,7 @@ Singleton {
|
|||||||
function initOriginalNiriSettings() {
|
function initOriginalNiriSettings() {
|
||||||
if (originalNiriSettings)
|
if (originalNiriSettings)
|
||||||
return;
|
return;
|
||||||
originalNiriSettings = JSON.parse(JSON.stringify(SettingsData.niriOutputSettings));
|
originalNiriSettings = JSON.parse(JSON.stringify(SessionData.niriOutputSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHyprlandOutputIdentifier(output, outputName) {
|
function getHyprlandOutputIdentifier(output, outputName) {
|
||||||
@@ -2001,7 +1993,7 @@ Singleton {
|
|||||||
const val = pending[key];
|
const val = pending[key];
|
||||||
return (val !== null && val !== undefined) ? val : defaultValue;
|
return (val !== null && val !== undefined) ? val : defaultValue;
|
||||||
}
|
}
|
||||||
return SettingsData.getHyprlandOutputSetting(identifier, key, defaultValue);
|
return SessionData.getHyprlandOutputSetting(identifier, key, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHyprlandSetting(output, outputName, key, value) {
|
function setHyprlandSetting(output, outputName, key, value) {
|
||||||
@@ -2019,7 +2011,7 @@ Singleton {
|
|||||||
function initOriginalHyprlandSettings() {
|
function initOriginalHyprlandSettings() {
|
||||||
if (originalHyprlandSettings)
|
if (originalHyprlandSettings)
|
||||||
return;
|
return;
|
||||||
originalHyprlandSettings = JSON.parse(JSON.stringify(SettingsData.hyprlandOutputSettings));
|
originalHyprlandSettings = JSON.parse(JSON.stringify(SessionData.hyprlandOutputSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
function initOriginalOutputs() {
|
function initOriginalOutputs() {
|
||||||
@@ -2259,7 +2251,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildMergedNiriSettings() {
|
function buildMergedNiriSettings() {
|
||||||
const merged = JSON.parse(JSON.stringify(SettingsData.niriOutputSettings));
|
const merged = JSON.parse(JSON.stringify(SessionData.niriOutputSettings));
|
||||||
for (const outputId in pendingNiriChanges) {
|
for (const outputId in pendingNiriChanges) {
|
||||||
if (!merged[outputId])
|
if (!merged[outputId])
|
||||||
merged[outputId] = {};
|
merged[outputId] = {};
|
||||||
@@ -2278,20 +2270,20 @@ Singleton {
|
|||||||
function commitNiriSettingsChanges() {
|
function commitNiriSettingsChanges() {
|
||||||
for (const outputId in pendingNiriChanges) {
|
for (const outputId in pendingNiriChanges) {
|
||||||
for (const key in pendingNiriChanges[outputId]) {
|
for (const key in pendingNiriChanges[outputId]) {
|
||||||
SettingsData.setNiriOutputSetting(outputId, key, pendingNiriChanges[outputId][key]);
|
SessionData.setNiriOutputSetting(outputId, key, pendingNiriChanges[outputId][key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear stale disabled from SettingsData so NiriService reads clean state
|
// Clear stale disabled from SettingsData so NiriService reads clean state
|
||||||
if (Object.keys(outputs).length <= 1) {
|
if (Object.keys(outputs).length <= 1) {
|
||||||
for (const id in SettingsData.niriOutputSettings) {
|
for (const id in SessionData.niriOutputSettings) {
|
||||||
if (SettingsData.niriOutputSettings[id]?.disabled)
|
if (SessionData.niriOutputSettings[id]?.disabled)
|
||||||
SettingsData.setNiriOutputSetting(id, "disabled", null);
|
SessionData.setNiriOutputSetting(id, "disabled", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMergedHyprlandSettings() {
|
function buildMergedHyprlandSettings() {
|
||||||
const merged = JSON.parse(JSON.stringify(SettingsData.hyprlandOutputSettings));
|
const merged = JSON.parse(JSON.stringify(SessionData.hyprlandOutputSettings));
|
||||||
for (const outputId in pendingHyprlandChanges) {
|
for (const outputId in pendingHyprlandChanges) {
|
||||||
if (!merged[outputId])
|
if (!merged[outputId])
|
||||||
merged[outputId] = {};
|
merged[outputId] = {};
|
||||||
@@ -2316,16 +2308,16 @@ Singleton {
|
|||||||
for (const key in pendingHyprlandChanges[outputId]) {
|
for (const key in pendingHyprlandChanges[outputId]) {
|
||||||
const val = pendingHyprlandChanges[outputId][key];
|
const val = pendingHyprlandChanges[outputId][key];
|
||||||
if (val === null || val === undefined)
|
if (val === null || val === undefined)
|
||||||
SettingsData.removeHyprlandOutputSetting(outputId, key);
|
SessionData.removeHyprlandOutputSetting(outputId, key);
|
||||||
else
|
else
|
||||||
SettingsData.setHyprlandOutputSetting(outputId, key, val);
|
SessionData.setHyprlandOutputSetting(outputId, key, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear stale disabled from SettingsData so HyprlandService reads clean state
|
// Clear stale disabled from SettingsData so HyprlandService reads clean state
|
||||||
if (Object.keys(outputs).length <= 1) {
|
if (Object.keys(outputs).length <= 1) {
|
||||||
for (const id in SettingsData.hyprlandOutputSettings) {
|
for (const id in SessionData.hyprlandOutputSettings) {
|
||||||
if (SettingsData.hyprlandOutputSettings[id]?.disabled)
|
if (SessionData.hyprlandOutputSettings[id]?.disabled)
|
||||||
SettingsData.removeHyprlandOutputSetting(id, "disabled");
|
SessionData.removeHyprlandOutputSetting(id, "disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2372,13 +2364,13 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hadNiriChanges) {
|
if (hadNiriChanges) {
|
||||||
SettingsData.niriOutputSettings = JSON.parse(JSON.stringify(originalNiriSettings));
|
SessionData.niriOutputSettings = JSON.parse(JSON.stringify(originalNiriSettings));
|
||||||
SettingsData.saveSettings();
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hadHyprlandChanges) {
|
if (hadHyprlandChanges) {
|
||||||
SettingsData.hyprlandOutputSettings = JSON.parse(JSON.stringify(originalHyprlandSettings));
|
SessionData.hyprlandOutputSettings = JSON.parse(JSON.stringify(originalHyprlandSettings));
|
||||||
SettingsData.saveSettings();
|
SessionData.saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingHyprlandChanges = {};
|
pendingHyprlandChanges = {};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Item {
|
|||||||
LayoutMirroring.childrenInherit: true
|
LayoutMirroring.childrenInherit: true
|
||||||
|
|
||||||
property string selectedProfileId: {
|
property string selectedProfileId: {
|
||||||
const id = SettingsData.activeDisplayProfile[CompositorService.compositor] || "";
|
const id = SessionData.activeDisplayProfile[CompositorService.compositor] || "";
|
||||||
if (!SettingsData.displayProfileAutoSelect) {
|
if (!SettingsData.displayProfileAutoSelect) {
|
||||||
const profile = DisplayConfigState.validatedProfiles[id];
|
const profile = DisplayConfigState.validatedProfiles[id];
|
||||||
if (profile && profile.name === "")
|
if (profile && profile.name === "")
|
||||||
@@ -169,7 +169,7 @@ Item {
|
|||||||
onToggled: checked => {
|
onToggled: checked => {
|
||||||
SettingsData.displayProfileAutoSelect = checked;
|
SettingsData.displayProfileAutoSelect = checked;
|
||||||
if (!checked)
|
if (!checked)
|
||||||
SettingsData.setActiveDisplayProfile(CompositorService.compositor, "");
|
SessionData.setActiveDisplayProfile(CompositorService.compositor, "");
|
||||||
SettingsData.saveSettings();
|
SettingsData.saveSettings();
|
||||||
if (checked)
|
if (checked)
|
||||||
DisplayConfigState.applyAutoConfig();
|
DisplayConfigState.applyAutoConfig();
|
||||||
|
|||||||
@@ -714,7 +714,7 @@ Item {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: syncPendingPill
|
id: syncPendingPill
|
||||||
|
|
||||||
readonly property bool shown: SettingsData.greeterSyncPending && root.greeterInstalled
|
readonly property bool shown: SessionData.greeterSyncPending && root.greeterInstalled
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ Singleton {
|
|||||||
|
|
||||||
function applyWlrModeOverrides(modeOverrides, callback) {
|
function applyWlrModeOverrides(modeOverrides, callback) {
|
||||||
if (CompositorService.isHyprland) {
|
if (CompositorService.isHyprland) {
|
||||||
HyprlandService.generateOutputsConfig(buildWlrOutputsData(modeOverrides), SettingsData.hyprlandOutputSettings, callback);
|
HyprlandService.generateOutputsConfig(buildWlrOutputsData(modeOverrides), SessionData.hyprlandOutputSettings, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ Singleton {
|
|||||||
|
|
||||||
function findActiveProfileMode(outputName, output) {
|
function findActiveProfileMode(outputName, output) {
|
||||||
const compositor = CompositorService.compositor;
|
const compositor = CompositorService.compositor;
|
||||||
const profileModes = SettingsData.activeDisplayProfileModes?.[compositor] || {};
|
const profileModes = SessionData.activeDisplayProfileModes?.[compositor] || {};
|
||||||
if (Object.keys(profileModes).length === 0)
|
if (Object.keys(profileModes).length === 0)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ Singleton {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = hyprlandSettings || SettingsData.hyprlandOutputSettings;
|
const settings = hyprlandSettings || SessionData.hyprlandOutputSettings;
|
||||||
let lines = ["-- Auto-generated by DMS — do not edit manually", ""];
|
let lines = ["-- Auto-generated by DMS — do not edit manually", ""];
|
||||||
|
|
||||||
for (const outputName in outputsData) {
|
for (const outputName in outputsData) {
|
||||||
|
|||||||
@@ -1446,7 +1446,7 @@ window-rule {
|
|||||||
const identifier = getOutputIdentifier(output, outputName);
|
const identifier = getOutputIdentifier(output, outputName);
|
||||||
if (niriSettings)
|
if (niriSettings)
|
||||||
return niriSettings[identifier] || niriSettings[outputName] || {};
|
return niriSettings[identifier] || niriSettings[outputName] || {};
|
||||||
return SettingsData.getNiriOutputSettings(identifier);
|
return SessionData.getNiriOutputSettings(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformToNiri(transform) {
|
function transformToNiri(transform) {
|
||||||
|
|||||||
Reference in New Issue
Block a user