aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalvin Lee <cyrus296@gmail.com>2017-11-09 12:58:32 -0700
committerCalvin Lee <cyrus296@gmail.com>2017-12-29 12:11:51 -0700
commit87035380e33c7da10b53c6da713c56f3d89a1577 (patch)
tree4b31ad282fe07227f5720928b1ba07715bc7ea48
parentb9f36716b52d4566609ac64be88b8a1f65602214 (diff)
Add `dbus_get_prop_async` utility
This drastically reduces the amount of boilerplate needed to get a property from a bus object.
-rw-r--r--include/swaybar/tray/dbus.h17
-rw-r--r--swaybar/tray/dbus.c90
-rw-r--r--swaybar/tray/sni.c184
-rw-r--r--swaybar/tray/tray.c139
4 files changed, 137 insertions, 293 deletions
diff --git a/include/swaybar/tray/dbus.h b/include/swaybar/tray/dbus.h
index 51754464..125ce96f 100644
--- a/include/swaybar/tray/dbus.h
+++ b/include/swaybar/tray/dbus.h
@@ -12,6 +12,23 @@ extern DBusConnection *conn;
bool dbus_message_iter_check_signature(DBusMessageIter *iter, const char *sig);
/**
+ * Fetches the property and calls `callback` with a message iter pointing it.
+ * Performs error handling and signature checking.
+ *
+ * Returns: true if message is successfully sent (will not necessarily arrive)
+ * and false otherwise
+ *
+ * NOTE: `expected_signature` must remain valid until the message reply is
+ * received, please only use 'static signatures.
+ */
+bool dbus_get_prop_async(const char *destination,
+ const char *path,
+ const char *iface,
+ const char *prop,
+ const char *expected_signature,
+ void(*callback)(DBusMessageIter *iter, void *data),
+ void *data);
+/**
* Should be called in main loop to dispatch events
*/
void dispatch_dbus();
diff --git a/swaybar/tray/dbus.c b/swaybar/tray/dbus.c
index 46a1c807..4439fb83 100644
--- a/swaybar/tray/dbus.c
+++ b/swaybar/tray/dbus.c
@@ -136,7 +136,58 @@ static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_s
}
}
-/* Public functions below */
+struct async_prop_data {
+ char const *sig;
+ void(*callback)(DBusMessageIter *, void *);
+ void *usr_data;
+};
+
+static void get_prop_callback(DBusPendingCall *pending, void *_data) {
+ struct async_prop_data *data = _data;
+
+ DBusMessage *reply = dbus_pending_call_steal_reply(pending);
+
+ if (!reply) {
+ sway_log(L_INFO, "Got no icon name reply from item");
+ goto bail;
+ }
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ char *msg;
+
+ dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_STRING, &msg,
+ DBUS_TYPE_INVALID);
+
+ sway_log(L_INFO, "Failure to get property: %s", msg);
+ goto bail;
+ }
+
+ DBusMessageIter iter;
+ DBusMessageIter variant;
+
+ dbus_message_iter_init(reply, &iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ sway_log(L_ERROR, "Property relpy type incorrect");
+ goto bail;
+ }
+ dbus_message_iter_recurse(&iter, &variant);
+
+ if (!dbus_message_iter_check_signature(&variant, data->sig)) {
+ sway_log(L_INFO, "Property returned has incorrect signatue.");
+ goto bail;
+ }
+
+ data->callback(&variant, data->usr_data);
+
+bail:
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+ dbus_pending_call_unref(pending);
+}
+
+/* Public functions below -- see header for docs*/
bool dbus_message_iter_check_signature(DBusMessageIter *iter, const char *sig) {
char *msg_sig = dbus_message_iter_get_signature(iter);
@@ -145,6 +196,43 @@ bool dbus_message_iter_check_signature(DBusMessageIter *iter, const char *sig) {
return (result == 0);
}
+bool dbus_get_prop_async(const char *destination,
+ const char *path, const char *iface,
+ const char *prop, const char *expected_signature,
+ void(*callback)(DBusMessageIter *, void *), void *usr_data) {
+ struct async_prop_data *data = malloc(sizeof(struct async_prop_data));
+ if (!data) {
+ return false;
+ }
+ DBusPendingCall *pending;
+ DBusMessage *message = dbus_message_new_method_call(
+ destination, path,
+ "org.freedesktop.DBus.Properties",
+ "Get");
+
+ dbus_message_append_args(message,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &prop,
+ DBUS_TYPE_INVALID);
+
+ bool status =
+ dbus_connection_send_with_reply(conn, message, &pending, -1);
+
+ dbus_message_unref(message);
+
+ if (!(pending || status)) {
+ sway_log(L_ERROR, "Could not get property");
+ return false;
+ }
+
+ data->sig = expected_signature;
+ data->callback = callback;
+ data->usr_data = usr_data;
+ dbus_pending_call_set_notify(pending, get_prop_callback, data, free);
+
+ return true;
+}
+
void dispatch_dbus() {
if (!should_dispatch || !conn) {
return;
diff --git a/swaybar/tray/sni.c b/swaybar/tray/sni.c
index 401a0091..200422da 100644
--- a/swaybar/tray/sni.c
+++ b/swaybar/tray/sni.c
@@ -14,6 +14,9 @@
#include "client/cairo.h"
#include "log.h"
+static const char *KDE_IFACE = "org.kde.StatusNotifierItem";
+static const char *FD_IFACE = "org.freedesktop.StatusNotifierItem";
+
// Not sure what this is but cairo needs it.
static const cairo_user_data_key_t cairo_user_data_key;
@@ -38,57 +41,19 @@ void sni_icon_ref_free(struct sni_icon_ref *sni_ref) {
}
/* Gets the pixmap of an icon */
-static void reply_icon(DBusPendingCall *pending, void *_data) {
+static void reply_icon(DBusMessageIter *iter /* a(iiay) */, void *_data) {
struct StatusNotifierItem *item = _data;
- DBusMessage *reply = dbus_pending_call_steal_reply(pending);
-
- if (!reply) {
- sway_log(L_ERROR, "Did not get reply");
- 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; /* v[a(iiay)] */
- DBusMessageIter array; /* a(iiay) */
DBusMessageIter d_struct; /* (iiay) */
DBusMessageIter icon; /* ay */
- dbus_message_iter_init(reply, &iter);
-
- // Each if here checks the types above before recursing
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- sway_log(L_ERROR, "Icon relpy type incorrect");
- goto bail;
- }
- dbus_message_iter_recurse(&iter, &variant);
-
- if (dbus_message_iter_check_signature(&variant, "a(iiay)")) {
- sway_log(L_ERROR, "Icon relpy type incorrect");
- goto bail;
- }
-
- if (dbus_message_iter_get_element_count(&variant) == 0) {
+ if (dbus_message_iter_get_element_count(iter) == 0) {
// Can't recurse if there are no items
sway_log(L_INFO, "Item has no icon");
- goto bail;
+ return;
}
- dbus_message_iter_recurse(&variant, &array);
- dbus_message_iter_recurse(&array, &d_struct);
+ dbus_message_iter_recurse(iter, &d_struct);
int width;
dbus_message_iter_get_basic(&d_struct, &width);
@@ -102,13 +67,13 @@ static void reply_icon(DBusPendingCall *pending, void *_data) {
if (!len) {
sway_log(L_ERROR, "No icon data");
- goto bail;
+ return;
}
// Also implies len % 4 == 0, useful below
if (len != width * height * 4) {
sway_log(L_ERROR, "Incorrect array size passed");
- goto bail;
+ return;
}
dbus_message_iter_recurse(&d_struct, &icon);
@@ -117,7 +82,7 @@ static void reply_icon(DBusPendingCall *pending, void *_data) {
// FIXME support a variable stride
// (works on my machine though for all tested widths)
if (!sway_assert(stride == width * 4, "Stride must be equal to byte length")) {
- goto bail;
+ return;
}
// Data is by reference, no need to free
@@ -127,7 +92,7 @@ static void reply_icon(DBusPendingCall *pending, void *_data) {
uint8_t *image_data = malloc(stride * height);
if (!image_data) {
sway_log(L_ERROR, "Could not allocate memory for icon");
- goto bail;
+ return;
}
// Transform from network byte order to host byte order
@@ -155,97 +120,22 @@ static void reply_icon(DBusPendingCall *pending, void *_data) {
item->dirty = true;
dirty = true;
- dbus_message_unref(reply);
- dbus_pending_call_unref(pending);
return;
} else {
sway_log(L_ERROR, "Could not create image surface");
free(image_data);
}
-bail:
- if (reply) {
- dbus_message_unref(reply);
- }
- dbus_pending_call_unref(pending);
sway_log(L_ERROR, "Could not get icon from item");
return;
}
-static void send_icon_msg(struct StatusNotifierItem *item) {
- DBusPendingCall *pending;
- DBusMessage *message = dbus_message_new_method_call(
- item->name,
- item->object_path,
- "org.freedesktop.DBus.Properties",
- "Get");
- const char *iface;
- if (item->kde_special_snowflake) {
- iface = "org.kde.StatusNotifierItem";
- } else {
- iface = "org.freedesktop.StatusNotifierItem";
- }
- const char *prop = "IconPixmap";
-
- dbus_message_append_args(message,
- DBUS_TYPE_STRING, &iface,
- DBUS_TYPE_STRING, &prop,
- DBUS_TYPE_INVALID);
-
- bool status =
- dbus_connection_send_with_reply(conn, message, &pending, -1);
-
- dbus_message_unref(message);
-
- if (!(pending || status)) {
- sway_log(L_ERROR, "Could not get item icon");
- return;
- }
-
- dbus_pending_call_set_notify(pending, reply_icon, item, NULL);
-}
/* Get an icon by its name */
-static void reply_icon_name(DBusPendingCall *pending, void *_data) {
+static void reply_icon_name(DBusMessageIter *iter, void *_data) {
struct StatusNotifierItem *item = _data;
- DBusMessage *reply = dbus_pending_call_steal_reply(pending);
-
- if (!reply) {
- sway_log(L_INFO, "Got no icon name reply from item");
- 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_INFO, "Could not get icon name: %s", msg);
- goto bail;
- }
-
- DBusMessageIter iter; /* v[s] */
- DBusMessageIter variant; /* s */
-
- dbus_message_iter_init(reply, &iter);
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- sway_log(L_ERROR, "Icon name relpy type incorrect");
- goto bail;
- }
- dbus_message_iter_recurse(&iter, &variant);
-
-
- if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_STRING) {
- sway_log(L_ERROR, "Icon name relpy type incorrect");
- goto bail;
- }
-
char *icon_name;
- dbus_message_iter_get_basic(&variant, &icon_name);
+ dbus_message_iter_get_basic(iter, &icon_name);
cairo_surface_t *image = find_icon(icon_name, 256);
@@ -259,55 +149,19 @@ static void reply_icon_name(DBusPendingCall *pending, void *_data) {
item->dirty = true;
dirty = true;
- dbus_message_unref(reply);
- dbus_pending_call_unref(pending);
return;
}
-bail:
- if (reply) {
- dbus_message_unref(reply);
- }
- dbus_pending_call_unref(pending);
// Now try the pixmap
- send_icon_msg(item);
- return;
-}
-static void send_icon_name_msg(struct StatusNotifierItem *item) {
- DBusPendingCall *pending;
- DBusMessage *message = dbus_message_new_method_call(
- item->name,
- item->object_path,
- "org.freedesktop.DBus.Properties",
- "Get");
- const char *iface;
- if (item->kde_special_snowflake) {
- iface = "org.kde.StatusNotifierItem";
- } else {
- iface = "org.freedesktop.StatusNotifierItem";
- }
- const char *prop = "IconName";
-
- dbus_message_append_args(message,
- DBUS_TYPE_STRING, &iface,
- DBUS_TYPE_STRING, &prop,
- DBUS_TYPE_INVALID);
-
- bool status =
- dbus_connection_send_with_reply(conn, message, &pending, -1);
-
- dbus_message_unref(message);
-
- if (!(pending || status)) {
- sway_log(L_ERROR, "Could not get item icon name");
- return;
- }
-
- dbus_pending_call_set_notify(pending, reply_icon_name, item, NULL);
+ dbus_get_prop_async(item->name, item->object_path,
+ (item->kde_special_snowflake ? KDE_IFACE : FD_IFACE),
+ "IconPixmap", "a(iiay)", reply_icon, item);
}
void get_icon(struct StatusNotifierItem *item) {
- send_icon_name_msg(item);
+ dbus_get_prop_async(item->name, item->object_path,
+ (item->kde_special_snowflake ? KDE_IFACE : FD_IFACE),
+ "IconName", "s", reply_icon_name, item);
}
void sni_activate(struct StatusNotifierItem *item, uint32_t x, uint32_t y) {
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c
index f1ecb429..89e7c3e2 100644
--- a/swaybar/tray/tray.c
+++ b/swaybar/tray/tray.c
@@ -38,47 +38,13 @@ static void register_host(char *name) {
dbus_message_unref(message);
}
-static void get_items_reply(DBusPendingCall *pending, void *_data) {
- DBusMessage *reply = dbus_pending_call_steal_reply(pending);
-
- if (!reply) {
- sway_log(L_ERROR, "Got no 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;
+static void get_items_reply(DBusMessageIter *iter, void *_data) {
DBusMessageIter array;
- 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(as)");
- goto bail;
- }
- dbus_message_iter_recurse(&iter, &variant);
- if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&variant) != DBUS_TYPE_STRING) {
- sway_log(L_ERROR, "Replyed with wrong type, not v(as)");
- goto bail;
- }
-
// O(n) function, could be faster dynamically reading values
- int len = dbus_message_iter_get_element_count(&variant);
+ int len = dbus_message_iter_get_element_count(iter);
- dbus_message_iter_recurse(&variant, &array);
+ dbus_message_iter_recurse(iter, &array);
for (int i = 0; i < len; i++) {
const char *name;
dbus_message_iter_get_basic(&array, &name);
@@ -93,52 +59,14 @@ static void get_items_reply(DBusPendingCall *pending, void *_data) {
}
}
}
-
-bail:
- dbus_message_unref(reply);
- 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;
+static void get_obj_items_reply(DBusMessageIter *iter, void *_data) {
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 (dbus_message_iter_check_signature(&iter, "a(os)")) {
- sway_log(L_ERROR, "Replyed with wrong type not a(os)");
- goto bail;
- }
-
- int len = dbus_message_iter_get_element_count(&variant);
+ int len = dbus_message_iter_get_element_count(iter);
- dbus_message_iter_recurse(&variant, &array);
+ dbus_message_iter_recurse(iter, &array);
for (int i = 0; i < len; i++) {
const char *object_path;
const char *unique_name;
@@ -164,10 +92,6 @@ static void get_obj_items_reply(DBusPendingCall *pending, void *_data) {
}
}
}
-
-bail:
- dbus_message_unref(reply);
- dbus_pending_call_unref(pending);
}
static void get_items() {
@@ -176,52 +100,13 @@ static void get_items() {
list_free(tray->items);
tray->items = create_list();
- DBusPendingCall *pending;
- DBusMessage *message = dbus_message_new_method_call(
- "org.freedesktop.StatusNotifierWatcher",
- "/StatusNotifierWatcher",
- "org.freedesktop.DBus.Properties",
- "Get");
-
- const char *iface = "org.freedesktop.StatusNotifierWatcher";
- const char *prop = "RegisteredStatusNotifierItems";
- dbus_message_append_args(message,
- DBUS_TYPE_STRING, &iface,
- DBUS_TYPE_STRING, &prop,
- DBUS_TYPE_INVALID);
-
- bool 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_items_reply, NULL, NULL);
+ dbus_get_prop_async("org.freedesktop.StatusNotifierWatcher",
+ "/StatusNotifierWatcher","org.freedesktop.StatusNotifierWatcher",
+ "RegisteredStatusNotifierItems", "as", get_items_reply, 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);
+ dbus_get_prop_async("org.freedesktop.StatusNotifierWatcher",
+ "/StatusNotifierWatcher","org.swaywm.LessSuckyStatusNotifierWatcher",
+ "RegisteredObjectPathItems", "a(os)", get_obj_items_reply, NULL);
}
static DBusHandlerResult signal_handler(DBusConnection *connection,