Skip to content

Commit 436a931

Browse files
bdwaltonandydotxyz
authored andcommitted
Handle systray absence and restarts gracefully
Move registration into a goroutine so that we can handle the case when org.kde.StatusNotifierWatcher is absent at startup or when it is restarted later. (Restarting the systray is common with, eg, i3 or sway config reload.) In the goroutine, we setup a signal listener for NameOwnerChanged on org.kde.StatusNotifierWatcher so we can handle it coming and going appropriately. The goroutine will exit when quitChan is closed so it shouldn't leak.
1 parent b6a2d6c commit 436a931

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

systray_unix.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,51 @@ func nativeStart() {
227227
instance.menuProps = menuProps
228228
instance.lock.Unlock()
229229

230-
obj := conn.Object("org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher")
230+
go stayRegistered()
231+
}
232+
233+
func register() bool {
234+
obj := instance.conn.Object("org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher")
231235
call := obj.Call("org.kde.StatusNotifierWatcher.RegisterStatusNotifierItem", 0, path)
232236
if call.Err != nil {
233-
log.Printf("systray error: failed to register our icon with the notifier watcher (maybe no tray is running?): %s\n", call.Err)
237+
log.Printf("systray error: failed to register: %v\n", call.Err)
238+
return false
239+
}
240+
241+
return true
242+
}
243+
244+
func stayRegistered() {
245+
register()
246+
247+
conn := instance.conn
248+
if err := conn.AddMatchSignal(
249+
dbus.WithMatchObjectPath("/org/freedesktop/DBus"),
250+
dbus.WithMatchInterface("org.freedesktop.DBus"),
251+
dbus.WithMatchSender("org.freedesktop.DBus"),
252+
dbus.WithMatchMember("NameOwnerChanged"),
253+
dbus.WithMatchArg(0, "org.kde.StatusNotifierWatcher"),
254+
); err != nil {
255+
log.Printf("systray error: failed to register signal matching: %v\n", err)
256+
// If we can't monitor signals, there is no point in
257+
// us being here. we're either registered or not (per
258+
// above) and will roll the dice from here...
259+
return
260+
}
261+
262+
sc := make(chan *dbus.Signal, 10)
263+
conn.Signal(sc)
264+
265+
for {
266+
select {
267+
case sig := <-sc:
268+
// sig.Body has the args, which are [name old_owner new_owner]
269+
if sig.Body[2] != "" {
270+
register()
271+
}
272+
case <-quitChan:
273+
return
274+
}
234275
}
235276
}
236277

0 commit comments

Comments
 (0)