diff options
author | Calvin Lee <cyrus296@gmail.com> | 2017-06-07 16:45:28 -0700 |
---|---|---|
committer | Calvin Lee <cyrus296@gmail.com> | 2017-06-07 17:49:16 -0700 |
commit | 843ad38b3c427adb0bf319e9613d9813c8d9246c (patch) | |
tree | e02a5b06e2b6923371fd53724791c147c18a1fa4 /swaybar/event_loop.c | |
parent | Merge pull request #1232 from johalun/master-freebsd (diff) | |
download | sway-843ad38b3c427adb0bf319e9613d9813c8d9246c.tar.gz sway-843ad38b3c427adb0bf319e9613d9813c8d9246c.tar.zst sway-843ad38b3c427adb0bf319e9613d9813c8d9246c.zip |
Implement Tray Icons
This commit implements the StatusNotifierItem protocol, and enables
swaybar to show tray icons. It also uses `xembedsniproxy` in order to
communicate with xembed applications.
The tray is completely optional, and can be disabled on compile time
with the `enable-tray` option. Or on runtime with the bar config option
`tray_output none`.
Overview of changes:
In swaybar very little is changed outside the tray subfolder except
that all events are now polled in `event_loop.c`, this creates no
functional difference.
Six bar configuration options were added, these are detailed in
sway-bar(5)
The tray subfolder is where all protocol implementation takes place and
is organised as follows:
tray/sni_watcher.c:
This file contains the StatusNotifierWatcher. It keeps track of
items and hosts and reports when they come or go.
tray/tray.c
This file contains the StatusNotifierHost. It keeps track of
sway's version of the items and represents the tray itself.
tray/sni.c
This file contains the StatusNotifierItem struct and all
communication with individual items.
tray/icon.c
This file implements the icon theme protocol. It allows for
finding icons by name, rather than by pixmap.
tray/dbus.c
This file allows for asynchronous DBus communication.
See #986 #343
Diffstat (limited to 'swaybar/event_loop.c')
-rw-r--r-- | swaybar/event_loop.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c new file mode 100644 index 00000000..80655d8b --- /dev/null +++ b/swaybar/event_loop.c | |||
@@ -0,0 +1,143 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <stdlib.h> | ||
3 | #include <stdbool.h> | ||
4 | #include <string.h> | ||
5 | #include <strings.h> | ||
6 | #include <poll.h> | ||
7 | #include "swaybar/bar.h" | ||
8 | #include "swaybar/event_loop.h" | ||
9 | #include "list.h" | ||
10 | #include "log.h" | ||
11 | |||
12 | struct event_item { | ||
13 | void(*cb)(int fd, short mask, void *data); | ||
14 | void *data; | ||
15 | }; | ||
16 | |||
17 | struct timer_item { | ||
18 | timer_t timer; | ||
19 | void(*cb)(timer_t timer, void *data); | ||
20 | void *data; | ||
21 | }; | ||
22 | |||
23 | static struct { | ||
24 | // The order of each must be kept consistent | ||
25 | struct { /* pollfd array */ | ||
26 | struct pollfd *items; | ||
27 | int capacity; | ||
28 | int length; | ||
29 | } fds; | ||
30 | list_t *items; /* event_item list */ | ||
31 | |||
32 | // Timer list | ||
33 | list_t *timers; | ||
34 | } event_loop; | ||
35 | |||
36 | void add_timer(timer_t timer, | ||
37 | void(*cb)(timer_t timer, void *data), | ||
38 | void *data) { | ||
39 | |||
40 | struct timer_item *item = malloc(sizeof(struct timer_item)); | ||
41 | item->timer = timer; | ||
42 | item->cb = cb; | ||
43 | item->data = data; | ||
44 | |||
45 | list_add(event_loop.timers, item); | ||
46 | } | ||
47 | |||
48 | void add_event(int fd, short mask, | ||
49 | void(*cb)(int fd, short mask, void *data), void *data) { | ||
50 | |||
51 | struct pollfd pollfd = { | ||
52 | fd, | ||
53 | mask, | ||
54 | 0, | ||
55 | }; | ||
56 | |||
57 | // Resize | ||
58 | if (event_loop.fds.length == event_loop.fds.capacity) { | ||
59 | event_loop.fds.capacity += 10; | ||
60 | event_loop.fds.items = realloc(event_loop.fds.items, | ||
61 | sizeof(struct pollfd) * event_loop.fds.capacity); | ||
62 | } | ||
63 | |||
64 | event_loop.fds.items[event_loop.fds.length++] = pollfd; | ||
65 | |||
66 | struct event_item *item = malloc(sizeof(struct event_item)); | ||
67 | item->cb = cb; | ||
68 | item->data = data; | ||
69 | |||
70 | list_add(event_loop.items, item); | ||
71 | |||
72 | return; | ||
73 | } | ||
74 | |||
75 | bool remove_event(int fd) { | ||
76 | int index = -1; | ||
77 | for (int i = 0; i < event_loop.fds.length; ++i) { | ||
78 | if (event_loop.fds.items[i].fd == fd) { | ||
79 | index = i; | ||
80 | } | ||
81 | } | ||
82 | if (index != -1) { | ||
83 | free(event_loop.items->items[index]); | ||
84 | |||
85 | --event_loop.fds.length; | ||
86 | memmove(&event_loop.fds.items[index], &event_loop.fds.items[index + 1], | ||
87 | sizeof(struct pollfd) * event_loop.fds.length - index); | ||
88 | |||
89 | list_del(event_loop.items, index); | ||
90 | return true; | ||
91 | } else { | ||
92 | return false; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { | ||
97 | const struct timer_item *timer_item = _timer_item; | ||
98 | const timer_t *timer = _timer; | ||
99 | if (timer_item->timer == timer) { | ||
100 | return 0; | ||
101 | } else { | ||
102 | return -1; | ||
103 | } | ||
104 | } | ||
105 | bool remove_timer(timer_t timer) { | ||
106 | int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); | ||
107 | if (index != -1) { | ||
108 | list_del(event_loop.timers, index); | ||
109 | return true; | ||
110 | } | ||
111 | return false; | ||
112 | } | ||
113 | |||
114 | void event_loop_poll() { | ||
115 | poll(event_loop.fds.items, event_loop.fds.length, -1); | ||
116 | |||
117 | for (int i = 0; i < event_loop.fds.length; ++i) { | ||
118 | struct pollfd pfd = event_loop.fds.items[i]; | ||
119 | struct event_item *item = (struct event_item *)event_loop.items->items[i]; | ||
120 | |||
121 | if (pfd.revents & pfd.events) { | ||
122 | item->cb(pfd.fd, pfd.revents, item->data); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | // check timers | ||
127 | // not tested, but seems to work | ||
128 | for (int i = 0; i < event_loop.timers->length; ++i) { | ||
129 | struct timer_item *item = event_loop.timers->items[i]; | ||
130 | int overrun = timer_getoverrun(item->timer); | ||
131 | if (overrun && overrun != -1) { | ||
132 | item->cb(item->timer, item->data); | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | void init_event_loop() { | ||
138 | event_loop.fds.length = 0; | ||
139 | event_loop.fds.capacity = 10; | ||
140 | event_loop.fds.items = malloc(event_loop.fds.capacity * sizeof(struct pollfd)); | ||
141 | event_loop.items = create_list(); | ||
142 | event_loop.timers = create_list(); | ||
143 | } | ||