Skip to content

Commit 4f18675

Browse files
committed
Support unified KDE & XDG host and item
1 parent ba419c1 commit 4f18675

File tree

10 files changed

+244
-272
lines changed

10 files changed

+244
-272
lines changed

include/swaybar/tray/host.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifndef _SWAYBAR_TRAY_HOST_H
2+
#define _SWAYBAR_TRAY_HOST_H
3+
4+
#include "swaybar/tray/tray.h"
5+
6+
char *start_host(char *protocol, struct swaybar_tray *tray);
7+
void stop_host(char *host, struct swaybar_tray *tray);
8+
9+
#endif

include/swaybar/tray/host_kde.h

Lines changed: 0 additions & 17 deletions
This file was deleted.

include/swaybar/tray/item.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef _SWAYBAR_TRAY_ITEM_H
2+
#define _SWAYBAR_TRAY_ITEM_H
3+
4+
#include <cairo.h>
5+
#include <stdbool.h>
6+
#include <stdint.h>
7+
#include "swaybar/tray/tray.h"
8+
9+
struct swaybar_output;
10+
11+
struct swaybar_sni {
12+
// icon properties
13+
struct swaybar_tray *tray;
14+
cairo_surface_t *icon;
15+
int min_size;
16+
int max_size;
17+
18+
// dbus properties
19+
char *watcher_id;
20+
char *service;
21+
char *path;
22+
char *interface;
23+
24+
char *status;
25+
char *icon_name;
26+
char *attention_icon_name;
27+
bool item_is_menu;
28+
char *menu;
29+
};
30+
31+
struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray);
32+
void destroy_sni(struct swaybar_sni *sni);
33+
uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
34+
struct swaybar_sni *sni);
35+
36+
#endif

include/swaybar/tray/item_kde.h

Lines changed: 0 additions & 36 deletions
This file was deleted.

include/swaybar/tray/tray.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
struct swaybar;
1515
struct swaybar_output;
16-
struct swaybar_host_kde;
1716
struct swaybar_watcher;
1817

1918
struct swaybar_tray {
@@ -22,7 +21,9 @@ struct swaybar_tray {
2221
int fd;
2322
sd_bus *bus;
2423

25-
struct swaybar_host_kde *host_kde;
24+
char *host_kde;
25+
char *host_xdg;
26+
list_t *items; // struct swaybar_sni *
2627
struct swaybar_watcher *watcher_kde;
2728
struct swaybar_watcher *watcher_xdg;
2829

swaybar/meson.build

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
tray_files = get_option('enable-tray') ? [
2-
'tray/host_kde.c',
2+
'tray/host.c',
33
'tray/icon.c',
4-
'tray/item_kde.c',
4+
'tray/item.c',
55
'tray/tray.c',
66
'tray/watcher.c'
77
] : []

swaybar/tray/host.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#define _POSIX_C_SOURCE 200809L
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <unistd.h>
6+
#include "swaybar/bar.h"
7+
#include "swaybar/tray/host.h"
8+
#include "swaybar/tray/item.h"
9+
#include "swaybar/tray/tray.h"
10+
#include "log.h"
11+
12+
static void add_sni(struct swaybar_tray *tray, char *id) {
13+
wlr_log(WLR_DEBUG, "Registering Status Notifier Item '%s'", id);
14+
list_add(tray->items, create_sni(id, tray));
15+
set_bar_dirty(tray->bar);
16+
}
17+
18+
static int handle_sni_registered(sd_bus_message *msg, void *data,
19+
sd_bus_error *error) {
20+
char *id;
21+
int ret = sd_bus_message_read(msg, "s", &id);
22+
if (ret < 0) {
23+
wlr_log(WLR_ERROR, "Failed to parse register SNI message: %s", strerror(-ret));
24+
}
25+
26+
struct swaybar_tray *tray = data;
27+
add_sni(tray, id);
28+
29+
return ret;
30+
}
31+
32+
static int cmp_sni_id(const void *item, const void *cmp_to) {
33+
const struct swaybar_sni *sni = item;
34+
return strcmp(sni->watcher_id, cmp_to);
35+
}
36+
37+
static int handle_sni_unregistered(sd_bus_message *msg, void *data,
38+
sd_bus_error *error) {
39+
char *id;
40+
int ret = sd_bus_message_read(msg, "s", &id);
41+
if (ret < 0) {
42+
wlr_log(WLR_ERROR, "Failed to parse unregister SNI message: %s", strerror(-ret));
43+
}
44+
45+
struct swaybar_tray *tray = data;
46+
int idx = list_seq_find(tray->items, cmp_sni_id, id);
47+
if (idx != -1) {
48+
wlr_log(WLR_DEBUG, "Unregistering Status Notifier Item '%s'", id);
49+
list_del(tray->items, idx);
50+
set_bar_dirty(tray->bar);
51+
}
52+
return ret;
53+
}
54+
55+
char *start_host(char *protocol, struct swaybar_tray *tray) {
56+
size_t len = snprintf(NULL, 0, "org.%s.StatusNotifierWatcher", protocol) + 1;
57+
char *watcher_interface = malloc(len);
58+
snprintf(watcher_interface, len, "org.%s.StatusNotifierWatcher", protocol);
59+
static const char *watcher_path = "/StatusNotifierWatcher";
60+
61+
sd_bus_slot *register_slot = NULL;
62+
int ret = sd_bus_match_signal(tray->bus, &register_slot, watcher_interface,
63+
watcher_path, watcher_interface, "StatusNotifierItemRegistered",
64+
handle_sni_registered, tray);
65+
if (ret < 0) {
66+
wlr_log(WLR_ERROR, "Failed to subscribe to registering events: %s",
67+
strerror(-ret));
68+
goto error;
69+
}
70+
ret = sd_bus_match_signal(tray->bus, NULL, watcher_interface,
71+
watcher_path, watcher_interface, "StatusNotifierItemUnregistered",
72+
handle_sni_unregistered, tray);
73+
if (ret < 0) {
74+
wlr_log(WLR_ERROR, "Failed to subscribe to unregistering events: %s",
75+
strerror(-ret));
76+
goto error;
77+
}
78+
sd_bus_slot_set_floating(register_slot, 1);
79+
80+
pid_t pid = getpid();
81+
size_t name_len = snprintf(NULL, 0, "org.%s.StatusNotifierHost-%d",
82+
protocol, pid) + 1;
83+
char *host = malloc(name_len);
84+
snprintf(host, name_len, "org.%s.StatusNotifierHost-%d", protocol, pid);
85+
ret = sd_bus_request_name(tray->bus, host, 0);
86+
if (ret < 0) {
87+
wlr_log(WLR_DEBUG, "Failed to acquire service name: %s", strerror(-ret));
88+
goto error;
89+
}
90+
91+
// this is called asynchronously in case the watcher is owned by this process
92+
ret = sd_bus_call_method_async(tray->bus, NULL, watcher_interface,
93+
watcher_path, watcher_interface, "RegisterStatusNotifierHost",
94+
NULL, NULL, "s", host);
95+
if (ret < 0) {
96+
wlr_log(WLR_ERROR, "Failed to send register call: %s", strerror(-ret));
97+
goto error;
98+
}
99+
100+
struct swaybar_watcher *watcher = protocol[0] == 'f' ?
101+
tray->watcher_xdg : tray->watcher_kde;
102+
if (!watcher) {
103+
// this tray did not initialize watcher, so need to get existing items
104+
sd_bus_error error = SD_BUS_ERROR_NULL;
105+
char **ids;
106+
ret = sd_bus_get_property_strv(tray->bus, watcher_interface, watcher_path,
107+
watcher_interface, "RegisteredStatusNotifierItems", &error, &ids);
108+
if (ret < 0) {
109+
wlr_log(WLR_ERROR, "Failed to get registered items from watcher: %s",
110+
error.message);
111+
sd_bus_error_free(&error);
112+
} else if (ids) {
113+
for (char **id = ids; *id; ++id) {
114+
add_sni(tray, *id);
115+
}
116+
}
117+
}
118+
119+
wlr_log(WLR_DEBUG, "Registered %s", host);
120+
return host;
121+
error:
122+
sd_bus_slot_unref(register_slot);
123+
free(host);
124+
return NULL;
125+
}
126+
127+
void stop_host(char *name, struct swaybar_tray *tray) {
128+
sd_bus_release_name(tray->bus, name);
129+
free(name);
130+
}

0 commit comments

Comments
 (0)