Skip to content

Commit

Permalink
Merge pull request #247 from andydotxyz/fix/updatesystray
Browse files Browse the repository at this point in the history
  • Loading branch information
andydotxyz authored Nov 16, 2023
2 parents 46aed46 + c5cc0cf commit 62d5158
Showing 1 changed file with 67 additions and 49 deletions.
116 changes: 67 additions & 49 deletions modules/systray/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ import (
"github.com/godbus/dbus/v5/introspect"
"github.com/godbus/dbus/v5/prop"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
deskDriver "fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"fyshos.com/fynedesk"
"fyshos.com/fynedesk/internal/icon"
"fyshos.com/fynedesk/modules/systray/generated/menu"
"fyshos.com/fynedesk/modules/systray/generated/notifier"
"fyshos.com/fynedesk/modules/systray/generated/watcher"
wmtheme "fyshos.com/fynedesk/theme"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
deskDriver "fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

const (
Expand All @@ -56,14 +57,19 @@ type tray struct {
menu *menu.Dbusmenu

box *fyne.Container
nodes map[dbus.Sender]*widget.Button
nodes map[dbus.Sender]*node
}

type node struct {
ico *widget.Button
ni *notifier.StatusNotifierItem
}

// NewTray creates a new module that will show a system tray in the status area
func NewTray() fynedesk.Module {
iconSize := wmtheme.NarrowBarWidth
grid := container.New(collapsingGridWrap(fyne.NewSize(iconSize, iconSize)))
t := &tray{box: grid, nodes: make(map[dbus.Sender]*widget.Button)}
t := &tray{box: grid, nodes: make(map[dbus.Sender]*node)}

conn, _ := dbus.ConnectSessionBus()
t.conn = conn
Expand Down Expand Up @@ -116,6 +122,7 @@ func NewTray() fynedesk.Module {
}

watchErr := t.conn.AddMatchSignal(dbus.WithMatchInterface("org.freedesktop.DBus"), dbus.WithMatchObjectPath("/org/freedesktop/DBus"))
_ = t.conn.AddMatchSignal(dbus.WithMatchInterface("org.kde.StatusNotifierItem"))
if watchErr != nil {
fyne.LogError("Failed to monitor systray name loss", watchErr)
return t
Expand All @@ -125,19 +132,25 @@ func NewTray() fynedesk.Module {
t.conn.Signal(c)
go func() {
for v := range c {
if v.Name != "org.freedesktop.DBus.NameOwnerChanged" {
switch v.Name {
case "org.freedesktop.DBus.NameOwnerChanged":
name := v.Body[0]
newOwner := v.Body[2]
if newOwner == "" {
if item, ok := t.nodes[dbus.Sender(name.(string))]; ok {
t.box.Remove(item.ico)
t.box.Refresh()
}
}
case "org.kde.StatusNotifierItem.NewIcon":
item, ok := t.nodes[dbus.Sender(v.Sender)]
if ok {
t.updateIcon(item)
}
default:
log.Println("Also", v.Name)
continue
}

name := v.Body[0]
newOwner := v.Body[2]
if newOwner == "" {
if item, ok := t.nodes[dbus.Sender(name.(string))]; ok {
t.box.Remove(item)
t.box.Refresh()
}
}
}
}()

Expand All @@ -150,8 +163,9 @@ func (t *tray) Destroy() {
func (t *tray) RegisterStatusNotifierItem(service string, sender dbus.Sender) (err *dbus.Error) {
ni := notifier.NewStatusNotifierItem(t.conn.Object(string(sender), dbus.ObjectPath(service)))

ico, ok := t.nodes[sender]
item, ok := t.nodes[sender]
if !ok {
var ico *widget.Button
ico = widget.NewButton("", func() {
if m, err := ni.GetMenu(t.conn.Context()); err == nil {
t.showMenu(string(sender), m, ico)
Expand All @@ -164,40 +178,13 @@ func (t *tray) RegisterStatusNotifierItem(service string, sender dbus.Sender) (e
}
})
ico.Importance = widget.LowImportance
t.nodes[sender] = ico
item = &node{ico, ni}
t.nodes[sender] = item
t.box.Add(ico)
}

ic, _ := ni.GetIconPixmap(t.conn.Context())
if len(ic) > 0 {
img := pixelsToImage(ic[0])
unique := strconv.Itoa(resourceID) + ".png"
resourceID++
w := &bytes.Buffer{}
_ = png.Encode(w, img)
ico.SetIcon(fyne.NewStaticResource(unique, w.Bytes()))
} else {
name, _ := ni.GetIconName(t.conn.Context())
path, _ := ni.GetIconThemePath(t.conn.Context())
fullPath := ""
if path != "" {
fullPath = filepath.Join(path, name+".png")
if _, err := os.Stat(fullPath); err != nil { // not found, search instead
fullPath = icon.FdoLookupIconPathInTheme("64", filepath.Join(path, "hicolor"), "", name)
}
} else {
fullPath = icon.FdoLookupIconPath("", 64, name)
}
img, err := ioutil.ReadFile(fullPath)
if err != nil {
fyne.LogError("Failed to load status icon", err)
ico.SetIcon(wmtheme.BrokenImageIcon)
} else {
ico.SetIcon(fyne.NewStaticResource(name, img))
}
}

ico.Refresh()
t.nodes[sender].ni = ni
t.updateIcon(item)
t.box.Refresh()

return nil
Expand Down Expand Up @@ -316,6 +303,37 @@ func (t *tray) showMenu(sender string, name dbus.ObjectPath, from fyne.CanvasObj
fynedesk.Instance().WindowManager().ShowOverlay(w, size, pos)
}

func (t *tray) updateIcon(i *node) {
ic, _ := i.ni.GetIconPixmap(t.conn.Context())
if len(ic) > 0 {
img := pixelsToImage(ic[0])
unique := strconv.Itoa(resourceID) + ".png"
resourceID++
w := &bytes.Buffer{}
_ = png.Encode(w, img)
i.ico.SetIcon(fyne.NewStaticResource(unique, w.Bytes()))
} else {
name, _ := i.ni.GetIconName(t.conn.Context())
path, _ := i.ni.GetIconThemePath(t.conn.Context())
fullPath := ""
if path != "" {
fullPath = filepath.Join(path, name+".png")
if _, err := os.Stat(fullPath); err != nil { // not found, search instead
fullPath = icon.FdoLookupIconPathInTheme("64", filepath.Join(path, "hicolor"), "", name)
}
} else {
fullPath = icon.FdoLookupIconPath("", 64, name)
}
img, err := ioutil.ReadFile(fullPath)
if err != nil {
fyne.LogError("Failed to load status icon", err)
i.ico.SetIcon(wmtheme.BrokenImageIcon)
} else {
i.ico.SetIcon(fyne.NewStaticResource(name, img))
}
}
}

func createPropSpec() map[string]map[string]*prop.Prop {
return map[string]map[string]*prop.Prop{
"org.kde.StatusNotifierWatcher": {
Expand Down

0 comments on commit 62d5158

Please sign in to comment.