diff options
| author | Calvin Lee <cyrus296@gmail.com> | 2017-10-24 11:59:42 -0600 |
|---|---|---|
| committer | Calvin Lee <cyrus296@gmail.com> | 2017-12-29 12:11:51 -0700 |
| commit | ad99d9dff8f8e8ee78b5195d6ca440af130f6ab6 (patch) | |
| tree | c8ca022e7a61922dc6d3303e944c9b364ed89848 /swaybar/tray/tray.c | |
| parent | d85ad05fa857cd7d7af2c8e2c33616d7895e1955 (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.c | 128 |
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, |
