diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-06-14 18:53:32 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-14 18:53:32 -0400 |
commit | eb6e38c86d2deb37cc6f378f8644c4a530fd7448 (patch) | |
tree | e3c567c4684faf0f9a7f77494f1bf638171d5349 /swaybar/tray/dbus.c | |
parent | Merge pull request #1236 from ykrivopalov/fix_complex_status_command (diff) | |
parent | Merge branch 'master' into tray (diff) | |
download | sway-eb6e38c86d2deb37cc6f378f8644c4a530fd7448.tar.gz sway-eb6e38c86d2deb37cc6f378f8644c4a530fd7448.tar.zst sway-eb6e38c86d2deb37cc6f378f8644c4a530fd7448.zip |
Implement Tray Icons
Diffstat (limited to 'swaybar/tray/dbus.c')
-rw-r--r-- | swaybar/tray/dbus.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/swaybar/tray/dbus.c b/swaybar/tray/dbus.c new file mode 100644 index 00000000..333d398e --- /dev/null +++ b/swaybar/tray/dbus.c | |||
@@ -0,0 +1,189 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <stdint.h> | ||
5 | #include <stdbool.h> | ||
6 | #include <poll.h> | ||
7 | #include <signal.h> | ||
8 | #include <time.h> | ||
9 | #include <dbus/dbus.h> | ||
10 | #include "swaybar/tray/dbus.h" | ||
11 | #include "swaybar/event_loop.h" | ||
12 | #include "log.h" | ||
13 | |||
14 | DBusConnection *conn = NULL; | ||
15 | |||
16 | static void dispatch_watch(int fd, short mask, void *data) { | ||
17 | sway_log(L_DEBUG, "Dispatching watch"); | ||
18 | DBusWatch *watch = data; | ||
19 | |||
20 | if (!dbus_watch_get_enabled(watch)) { | ||
21 | return; | ||
22 | } | ||
23 | |||
24 | uint32_t flags = 0; | ||
25 | |||
26 | if (mask & POLLIN) { | ||
27 | flags |= DBUS_WATCH_READABLE; | ||
28 | } if (mask & POLLOUT) { | ||
29 | flags |= DBUS_WATCH_WRITABLE; | ||
30 | } if (mask & POLLHUP) { | ||
31 | flags |= DBUS_WATCH_HANGUP; | ||
32 | } if (mask & POLLERR) { | ||
33 | flags |= DBUS_WATCH_ERROR; | ||
34 | } | ||
35 | |||
36 | dbus_watch_handle(watch, flags); | ||
37 | } | ||
38 | |||
39 | static dbus_bool_t add_watch(DBusWatch *watch, void *_data) { | ||
40 | if (!dbus_watch_get_enabled(watch)) { | ||
41 | // Watch should not be polled | ||
42 | return TRUE; | ||
43 | } | ||
44 | |||
45 | short mask = 0; | ||
46 | uint32_t flags = dbus_watch_get_flags(watch); | ||
47 | |||
48 | if (flags & DBUS_WATCH_READABLE) { | ||
49 | mask |= POLLIN; | ||
50 | } if (flags & DBUS_WATCH_WRITABLE) { | ||
51 | mask |= POLLOUT; | ||
52 | } | ||
53 | |||
54 | int fd = dbus_watch_get_unix_fd(watch); | ||
55 | |||
56 | sway_log(L_DEBUG, "Adding DBus watch fd: %d", fd); | ||
57 | add_event(fd, mask, dispatch_watch, watch); | ||
58 | |||
59 | return TRUE; | ||
60 | } | ||
61 | |||
62 | static void remove_watch(DBusWatch *watch, void *_data) { | ||
63 | int fd = dbus_watch_get_unix_fd(watch); | ||
64 | |||
65 | remove_event(fd); | ||
66 | } | ||
67 | |||
68 | static void dispatch_timeout(timer_t timer, void *data) { | ||
69 | sway_log(L_DEBUG, "Dispatching DBus timeout"); | ||
70 | DBusTimeout *timeout = data; | ||
71 | |||
72 | if (dbus_timeout_get_enabled(timeout)) { | ||
73 | dbus_timeout_handle(timeout); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) { | ||
78 | if (!dbus_timeout_get_enabled(timeout)) { | ||
79 | return TRUE; | ||
80 | } | ||
81 | |||
82 | timer_t *timer = malloc(sizeof(timer_t)); | ||
83 | if (!timer) { | ||
84 | sway_log(L_ERROR, "Cannot allocate memory"); | ||
85 | return FALSE; | ||
86 | } | ||
87 | struct sigevent ev = { | ||
88 | .sigev_notify = SIGEV_NONE, | ||
89 | }; | ||
90 | |||
91 | if (timer_create(CLOCK_MONOTONIC, &ev, timer)) { | ||
92 | sway_log(L_ERROR, "Could not create DBus timer"); | ||
93 | return FALSE; | ||
94 | } | ||
95 | |||
96 | int interval = dbus_timeout_get_interval(timeout); | ||
97 | int interval_sec = interval / 1000; | ||
98 | int interval_msec = (interval_sec * 1000) - interval; | ||
99 | |||
100 | struct timespec period = { | ||
101 | (time_t) interval_sec, | ||
102 | ((long) interval_msec) * 1000 * 1000, | ||
103 | }; | ||
104 | struct itimerspec time = { | ||
105 | period, | ||
106 | period, | ||
107 | }; | ||
108 | |||
109 | timer_settime(*timer, 0, &time, NULL); | ||
110 | |||
111 | dbus_timeout_set_data(timeout, timer, free); | ||
112 | |||
113 | sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec); | ||
114 | add_timer(*timer, dispatch_timeout, timeout); | ||
115 | |||
116 | return TRUE; | ||
117 | } | ||
118 | static void remove_timeout(DBusTimeout *timeout, void *_data) { | ||
119 | timer_t *timer = (timer_t *) dbus_timeout_get_data(timeout); | ||
120 | sway_log(L_DEBUG, "Removing DBus timeout."); | ||
121 | |||
122 | if (timer) { | ||
123 | remove_timer(*timer); | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static bool should_dispatch = true; | ||
128 | |||
129 | static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_status, | ||
130 | void *_data) { | ||
131 | if (new_status == DBUS_DISPATCH_DATA_REMAINS) { | ||
132 | should_dispatch = true; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /* Public functions below */ | ||
137 | |||
138 | void dispatch_dbus() { | ||
139 | if (!should_dispatch) { | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | DBusDispatchStatus status; | ||
144 | |||
145 | do { | ||
146 | status = dbus_connection_dispatch(conn); | ||
147 | } while (status == DBUS_DISPATCH_DATA_REMAINS); | ||
148 | |||
149 | if (status != DBUS_DISPATCH_COMPLETE) { | ||
150 | sway_log(L_ERROR, "Cannot dispatch dbus events: %d", status); | ||
151 | } | ||
152 | |||
153 | should_dispatch = false; | ||
154 | } | ||
155 | |||
156 | int dbus_init() { | ||
157 | DBusError error; | ||
158 | dbus_error_init(&error); | ||
159 | |||
160 | conn = dbus_bus_get(DBUS_BUS_SESSION, &error); | ||
161 | dbus_connection_set_exit_on_disconnect(conn, FALSE); | ||
162 | if (dbus_error_is_set(&error)) { | ||
163 | sway_log(L_ERROR, "Cannot get bus connection: %s\n", error.message); | ||
164 | conn = NULL; | ||
165 | return -1; | ||
166 | } | ||
167 | |||
168 | sway_log(L_INFO, "Unique name: %s\n", dbus_bus_get_unique_name(conn)); | ||
169 | |||
170 | // Will be called if dispatch status changes | ||
171 | dbus_connection_set_dispatch_status_function(conn, dispatch_status, NULL, NULL); | ||
172 | |||
173 | if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch, | ||
174 | NULL, NULL, NULL)) { | ||
175 | dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); | ||
176 | sway_log(L_ERROR, "Failed to activate DBUS watch functions"); | ||
177 | return -1; | ||
178 | } | ||
179 | |||
180 | if (!dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, | ||
181 | NULL, NULL, NULL)) { | ||
182 | dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); | ||
183 | dbus_connection_set_timeout_functions(conn, NULL, NULL, NULL, NULL, NULL); | ||
184 | sway_log(L_ERROR, "Failed to activate DBUS timeout functions"); | ||
185 | return -1; | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||