-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunity.go
128 lines (112 loc) · 3.06 KB
/
unity.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package taskbar
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/godbus/dbus/v5"
"github.com/godbus/dbus/v5/introspect"
)
// Dbus interface name
const dbusInterface = "com.canonical.Unity.LauncherEntry"
// Dbus introspection scheme
const introspection = `
<node>
<interface name="` + dbusInterface + `">
<method name="Query">
<arg direction="out" type="a{sv}"/>
</method>
<signal name="Update">
<arg name="appUri" type="s"/>
<arg name="properties" type="a{sv}"/>
</signal>
</interface>` + introspect.IntrospectDataString + `</node> `
type libUnityEntry struct {
connection *dbus.Conn
uri string
objectPath dbus.ObjectPath
progress float64
progressVisible bool
urgent bool
count int64
countVisible bool
}
func libUnityConnect(desktopName string) (*libUnityEntry, error) {
var hash uint64
conn, err := dbus.ConnectSessionBus()
if err != nil {
return nil, errors.New(fmt.Sprintf("Failed to connect to session bus: %v", err))
}
entry := libUnityEntry{}
if !strings.HasSuffix(desktopName, ".desktop") {
desktopName = desktopName + ".desktop"
}
entry.connection = conn
entry.uri = "application://" + desktopName
// DJB hash of URI string is used as identifier
hash = 5381
for _, c := range []byte(entry.uri) {
hash = hash*33 + uint64(c)
}
entry.objectPath = dbus.ObjectPath("/com/canonical/unity/launcherentry/" + strconv.FormatUint(hash, 10))
conn.Export(&entry, entry.objectPath, dbusInterface)
conn.Export(introspect.Introspectable(introspection), entry.objectPath,
"org.freedesktop.DBus.Introspectable")
return &entry, nil
}
func libUnityDisconnect(entry *libUnityEntry) error {
if entry == nil {
return nil
}
if err := entry.update(0, false, 0); err != nil {
return err
}
if err := entry.connection.Close(); err != nil {
return err
}
return nil
}
// com.canonical.Unity.LauncherEntry.Query Dbus method
func (entry *libUnityEntry) Query() (map[string]interface{}, *dbus.Error) {
data := map[string]interface{}{
"progress": entry.progress,
"progress-visible": entry.progressVisible,
"urgent": entry.urgent,
"count": entry.count,
"countVisible": entry.countVisible,
}
return data, nil
}
func (entry *libUnityEntry) update(progress float64, pulse bool, count int64) error {
var progressVisible bool
var countVisible bool
if progress > 0.0 && (!pulse) {
progressVisible = true
}
if count > 0 {
countVisible = true
}
// Saving properties to use in [Query]
entry.progress = progress
entry.progressVisible = progressVisible
entry.urgent = pulse
entry.count = count
entry.countVisible = countVisible
// Data to send with signal
data := map[string]interface{}{
"progress": progress,
"progress-visible": progressVisible,
"urgent": pulse,
"count": count,
"count-visible": countVisible,
}
// Emit com.canonical.Unity.LauncherEntry.Update signal
if err := entry.connection.Emit(
entry.objectPath,
dbusInterface+".Update",
entry.uri,
data); err != nil {
return err
}
return nil
}