1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-17 08:35:21 -04:00

Compare commits

...

6 Commits

Author SHA1 Message Date
bbedward 056576fbe7 core: execute quickshell IPC with pid 2026-03-24 10:45:53 -04:00
bbedward d28a5bdf7f widgets: convert DankButtonGroup to Row instead of Flow 2026-03-24 10:45:49 -04:00
bbedward f62ea119f7 popout: avoid calling close on bad reference 2026-03-24 10:45:44 -04:00
bbedward a1f9b98727 wallpaper: updatesEnabled set on screen changes 2026-03-24 10:45:37 -04:00
bbedward b9c8914d46 cli/notify: append file:// prefix for --file arguments
fixes #1962
2026-03-24 10:45:28 -04:00
İlkecan Bozdoğan 8697840d46 nix: add package option for dms-shell (#1864)
... to make it configurable.
2026-03-24 10:44:51 -04:00
13 changed files with 149 additions and 28 deletions
+2 -3
View File
@@ -64,9 +64,8 @@ var killCmd = &cobra.Command{
} }
var ipcCmd = &cobra.Command{ var ipcCmd = &cobra.Command{
Use: "ipc [target] [function] [args...]", Use: "ipc [target] [function] [args...]",
Short: "Send IPC commands to running DMS shell", Short: "Send IPC commands to running DMS shell",
PreRunE: findConfig,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
_ = findConfig(cmd, args) _ = findConfig(cmd, args)
return getShellIPCCompletions(args, toComplete), cobra.ShellCompDirectiveNoFileComp return getShellIPCCompletions(args, toComplete), cobra.ShellCompDirectiveNoFileComp
+51 -3
View File
@@ -616,6 +616,43 @@ func getShellIPCCompletions(args []string, _ string) []string {
return nil return nil
} }
func getFirstDMSPID() (int, bool) {
dir := getRuntimeDir()
entries, err := os.ReadDir(dir)
if err != nil {
return 0, false
}
for _, entry := range entries {
if !strings.HasPrefix(entry.Name(), "danklinux-") || !strings.HasSuffix(entry.Name(), ".pid") {
continue
}
data, err := os.ReadFile(filepath.Join(dir, entry.Name()))
if err != nil {
continue
}
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
if err != nil {
continue
}
proc, err := os.FindProcess(pid)
if err != nil {
continue
}
if proc.Signal(syscall.Signal(0)) != nil {
continue
}
return pid, true
}
return 0, false
}
func runShellIPCCommand(args []string) { func runShellIPCCommand(args []string) {
if len(args) == 0 { if len(args) == 0 {
printIPCHelp() printIPCHelp()
@@ -627,10 +664,21 @@ func runShellIPCCommand(args []string) {
} }
cmdArgs := []string{"ipc"} cmdArgs := []string{"ipc"}
if qsHasAnyDisplay() {
cmdArgs = append(cmdArgs, "--any-display") switch pid, ok := getFirstDMSPID(); {
case ok:
cmdArgs = append(cmdArgs, "--pid", strconv.Itoa(pid))
default:
if err := findConfig(nil, nil); err != nil {
log.Fatalf("Error finding config: %v", err)
}
// ! TODO - remove check when QS 0.3 is released
if qsHasAnyDisplay() {
cmdArgs = append(cmdArgs, "--any-display")
}
cmdArgs = append(cmdArgs, "-p", configPath)
} }
cmdArgs = append(cmdArgs, "-p", configPath)
cmdArgs = append(cmdArgs, args...) cmdArgs = append(cmdArgs, args...)
cmd := exec.Command("qs", cmdArgs...) cmd := exec.Command("qs", cmdArgs...)
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
+6 -1
View File
@@ -6,6 +6,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings"
"syscall" "syscall"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
@@ -59,7 +60,11 @@ func Send(n Notification) error {
hints := map[string]dbus.Variant{} hints := map[string]dbus.Variant{}
if n.FilePath != "" { if n.FilePath != "" {
hints["image_path"] = dbus.MakeVariant(n.FilePath) imgPath := n.FilePath
if !strings.HasPrefix(imgPath, "file://") {
imgPath = "file://" + imgPath
}
hints["image_path"] = dbus.MakeVariant(imgPath)
} }
obj := conn.Object(notifyDest, notifyPath) obj := conn.Object(notifyDest, notifyPath)
+1 -1
View File
@@ -13,7 +13,7 @@ func NewManager(display wlclient.WaylandDisplay) (*Manager, error) {
m := &Manager{ m := &Manager{
display: display, display: display,
ctx: display.Context(), ctx: display.Context(),
cmdq: make(chan cmd, 128), cmdq: make(chan cmd, 512),
stopChan: make(chan struct{}), stopChan: make(chan struct{}),
dirty: make(chan struct{}, 1), dirty: make(chan struct{}, 1),
fatalError: make(chan error, 1), fatalError: make(chan error, 1),
+1 -2
View File
@@ -2,7 +2,6 @@
config, config,
lib, lib,
pkgs, pkgs,
dmsPkgs,
... ...
}: }:
let let
@@ -10,7 +9,7 @@ let
in in
{ {
packages = [ packages = [
dmsPkgs.dms-shell cfg.package
] ]
++ lib.optional cfg.enableSystemMonitoring cfg.dgop.package ++ lib.optional cfg.enableSystemMonitoring cfg.dgop.package
++ lib.optionals cfg.enableVPN [ ++ lib.optionals cfg.enableVPN [
+18 -2
View File
@@ -8,6 +8,7 @@
let let
inherit (lib) types; inherit (lib) types;
cfg = config.programs.dank-material-shell.greeter; cfg = config.programs.dank-material-shell.greeter;
cfgDms = config.programs.dank-material-shell;
inherit (config.services.greetd.settings.default_session) user; inherit (config.services.greetd.settings.default_session) user;
@@ -30,13 +31,13 @@ let
lib.escapeShellArgs ( lib.escapeShellArgs (
[ [
"sh" "sh"
"${../../quickshell/Modules/Greetd/assets/dms-greeter}" "${cfg.package}/share/quickshell/dms/Modules/Greetd/assets/dms-greeter"
"--cache-dir" "--cache-dir"
cacheDir cacheDir
"--command" "--command"
cfg.compositor.name cfg.compositor.name
"-p" "-p"
"${dmsPkgs.dms-shell}/share/quickshell/dms" "${cfg.package}/share/quickshell/dms"
] ]
++ lib.optionals (cfg.compositor.customConfig != "") [ ++ lib.optionals (cfg.compositor.customConfig != "") [
"-C" "-C"
@@ -66,6 +67,21 @@ in
options.programs.dank-material-shell.greeter = { options.programs.dank-material-shell.greeter = {
enable = lib.mkEnableOption "DankMaterialShell greeter"; enable = lib.mkEnableOption "DankMaterialShell greeter";
package = lib.mkOption {
type = types.package;
default = if cfgDms.enable or false then cfgDms.package else dmsPkgs.dms-shell;
defaultText = lib.literalExpression ''
if config.programs.dank-material-shell.enable
then config.programs.dank-material-shell.package
else built from source;
'';
description = ''
The DankMaterialShell package to use for the greeter.
Defaults to the package from `programs.dank-material-shell` if it is enabled,
otherwise defaults to building from source.
'';
};
compositor.name = lib.mkOption { compositor.name = lib.mkOption {
type = types.enum [ type = types.enum [
"niri" "niri"
+1 -3
View File
@@ -2,7 +2,6 @@
config, config,
pkgs, pkgs,
lib, lib,
dmsPkgs,
... ...
}@args: }@args:
let let
@@ -13,7 +12,6 @@ let
config config
pkgs pkgs
lib lib
dmsPkgs
; ;
}; };
hasPluginSettings = lib.any (plugin: plugin.settings != { }) ( hasPluginSettings = lib.any (plugin: plugin.settings != { }) (
@@ -96,7 +94,7 @@ in
}; };
Service = { Service = {
ExecStart = lib.getExe dmsPkgs.dms-shell + " run --session"; ExecStart = lib.getExe cfg.package + " run --session";
Restart = "on-failure"; Restart = "on-failure";
}; };
+1 -3
View File
@@ -2,7 +2,6 @@
config, config,
pkgs, pkgs,
lib, lib,
dmsPkgs,
... ...
}@args: }@args:
let let
@@ -12,7 +11,6 @@ let
config config
pkgs pkgs
lib lib
dmsPkgs
; ;
}; };
in in
@@ -36,7 +34,7 @@ in
restartIfChanged = cfg.systemd.restartIfChanged; restartIfChanged = cfg.systemd.restartIfChanged;
serviceConfig = { serviceConfig = {
ExecStart = lib.getExe dmsPkgs.dms-shell + " run --session"; ExecStart = lib.getExe cfg.package + " run --session";
Restart = "on-failure"; Restart = "on-failure";
}; };
}; };
+3
View File
@@ -26,6 +26,9 @@ in
options.programs.dank-material-shell = { options.programs.dank-material-shell = {
enable = lib.mkEnableOption "DankMaterialShell"; enable = lib.mkEnableOption "DankMaterialShell";
package = lib.mkPackageOption dmsPkgs "dms-shell" {
extraDescription = "The DankMaterialShell package to use (defaults to be built from source)";
};
systemd = { systemd = {
enable = lib.mkEnableOption "DankMaterialShell systemd startup"; enable = lib.mkEnableOption "DankMaterialShell systemd startup";
+20 -9
View File
@@ -1,4 +1,5 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import QtQuick import QtQuick
@@ -13,21 +14,31 @@ Singleton {
signal popoutChanged signal popoutChanged
function _closePopout(popout) { function _closePopout(popout) {
switch (true) { try {
case popout.dashVisible !== undefined: switch (true) {
popout.dashVisible = false; case popout.dashVisible !== undefined:
popout.dashVisible = false;
return;
case popout.notificationHistoryVisible !== undefined:
popout.notificationHistoryVisible = false;
return;
default:
if (typeof popout.close !== "function")
return;
popout.close();
}
} catch (e) {
return; return;
case popout.notificationHistoryVisible !== undefined:
popout.notificationHistoryVisible = false;
return;
default:
popout.close();
} }
} }
function _isStale(popout) { function _isStale(popout) {
try { try {
return !popout || !("shouldBeVisible" in popout); if (!popout || !("shouldBeVisible" in popout))
return true;
if (!popout.screen)
return true;
return false;
} catch (e) { } catch (e) {
return true; return true;
} }
@@ -107,6 +107,26 @@ Variants {
} }
} }
Connections {
target: blurWallpaperWindow
function onWidthChanged() {
root._renderSettling = true;
renderSettleTimer.restart();
}
function onHeightChanged() {
root._renderSettling = true;
renderSettleTimer.restart();
}
}
Connections {
target: Quickshell
function onScreensChanged() {
root._renderSettling = true;
renderSettleTimer.restart();
}
}
Timer { Timer {
id: renderSettleTimer id: renderSettleTimer
interval: 1000 interval: 1000
@@ -108,10 +108,32 @@ Variants {
} }
} }
Connections {
target: wallpaperWindow
function onWidthChanged() {
root._renderSettling = true;
renderSettleTimer.restart();
}
function onHeightChanged() {
root._renderSettling = true;
renderSettleTimer.restart();
}
}
Connections {
target: Quickshell
function onScreensChanged() {
root._renderSettling = true;
renderSettleTimer.restart();
}
}
Connections { Connections {
target: NiriService target: NiriService
function onDisplayScalesChanged() { function onDisplayScalesChanged() {
root._recheckScreenScale(); root._recheckScreenScale();
root._renderSettling = true;
renderSettleTimer.restart();
} }
} }
@@ -119,6 +141,8 @@ Variants {
target: WlrOutputService target: WlrOutputService
function onWlrOutputAvailableChanged() { function onWlrOutputAvailableChanged() {
root._recheckScreenScale(); root._recheckScreenScale();
root._renderSettling = true;
renderSettleTimer.restart();
} }
} }
+1 -1
View File
@@ -3,7 +3,7 @@ import Quickshell
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
Flow { Row {
id: root id: root
property var model: [] property var model: []