mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3420d2be93 |
@@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=DMS Status Notifier Watcher (early tray)
|
||||||
|
# The tray watcher starts in parallel with the compositor and owns org.kde.StatusNotifierWatcher before
|
||||||
|
# graphical-session.target, i.e. before any XDG autostart app launches.
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
Before=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=dbus
|
||||||
|
BusName=org.kde.StatusNotifierWatcher
|
||||||
|
ExecStart=/usr/bin/dms tray-watcher
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=1
|
||||||
|
Slice=session.slice
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=graphical-session.target
|
||||||
@@ -774,5 +774,6 @@ func getCommonCommands() []*cobra.Command {
|
|||||||
trashCmd,
|
trashCmd,
|
||||||
systemCmd,
|
systemCmd,
|
||||||
switchUserCmd,
|
switchUserCmd,
|
||||||
|
trayWatcherCmd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/traywatcher"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var trayWatcherCmd = &cobra.Command{
|
||||||
|
Use: "tray-watcher",
|
||||||
|
Short: "Run a minimal StatusNotifierWatcher for early tray registration",
|
||||||
|
Long: `Run a minimal org.kde.StatusNotifierWatcher daemon.
|
||||||
|
|
||||||
|
Started early in the session (Before=graphical-session.target via
|
||||||
|
dms-tray-watcher.service), it lets tray apps launched by XDG autostart
|
||||||
|
register their items before the shell finishes loading, and keeps them
|
||||||
|
registered across shell restarts. The shell's tray host picks items up from
|
||||||
|
this watcher; if it is not running, the shell's built-in watcher takes over.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := traywatcher.Run(); err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -880,8 +880,9 @@ func (cd *ConfigDeployer) transformNiriConfigForNonSystemd(config, terminalComma
|
|||||||
|
|
||||||
config = regexp.MustCompile(`environment \{[^}]*\}`).ReplaceAllString(config, envVars)
|
config = regexp.MustCompile(`environment \{[^}]*\}`).ReplaceAllString(config, envVars)
|
||||||
|
|
||||||
spawnDms := `spawn-at-startup "dms" "run"`
|
// Watcher spawns first so it owns the SNI name before dms/tray apps start.
|
||||||
if !strings.Contains(config, spawnDms) {
|
spawnDms := "spawn-at-startup \"dms\" \"tray-watcher\"\nspawn-at-startup \"dms\" \"run\""
|
||||||
|
if !strings.Contains(config, `spawn-at-startup "dms" "run"`) {
|
||||||
// Insert spawn-at-startup for dms after the environment block
|
// Insert spawn-at-startup for dms after the environment block
|
||||||
envBlockEnd := regexp.MustCompile(`environment \{[^}]*\}`)
|
envBlockEnd := regexp.MustCompile(`environment \{[^}]*\}`)
|
||||||
if loc := envBlockEnd.FindStringIndex(config); loc != nil {
|
if loc := envBlockEnd.FindStringIndex(config); loc != nil {
|
||||||
|
|||||||
@@ -520,9 +520,21 @@ func TestHyprlandConfigStructure(t *testing.T) {
|
|||||||
assert.Contains(t, HyprlandLuaConfig, "input =")
|
assert.Contains(t, HyprlandLuaConfig, "input =")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In non-systemd mode dms is launched from the compositor config, so the tray
|
||||||
|
// watcher must be launched there too, before dms, to own the SNI name first.
|
||||||
|
func TestNonSystemdLaunchesTrayWatcherBeforeShell(t *testing.T) {
|
||||||
|
hypr := transformHyprlandLuaForNonSystemd(HyprlandLuaConfig, "ghostty")
|
||||||
|
assert.Contains(t, hypr, "hl.exec_cmd(\"dms tray-watcher\")\n\thl.exec_cmd(\"dms run\")")
|
||||||
|
|
||||||
|
niri := (&ConfigDeployer{}).transformNiriConfigForNonSystemd(NiriConfig, "ghostty")
|
||||||
|
assert.Contains(t, niri, "spawn-at-startup \"dms\" \"tray-watcher\"\nspawn-at-startup \"dms\" \"run\"")
|
||||||
|
}
|
||||||
|
|
||||||
func TestMangoConfigStructure(t *testing.T) {
|
func TestMangoConfigStructure(t *testing.T) {
|
||||||
assert.Contains(t, MangoConfig, "exec-once=dms run")
|
assert.Contains(t, MangoConfig, "exec-once=dms run")
|
||||||
assert.NotContains(t, MangoConfig, "exec_once=dms run")
|
assert.NotContains(t, MangoConfig, "exec_once=dms run")
|
||||||
|
// Tray watcher must start before the shell so it owns the SNI name first.
|
||||||
|
assert.Contains(t, MangoConfig, "exec-once=dms tray-watcher\nexec-once=dms run")
|
||||||
assert.Contains(t, MangoConfig, "source=./dms/binds.conf")
|
assert.Contains(t, MangoConfig, "source=./dms/binds.conf")
|
||||||
assert.Contains(t, MangoBindsConfig, "bind=SUPER,H,focusdir,left")
|
assert.Contains(t, MangoBindsConfig, "bind=SUPER,H,focusdir,left")
|
||||||
assert.Contains(t, MangoBindsConfig, "bind=SUPER,J,focusdir,down")
|
assert.Contains(t, MangoBindsConfig, "bind=SUPER,J,focusdir,down")
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ env=XDG_SESSION_TYPE,wayland
|
|||||||
|
|
||||||
# exec-once runs only at startup. Do NOT use exec= for the shell: mango re-runs
|
# exec-once runs only at startup. Do NOT use exec= for the shell: mango re-runs
|
||||||
# every exec= on each config reload, and DMS reloads the config, which would
|
# every exec= on each config reload, and DMS reloads the config, which would
|
||||||
# spawn a new shell on every reload.
|
# spawn a new shell on every reload. The tray watcher starts first so it owns
|
||||||
|
# the SNI name before dms and the tray apps come up.
|
||||||
|
exec-once=dms tray-watcher
|
||||||
exec-once=dms run
|
exec-once=dms run
|
||||||
|
|
||||||
source=./dms/colors.conf
|
source=./dms/colors.conf
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ func transformHyprlandLuaForNonSystemd(config, terminalCommand string) string {
|
|||||||
`hl.env("QT_QPA_PLATFORMTHEME_QT6", "gtk3")` + "\n" +
|
`hl.env("QT_QPA_PLATFORMTHEME_QT6", "gtk3")` + "\n" +
|
||||||
fmt.Sprintf(`hl.env("TERMINAL", %s)`, strconv.Quote(terminalCommand)) + "\n\n" +
|
fmt.Sprintf(`hl.env("TERMINAL", %s)`, strconv.Quote(terminalCommand)) + "\n\n" +
|
||||||
`hl.on("hyprland.start", function()` + "\n" +
|
`hl.on("hyprland.start", function()` + "\n" +
|
||||||
|
` hl.exec_cmd("dms tray-watcher")` + "\n" +
|
||||||
` hl.exec_cmd("dms run")` + "\n" +
|
` hl.exec_cmd("dms run")` + "\n" +
|
||||||
`end)` + "\n" +
|
`end)` + "\n" +
|
||||||
hyprlandStartupEnd
|
hyprlandStartupEnd
|
||||||
|
|||||||
@@ -587,13 +587,15 @@ TERMINAL=%s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseDistribution) EnableDMSService(ctx context.Context, wm deps.WindowManager) error {
|
func (b *BaseDistribution) EnableDMSService(ctx context.Context, wm deps.WindowManager) error {
|
||||||
|
// Pull in the tray watcher alongside dms; its Before=graphical-session.target
|
||||||
|
// ordering makes it claim the SNI name before autostart apps start.
|
||||||
switch wm {
|
switch wm {
|
||||||
case deps.WindowManagerNiri:
|
case deps.WindowManagerNiri:
|
||||||
if err := exec.CommandContext(ctx, "systemctl", "--user", "add-wants", "niri.service", "dms").Run(); err != nil {
|
if err := exec.CommandContext(ctx, "systemctl", "--user", "add-wants", "niri.service", "dms", "dms-tray-watcher").Run(); err != nil {
|
||||||
b.log("Warning: failed to add dms as a want for niri.service")
|
b.log("Warning: failed to add dms as a want for niri.service")
|
||||||
}
|
}
|
||||||
case deps.WindowManagerHyprland:
|
case deps.WindowManagerHyprland:
|
||||||
if err := exec.CommandContext(ctx, "systemctl", "--user", "add-wants", "hyprland-session.target", "dms").Run(); err != nil {
|
if err := exec.CommandContext(ctx, "systemctl", "--user", "add-wants", "hyprland-session.target", "dms", "dms-tray-watcher").Run(); err != nil {
|
||||||
b.log("Warning: failed to add dms as a want for hyprland-session.target")
|
b.log("Warning: failed to add dms as a want for hyprland-session.target")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
// Package traywatcher implements a minimal org.kde.StatusNotifierWatcher that
|
||||||
|
// claims the SNI name early in the session so autostart tray apps can register
|
||||||
|
// before the shell finishes loading. See docs/TRAY_WATCHER.md.
|
||||||
|
package traywatcher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
"github.com/godbus/dbus/v5/introspect"
|
||||||
|
"github.com/godbus/dbus/v5/prop"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
busName = "org.kde.StatusNotifierWatcher"
|
||||||
|
objPath = dbus.ObjectPath("/StatusNotifierWatcher")
|
||||||
|
iface = "org.kde.StatusNotifierWatcher"
|
||||||
|
)
|
||||||
|
|
||||||
|
const introXML = `<node>
|
||||||
|
<interface name="org.kde.StatusNotifierWatcher">
|
||||||
|
<method name="RegisterStatusNotifierItem">
|
||||||
|
<arg type="s" direction="in" name="service"/>
|
||||||
|
</method>
|
||||||
|
<method name="RegisterStatusNotifierHost">
|
||||||
|
<arg type="s" direction="in" name="service"/>
|
||||||
|
</method>
|
||||||
|
<property name="RegisteredStatusNotifierItems" type="as" access="read"/>
|
||||||
|
<property name="IsStatusNotifierHostRegistered" type="b" access="read"/>
|
||||||
|
<property name="ProtocolVersion" type="i" access="read"/>
|
||||||
|
<signal name="StatusNotifierItemRegistered">
|
||||||
|
<arg type="s" name="service"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="StatusNotifierItemUnregistered">
|
||||||
|
<arg type="s" name="service"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="StatusNotifierHostRegistered"/>
|
||||||
|
<signal name="StatusNotifierHostUnregistered"/>
|
||||||
|
</interface>
|
||||||
|
` + introspect.IntrospectDataString + prop.IntrospectDataString + `</node>`
|
||||||
|
|
||||||
|
type watcher struct {
|
||||||
|
conn *dbus.Conn
|
||||||
|
props *prop.Properties
|
||||||
|
mu sync.Mutex
|
||||||
|
items map[string]string // item id ("name/path") -> bus name to watch
|
||||||
|
hosts map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watcher) itemListLocked() []string {
|
||||||
|
list := make([]string, 0, len(w.items))
|
||||||
|
for item := range w.items {
|
||||||
|
list = append(list, item)
|
||||||
|
}
|
||||||
|
sort.Strings(list)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watcher) emit(signal string, args ...any) {
|
||||||
|
if err := w.conn.Emit(objPath, iface+"."+signal, args...); err != nil {
|
||||||
|
log.Warnf("failed to emit %s: %v", signal, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clients pass either an object path (item on the caller) or a bus name.
|
||||||
|
func (w *watcher) RegisterStatusNotifierItem(sender dbus.Sender, service string) *dbus.Error {
|
||||||
|
var item, watch string
|
||||||
|
if strings.HasPrefix(service, "/") {
|
||||||
|
item, watch = string(sender)+service, string(sender)
|
||||||
|
} else {
|
||||||
|
item, watch = service+"/StatusNotifierItem", service
|
||||||
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
if _, exists := w.items[item]; exists {
|
||||||
|
w.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w.items[item] = watch
|
||||||
|
list := w.itemListLocked()
|
||||||
|
w.mu.Unlock()
|
||||||
|
|
||||||
|
log.Infof("item registered: %s", item)
|
||||||
|
w.emit("StatusNotifierItemRegistered", item)
|
||||||
|
w.props.SetMust(iface, "RegisteredStatusNotifierItems", list)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watcher) RegisterStatusNotifierHost(sender dbus.Sender, service string) *dbus.Error {
|
||||||
|
watch := string(sender)
|
||||||
|
if service != "" && !strings.HasPrefix(service, "/") {
|
||||||
|
watch = service
|
||||||
|
}
|
||||||
|
|
||||||
|
w.mu.Lock()
|
||||||
|
if w.hosts[watch] {
|
||||||
|
w.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w.hosts[watch] = true
|
||||||
|
w.mu.Unlock()
|
||||||
|
|
||||||
|
log.Infof("host registered: %s", watch)
|
||||||
|
w.emit("StatusNotifierHostRegistered")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watcher) pruneOwner(name string) {
|
||||||
|
w.mu.Lock()
|
||||||
|
var removed []string
|
||||||
|
for item, watch := range w.items {
|
||||||
|
if watch == name {
|
||||||
|
delete(w.items, item)
|
||||||
|
removed = append(removed, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list := w.itemListLocked()
|
||||||
|
hostGone := w.hosts[name]
|
||||||
|
delete(w.hosts, name)
|
||||||
|
w.mu.Unlock()
|
||||||
|
|
||||||
|
for _, item := range removed {
|
||||||
|
log.Infof("item gone: %s", item)
|
||||||
|
w.emit("StatusNotifierItemUnregistered", item)
|
||||||
|
}
|
||||||
|
if len(removed) > 0 {
|
||||||
|
w.props.SetMust(iface, "RegisteredStatusNotifierItems", list)
|
||||||
|
}
|
||||||
|
if hostGone {
|
||||||
|
log.Infof("host gone: %s", name)
|
||||||
|
w.emit("StatusNotifierHostUnregistered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run serves the watcher until the session bus connection closes.
|
||||||
|
func Run() error {
|
||||||
|
conn, err := dbus.ConnectSessionBus()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("connect to session bus: %w", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
w := &watcher{conn: conn, items: map[string]string{}, hosts: map[string]bool{}}
|
||||||
|
|
||||||
|
if err := conn.Export(w, objPath, iface); err != nil {
|
||||||
|
return fmt.Errorf("export watcher: %w", err)
|
||||||
|
}
|
||||||
|
w.props, err = prop.Export(conn, objPath, map[string]map[string]*prop.Prop{
|
||||||
|
iface: {
|
||||||
|
"RegisteredStatusNotifierItems": {Value: []string{}, Emit: prop.EmitTrue},
|
||||||
|
// Always true: libappindicator clients drop the icon if it is false.
|
||||||
|
"IsStatusNotifierHostRegistered": {Value: true, Emit: prop.EmitFalse},
|
||||||
|
"ProtocolVersion": {Value: int32(0), Emit: prop.EmitFalse},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("export properties: %w", err)
|
||||||
|
}
|
||||||
|
if err := conn.Export(introspect.Introspectable(introXML), objPath, "org.freedesktop.DBus.Introspectable"); err != nil {
|
||||||
|
return fmt.Errorf("export introspection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := conn.AddMatchSignal(
|
||||||
|
dbus.WithMatchSender("org.freedesktop.DBus"),
|
||||||
|
dbus.WithMatchInterface("org.freedesktop.DBus"),
|
||||||
|
dbus.WithMatchMember("NameOwnerChanged"),
|
||||||
|
dbus.WithMatchObjectPath("/org/freedesktop/DBus"),
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("match NameOwnerChanged: %w", err)
|
||||||
|
}
|
||||||
|
sigs := make(chan *dbus.Signal, 128)
|
||||||
|
conn.Signal(sigs)
|
||||||
|
|
||||||
|
// No flags: queue for the name and take it when the current owner exits.
|
||||||
|
reply, err := conn.RequestName(busName, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("request %s: %w", busName, err)
|
||||||
|
}
|
||||||
|
if reply == dbus.RequestNameReplyInQueue {
|
||||||
|
log.Infof("name busy, queued for %s", busName)
|
||||||
|
}
|
||||||
|
|
||||||
|
for sig := range sigs {
|
||||||
|
switch sig.Name {
|
||||||
|
case "org.freedesktop.DBus.NameAcquired":
|
||||||
|
if len(sig.Body) == 1 && sig.Body[0] == busName {
|
||||||
|
log.Infof("acquired %s", busName)
|
||||||
|
}
|
||||||
|
case "org.freedesktop.DBus.NameOwnerChanged":
|
||||||
|
if len(sig.Body) != 3 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, _ := sig.Body[0].(string)
|
||||||
|
newOwner, _ := sig.Body[2].(string)
|
||||||
|
if name != busName && newOwner == "" {
|
||||||
|
w.pruneOwner(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("session bus connection closed")
|
||||||
|
}
|
||||||
@@ -72,6 +72,7 @@ override_dh_auto_install:
|
|||||||
if [ -d quickshell ]; then \
|
if [ -d quickshell ]; then \
|
||||||
cp -r quickshell/* debian/dms-git/usr/share/quickshell/dms/; \
|
cp -r quickshell/* debian/dms-git/usr/share/quickshell/dms/; \
|
||||||
install -Dm644 assets/systemd/dms.service debian/dms-git/usr/lib/systemd/user/dms.service; \
|
install -Dm644 assets/systemd/dms.service debian/dms-git/usr/lib/systemd/user/dms.service; \
|
||||||
|
install -Dm644 assets/systemd/dms-tray-watcher.service debian/dms-git/usr/lib/systemd/user/dms-tray-watcher.service; \
|
||||||
install -Dm644 assets/dms-open.desktop debian/dms-git/usr/share/applications/dms-open.desktop; \
|
install -Dm644 assets/dms-open.desktop debian/dms-git/usr/share/applications/dms-open.desktop; \
|
||||||
install -Dm644 assets/com.danklinux.dms.desktop debian/dms-git/usr/share/applications/com.danklinux.dms.desktop; \
|
install -Dm644 assets/com.danklinux.dms.desktop debian/dms-git/usr/share/applications/com.danklinux.dms.desktop; \
|
||||||
install -Dm644 assets/com.danklinux.dms.notepad.desktop debian/dms-git/usr/share/applications/com.danklinux.dms.notepad.desktop; \
|
install -Dm644 assets/com.danklinux.dms.notepad.desktop debian/dms-git/usr/share/applications/com.danklinux.dms.notepad.desktop; \
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ override_dh_auto_install:
|
|||||||
if [ -d DankMaterialShell-$(UPSTREAM_VERSION) ]; then \
|
if [ -d DankMaterialShell-$(UPSTREAM_VERSION) ]; then \
|
||||||
cp -r DankMaterialShell-$(UPSTREAM_VERSION)/quickshell/* debian/dms/usr/share/quickshell/dms/; \
|
cp -r DankMaterialShell-$(UPSTREAM_VERSION)/quickshell/* debian/dms/usr/share/quickshell/dms/; \
|
||||||
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/systemd/dms.service debian/dms/usr/lib/systemd/user/dms.service; \
|
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/systemd/dms.service debian/dms/usr/lib/systemd/user/dms.service; \
|
||||||
|
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/systemd/dms-tray-watcher.service debian/dms/usr/lib/systemd/user/dms-tray-watcher.service; \
|
||||||
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/dms-open.desktop debian/dms/usr/share/applications/dms-open.desktop; \
|
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/dms-open.desktop debian/dms/usr/share/applications/dms-open.desktop; \
|
||||||
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/com.danklinux.dms.desktop debian/dms/usr/share/applications/com.danklinux.dms.desktop; \
|
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/com.danklinux.dms.desktop debian/dms/usr/share/applications/com.danklinux.dms.desktop; \
|
||||||
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/com.danklinux.dms.notepad.desktop debian/dms/usr/share/applications/com.danklinux.dms.notepad.desktop; \
|
install -Dm644 DankMaterialShell-$(UPSTREAM_VERSION)/assets/com.danklinux.dms.notepad.desktop debian/dms/usr/share/applications/com.danklinux.dms.notepad.desktop; \
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ core/bin/${DMS_BINARY} completion fish > %{buildroot}%{_datadir}/fish/vendor_com
|
|||||||
|
|
||||||
# Install systemd user service
|
# Install systemd user service
|
||||||
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
||||||
|
install -Dm644 assets/systemd/dms-tray-watcher.service %{buildroot}%{_userunitdir}/dms-tray-watcher.service
|
||||||
|
|
||||||
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
||||||
install -Dm644 assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
install -Dm644 assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
@@ -145,6 +146,7 @@ pkill -USR1 -x dms >/dev/null 2>&1 || :
|
|||||||
%doc quickshell/README.md
|
%doc quickshell/README.md
|
||||||
%{_datadir}/quickshell/dms/
|
%{_datadir}/quickshell/dms/
|
||||||
%{_userunitdir}/dms.service
|
%{_userunitdir}/dms.service
|
||||||
|
%{_userunitdir}/dms-tray-watcher.service
|
||||||
%{_datadir}/applications/dms-open.desktop
|
%{_datadir}/applications/dms-open.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.desktop
|
%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ install -d %{buildroot}%{_datadir}/fish/vendor_completions.d
|
|||||||
%{_builddir}/dms-cli completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || :
|
%{_builddir}/dms-cli completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || :
|
||||||
|
|
||||||
install -Dm644 %{_builddir}/dms-qml/assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
install -Dm644 %{_builddir}/dms-qml/assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
||||||
|
install -Dm644 %{_builddir}/dms-qml/assets/systemd/dms-tray-watcher.service %{buildroot}%{_userunitdir}/dms-tray-watcher.service
|
||||||
|
|
||||||
install -Dm644 %{_builddir}/dms-qml/assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
install -Dm644 %{_builddir}/dms-qml/assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
||||||
install -Dm644 %{_builddir}/dms-qml/assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
install -Dm644 %{_builddir}/dms-qml/assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
@@ -112,6 +113,7 @@ pkill -USR1 -x dms >/dev/null 2>&1 || :
|
|||||||
%doc README.md CONTRIBUTING.md
|
%doc README.md CONTRIBUTING.md
|
||||||
%{_datadir}/quickshell/dms/
|
%{_datadir}/quickshell/dms/
|
||||||
%{_userunitdir}/dms.service
|
%{_userunitdir}/dms.service
|
||||||
|
%{_userunitdir}/dms-tray-watcher.service
|
||||||
%{_datadir}/applications/dms-open.desktop
|
%{_datadir}/applications/dms-open.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.desktop
|
%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
||||||
|
|||||||
@@ -101,6 +101,24 @@ in
|
|||||||
Install.WantedBy = [ cfg.systemd.target ];
|
Install.WantedBy = [ cfg.systemd.target ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Early SNI watcher so autostart tray apps register before the shell loads.
|
||||||
|
systemd.user.services.dms-tray-watcher = lib.mkIf cfg.systemd.enable {
|
||||||
|
Unit = {
|
||||||
|
Description = "DMS Status Notifier Watcher (early tray)";
|
||||||
|
PartOf = [ cfg.systemd.target ];
|
||||||
|
Before = [ cfg.systemd.target ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
Type = "dbus";
|
||||||
|
BusName = "org.kde.StatusNotifierWatcher";
|
||||||
|
ExecStart = lib.getExe cfg.package + " tray-watcher";
|
||||||
|
Restart = "on-failure";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install.WantedBy = [ cfg.systemd.target ];
|
||||||
|
};
|
||||||
|
|
||||||
xdg.stateFile."DankMaterialShell/session.json" = lib.mkIf (cfg.session != { }) {
|
xdg.stateFile."DankMaterialShell/session.json" = lib.mkIf (cfg.session != { }) {
|
||||||
source = jsonFormat.generate "session.json" cfg.session;
|
source = jsonFormat.generate "session.json" cfg.session;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,6 +39,24 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Early SNI watcher so autostart tray apps register before the shell loads.
|
||||||
|
systemd.user.services.dms-tray-watcher = lib.mkIf cfg.systemd.enable {
|
||||||
|
description = "DMS Status Notifier Watcher (early tray)";
|
||||||
|
path = lib.mkForce [ ];
|
||||||
|
|
||||||
|
partOf = [ cfg.systemd.target ];
|
||||||
|
before = [ cfg.systemd.target ];
|
||||||
|
wantedBy = [ cfg.systemd.target ];
|
||||||
|
restartIfChanged = cfg.systemd.restartIfChanged;
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "dbus";
|
||||||
|
BusName = "org.kde.StatusNotifierWatcher";
|
||||||
|
ExecStart = lib.getExe cfg.package + " tray-watcher";
|
||||||
|
Restart = "on-failure";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ cfg.quickshell.package ] ++ common.packages;
|
environment.systemPackages = [ cfg.quickshell.package ] ++ common.packages;
|
||||||
|
|
||||||
environment.etc = lib.mapAttrs' (name: value: {
|
environment.etc = lib.mapAttrs' (name: value: {
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ install -d %{buildroot}%{_datadir}/fish/vendor_completions.d
|
|||||||
./dms completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || :
|
./dms completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || :
|
||||||
|
|
||||||
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
||||||
|
install -Dm644 assets/systemd/dms-tray-watcher.service %{buildroot}%{_userunitdir}/dms-tray-watcher.service
|
||||||
|
|
||||||
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
||||||
install -Dm644 assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
install -Dm644 assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
@@ -152,6 +153,7 @@ pkill -USR1 -x dms >/dev/null 2>&1 || :
|
|||||||
%dir %{_datadir}/quickshell
|
%dir %{_datadir}/quickshell
|
||||||
%{_datadir}/quickshell/dms/
|
%{_datadir}/quickshell/dms/
|
||||||
%{_userunitdir}/dms.service
|
%{_userunitdir}/dms.service
|
||||||
|
%{_userunitdir}/dms-tray-watcher.service
|
||||||
%{_datadir}/applications/dms-open.desktop
|
%{_datadir}/applications/dms-open.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.desktop
|
%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ install -d %{buildroot}%{_datadir}/fish/vendor_completions.d
|
|||||||
./dms completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || :
|
./dms completion fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/dms.fish || :
|
||||||
|
|
||||||
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
||||||
|
install -Dm644 assets/systemd/dms-tray-watcher.service %{buildroot}%{_userunitdir}/dms-tray-watcher.service
|
||||||
|
|
||||||
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
||||||
install -Dm644 assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
install -Dm644 assets/com.danklinux.dms.desktop %{buildroot}%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
@@ -99,6 +100,7 @@ pkill -USR1 -x dms >/dev/null 2>&1 || :
|
|||||||
%dir %{_datadir}/quickshell
|
%dir %{_datadir}/quickshell
|
||||||
%{_datadir}/quickshell/dms/
|
%{_datadir}/quickshell/dms/
|
||||||
%{_userunitdir}/dms.service
|
%{_userunitdir}/dms.service
|
||||||
|
%{_userunitdir}/dms-tray-watcher.service
|
||||||
%{_datadir}/applications/dms-open.desktop
|
%{_datadir}/applications/dms-open.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.desktop
|
%{_datadir}/applications/com.danklinux.dms.desktop
|
||||||
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
%{_datadir}/applications/com.danklinux.dms.notepad.desktop
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ override_dh_auto_install:
|
|||||||
# Install systemd user service
|
# Install systemd user service
|
||||||
install -Dm644 dms-git-repo/assets/systemd/dms.service \
|
install -Dm644 dms-git-repo/assets/systemd/dms.service \
|
||||||
debian/dms-git/usr/lib/systemd/user/dms.service
|
debian/dms-git/usr/lib/systemd/user/dms.service
|
||||||
|
install -Dm644 dms-git-repo/assets/systemd/dms-tray-watcher.service \
|
||||||
|
debian/dms-git/usr/lib/systemd/user/dms-tray-watcher.service
|
||||||
|
|
||||||
# Install desktop file and icon
|
# Install desktop file and icon
|
||||||
install -Dm644 dms-git-repo/assets/dms-open.desktop \
|
install -Dm644 dms-git-repo/assets/dms-open.desktop \
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ override_dh_auto_install:
|
|||||||
# Install systemd user service (before copying everything else)
|
# Install systemd user service (before copying everything else)
|
||||||
install -Dm644 DankMaterialShell-$(BASE_VERSION)/assets/systemd/dms.service \
|
install -Dm644 DankMaterialShell-$(BASE_VERSION)/assets/systemd/dms.service \
|
||||||
debian/dms/usr/lib/systemd/user/dms.service
|
debian/dms/usr/lib/systemd/user/dms.service
|
||||||
|
install -Dm644 DankMaterialShell-$(BASE_VERSION)/assets/systemd/dms-tray-watcher.service \
|
||||||
|
debian/dms/usr/lib/systemd/user/dms-tray-watcher.service
|
||||||
|
|
||||||
# Install desktop file and icon
|
# Install desktop file and icon
|
||||||
install -Dm644 DankMaterialShell-$(BASE_VERSION)/assets/dms-open.desktop \
|
install -Dm644 DankMaterialShell-$(BASE_VERSION)/assets/dms-open.desktop \
|
||||||
|
|||||||
Reference in New Issue
Block a user