diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-12-31 15:43:23 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-31 15:43:23 -0500 |
commit | 3d7c20f062bebe39199d3872e5b64d5e8d61d100 (patch) | |
tree | 93b8ddb51873cae14db8d5f07db74ca96236f184 /swaybar/tray/tray.c | |
parent | Apply implicit fallback seat config (diff) | |
parent | swaybar: use KDE's SNI IconThemePath property (diff) | |
download | sway-3d7c20f062bebe39199d3872e5b64d5e8d61d100.tar.gz sway-3d7c20f062bebe39199d3872e5b64d5e8d61d100.tar.zst sway-3d7c20f062bebe39199d3872e5b64d5e8d61d100.zip |
Merge pull request #3249 from ianyfan/tray
Swaybar tray
Diffstat (limited to 'swaybar/tray/tray.c')
-rw-r--r-- | swaybar/tray/tray.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c new file mode 100644 index 00000000..acc300af --- /dev/null +++ b/swaybar/tray/tray.c | |||
@@ -0,0 +1,127 @@ | |||
1 | #include <cairo.h> | ||
2 | #include <stdint.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include "swaybar/config.h" | ||
6 | #include "swaybar/bar.h" | ||
7 | #include "swaybar/tray/icon.h" | ||
8 | #include "swaybar/tray/host.h" | ||
9 | #include "swaybar/tray/item.h" | ||
10 | #include "swaybar/tray/tray.h" | ||
11 | #include "swaybar/tray/watcher.h" | ||
12 | #include "list.h" | ||
13 | #include "log.h" | ||
14 | |||
15 | static int handle_lost_watcher(sd_bus_message *msg, | ||
16 | void *data, sd_bus_error *error) { | ||
17 | char *service, *old_owner, *new_owner; | ||
18 | int ret = sd_bus_message_read(msg, "sss", &service, &old_owner, &new_owner); | ||
19 | if (ret < 0) { | ||
20 | wlr_log(WLR_ERROR, "Failed to parse owner change message: %s", strerror(-ret)); | ||
21 | return ret; | ||
22 | } | ||
23 | |||
24 | if (!*new_owner) { | ||
25 | struct swaybar_tray *tray = data; | ||
26 | if (strcmp(service, "org.freedesktop.StatusNotifierWatcher") == 0) { | ||
27 | tray->watcher_xdg = create_watcher("freedesktop", tray->bus); | ||
28 | } else if (strcmp(service, "org.kde.StatusNotifierWatcher") == 0) { | ||
29 | tray->watcher_kde = create_watcher("kde", tray->bus); | ||
30 | } | ||
31 | } | ||
32 | |||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | struct swaybar_tray *create_tray(struct swaybar *bar) { | ||
37 | wlr_log(WLR_DEBUG, "Initializing tray"); | ||
38 | |||
39 | sd_bus *bus; | ||
40 | int ret = sd_bus_open_user(&bus); | ||
41 | if (ret < 0) { | ||
42 | wlr_log(WLR_ERROR, "Failed to connect to user bus: %s", strerror(-ret)); | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | struct swaybar_tray *tray = calloc(1, sizeof(struct swaybar_tray)); | ||
47 | if (!tray) { | ||
48 | return NULL; | ||
49 | } | ||
50 | tray->bar = bar; | ||
51 | tray->bus = bus; | ||
52 | tray->fd = sd_bus_get_fd(tray->bus); | ||
53 | |||
54 | tray->watcher_xdg = create_watcher("freedesktop", tray->bus); | ||
55 | tray->watcher_kde = create_watcher("kde", tray->bus); | ||
56 | |||
57 | ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.DBus", | ||
58 | "/org/freedesktop/DBus", "org.freedesktop.DBus", | ||
59 | "NameOwnerChanged", handle_lost_watcher, tray); | ||
60 | if (ret < 0) { | ||
61 | wlr_log(WLR_ERROR, "Failed to subscribe to unregistering events: %s", | ||
62 | strerror(-ret)); | ||
63 | } | ||
64 | |||
65 | tray->items = create_list(); | ||
66 | |||
67 | init_host(&tray->host_xdg, "freedesktop", tray); | ||
68 | init_host(&tray->host_kde, "kde", tray); | ||
69 | |||
70 | init_themes(&tray->themes, &tray->basedirs); | ||
71 | |||
72 | return tray; | ||
73 | } | ||
74 | |||
75 | void destroy_tray(struct swaybar_tray *tray) { | ||
76 | if (!tray) { | ||
77 | return; | ||
78 | } | ||
79 | finish_host(&tray->host_xdg); | ||
80 | finish_host(&tray->host_kde); | ||
81 | for (int i = 0; i < tray->items->length; ++i) { | ||
82 | destroy_sni(tray->items->items[0]); | ||
83 | } | ||
84 | list_free(tray->items); | ||
85 | destroy_watcher(tray->watcher_xdg); | ||
86 | destroy_watcher(tray->watcher_kde); | ||
87 | sd_bus_flush_close_unref(tray->bus); | ||
88 | finish_themes(tray->themes, tray->basedirs); | ||
89 | free(tray); | ||
90 | } | ||
91 | |||
92 | void tray_in(int fd, short mask, void *data) { | ||
93 | sd_bus *bus = data; | ||
94 | int ret; | ||
95 | while ((ret = sd_bus_process(bus, NULL)) > 0) { | ||
96 | // This space intentionally left blank | ||
97 | } | ||
98 | if (ret < 0) { | ||
99 | wlr_log(WLR_ERROR, "Failed to process bus: %s", strerror(-ret)); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static int cmp_output(const void *item, const void *cmp_to) { | ||
104 | return strcmp(item, cmp_to); | ||
105 | } | ||
106 | |||
107 | uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) { | ||
108 | struct swaybar_config *config = output->bar->config; | ||
109 | if (config->tray_outputs) { | ||
110 | if (list_seq_find(config->tray_outputs, cmp_output, output->name) == -1) { | ||
111 | return 0; | ||
112 | } | ||
113 | } // else display on all | ||
114 | |||
115 | if ((int) output->height*output->scale <= 2*config->tray_padding) { | ||
116 | return 2*config->tray_padding + 1; | ||
117 | } | ||
118 | |||
119 | uint32_t max_height = 0; | ||
120 | struct swaybar_tray *tray = output->bar->tray; | ||
121 | for (int i = 0; i < tray->items->length; ++i) { | ||
122 | uint32_t h = render_sni(cairo, output, x, tray->items->items[i]); | ||
123 | max_height = h > max_height ? h : max_height; | ||
124 | } | ||
125 | |||
126 | return max_height; | ||
127 | } | ||