aboutsummaryrefslogtreecommitdiff
path: root/swaybar/tray/tray.c
diff options
context:
space:
mode:
authorCalvin Lee <cyrus296@gmail.com>2017-10-24 11:59:42 -0600
committerCalvin Lee <cyrus296@gmail.com>2017-12-29 12:11:51 -0700
commitad99d9dff8f8e8ee78b5195d6ca440af130f6ab6 (patch)
treec8ca022e7a61922dc6d3303e944c9b364ed89848 /swaybar/tray/tray.c
parentd85ad05fa857cd7d7af2c8e2c33616d7895e1955 (diff)
Allow registering StatusNotifierItems by obj path
This commit impliments a KDE hidden feature where a SNI could be registered by object path instead of well-known name. This should allow libappindicator programs to work correctly under sway. See #1372
Diffstat (limited to 'swaybar/tray/tray.c')
-rw-r--r--swaybar/tray/tray.c128
1 files changed, 126 insertions, 2 deletions
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c
index 91c3af06..01532e1c 100644
--- a/swaybar/tray/tray.c
+++ b/swaybar/tray/tray.c
@@ -102,6 +102,70 @@ bail:
dbus_pending_call_unref(pending);
return;
}
+static void get_obj_items_reply(DBusPendingCall *pending, void *_data) {
+ DBusMessage *reply = dbus_pending_call_steal_reply(pending);
+
+ if (!reply) {
+ sway_log(L_ERROR, "Got no object path items reply from sni watcher");
+ goto bail;
+ }
+
+ int message_type = dbus_message_get_type(reply);
+
+ if (message_type == DBUS_MESSAGE_TYPE_ERROR) {
+ char *msg;
+
+ dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_STRING, &msg,
+ DBUS_TYPE_INVALID);
+
+ sway_log(L_ERROR, "Message is error: %s", msg);
+ goto bail;
+ }
+
+ DBusMessageIter iter;
+ DBusMessageIter variant;
+ DBusMessageIter array;
+ DBusMessageIter dstruct;
+
+ dbus_message_iter_init(reply, &iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ sway_log(L_ERROR, "Replyed with wrong type, not v(a(os))");
+ goto bail;
+ }
+ dbus_message_iter_recurse(&iter, &variant);
+ if (strcmp(dbus_message_iter_get_signature(&variant), "a(os)") != 0) {
+ sway_log(L_ERROR, "Replyed with wrong type not a(os)");
+ goto bail;
+ }
+
+ int len = dbus_message_iter_get_element_count(&variant);
+
+ dbus_message_iter_recurse(&variant, &array);
+ for (int i = 0; i < len; i++) {
+ const char *object_path;
+ const char *unique_name;
+
+ dbus_message_iter_recurse(&array, &dstruct);
+
+ dbus_message_iter_get_basic(&dstruct, &object_path);
+ dbus_message_iter_get_basic(&dstruct, &unique_name);
+
+ struct StatusNotifierItem *item =
+ sni_create_from_obj_path(unique_name, object_path);
+
+ if (item) {
+ sway_log(L_DEBUG, "Item registered with host: %s", unique_name);
+ list_add(tray->items, item);
+ dirty = true;
+ }
+ }
+
+bail:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
static void get_items() {
DBusPendingCall *pending;
DBusMessage *message = dbus_message_new_method_call(
@@ -127,6 +191,28 @@ static void get_items() {
}
dbus_pending_call_set_notify(pending, get_items_reply, NULL, NULL);
+
+ message = dbus_message_new_method_call(
+ "org.freedesktop.StatusNotifierWatcher",
+ "/StatusNotifierWatcher",
+ "org.freedesktop.DBus.Properties",
+ "Get");
+
+ iface = "org.swaywm.LessSuckyStatusNotifierWatcher";
+ prop = "RegisteredObjectPathItems";
+ dbus_message_append_args(message,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &prop,
+ DBUS_TYPE_INVALID);
+
+ status = dbus_connection_send_with_reply(conn, message, &pending, -1);
+ dbus_message_unref(message);
+
+ if (!(pending || status)) {
+ sway_log(L_ERROR, "Could not get items");
+ return;
+ }
+ dbus_pending_call_set_notify(pending, get_obj_items_reply, NULL, NULL);
}
static DBusHandlerResult signal_handler(DBusConnection *connection,
@@ -162,11 +248,14 @@ static DBusHandlerResult signal_handler(DBusConnection *connection,
}
int index;
- if ((index = list_seq_find(tray->items, sni_str_cmp, name)) != -1) {
+ bool found_item = false;
+ while ((index = list_seq_find(tray->items, sni_str_cmp, name)) != -1) {
+ found_item = true;
sni_free(tray->items->items[index]);
list_del(tray->items, index);
dirty = true;
- } else {
+ }
+ if (found_item == false) {
// If it's not in our list, then our list is incorrect.
// Fetch all items again
sway_log(L_INFO, "Host item list incorrect, refreshing");
@@ -189,6 +278,32 @@ static DBusHandlerResult signal_handler(DBusConnection *connection,
}
return DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_signal(message,
+ "org.swaywm.LessSuckyStatusNotifierWatcher",
+ "ObjPathItemRegistered")) {
+ const char *object_path;
+ const char *unique_name;
+ if (!dbus_message_get_args(message, NULL,
+ DBUS_TYPE_OBJECT_PATH, &object_path,
+ DBUS_TYPE_STRING, &unique_name,
+ DBUS_TYPE_INVALID)) {
+ sway_log(L_ERROR, "Error getting ObjPathItemRegistered args");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ // TODO allow one unique name to have multiple items
+ if (list_seq_find(tray->items, sni_str_cmp, unique_name) == -1) {
+ struct StatusNotifierItem *item =
+ sni_create_from_obj_path(unique_name,
+ object_path);
+
+ if (item) {
+ list_add(tray->items, item);
+ dirty = true;
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -255,6 +370,15 @@ static int init_host() {
sway_log(L_ERROR, "dbus_err: %s", error.message);
return -1;
}
+ dbus_bus_add_match(conn,
+ "type='signal',\
+ sender='org.freedesktop.StatusNotifierWatcher',\
+ member='ObjPathItemRegistered'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ sway_log(L_ERROR, "dbus_err: %s", error.message);
+ return -1;
+ }
// SNI matches
dbus_bus_add_match(conn,