mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #3372 from ianyfan/tray
swaybar: handle SNI signals better
This commit is contained in:
		
						commit
						cfdb614e84
					
				
					 5 changed files with 98 additions and 65 deletions
				
			
		| 
						 | 
					@ -35,6 +35,10 @@ struct swaybar_sni {
 | 
				
			||||||
	bool item_is_menu;
 | 
						bool item_is_menu;
 | 
				
			||||||
	char *menu;
 | 
						char *menu;
 | 
				
			||||||
	char *icon_theme_path; // non-standard KDE property
 | 
						char *icon_theme_path; // non-standard KDE property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sd_bus_slot *new_icon_slot;
 | 
				
			||||||
 | 
						sd_bus_slot *new_attention_icon_slot;
 | 
				
			||||||
 | 
						sd_bus_slot *new_status_slot;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray);
 | 
					struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,7 @@ int main(int argc, char **argv) {
 | 
				
			||||||
	if (debug) {
 | 
						if (debug) {
 | 
				
			||||||
		wlr_log_init(WLR_DEBUG, NULL);
 | 
							wlr_log_init(WLR_DEBUG, NULL);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		wlr_log_init(WLR_ERROR, NULL);
 | 
							wlr_log_init(WLR_INFO, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!swaybar.id) {
 | 
						if (!swaybar.id) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
 | 
				
			||||||
static void add_sni(struct swaybar_tray *tray, char *id) {
 | 
					static void add_sni(struct swaybar_tray *tray, char *id) {
 | 
				
			||||||
	int idx = list_seq_find(tray->items, cmp_sni_id, id);
 | 
						int idx = list_seq_find(tray->items, cmp_sni_id, id);
 | 
				
			||||||
	if (idx == -1) {
 | 
						if (idx == -1) {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Registering Status Notifier Item '%s'", id);
 | 
							wlr_log(WLR_INFO, "Registering Status Notifier Item '%s'", id);
 | 
				
			||||||
		struct swaybar_sni *sni = create_sni(id, tray);
 | 
							struct swaybar_sni *sni = create_sni(id, tray);
 | 
				
			||||||
		if (sni) {
 | 
							if (sni) {
 | 
				
			||||||
			list_add(tray->items, sni);
 | 
								list_add(tray->items, sni);
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ static int handle_sni_unregistered(sd_bus_message *msg, void *data,
 | 
				
			||||||
	struct swaybar_tray *tray = data;
 | 
						struct swaybar_tray *tray = data;
 | 
				
			||||||
	int idx = list_seq_find(tray->items, cmp_sni_id, id);
 | 
						int idx = list_seq_find(tray->items, cmp_sni_id, id);
 | 
				
			||||||
	if (idx != -1) {
 | 
						if (idx != -1) {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Unregistering Status Notifier Item '%s'", id);
 | 
							wlr_log(WLR_INFO, "Unregistering Status Notifier Item '%s'", id);
 | 
				
			||||||
		destroy_sni(tray->items->items[idx]);
 | 
							destroy_sni(tray->items->items[idx]);
 | 
				
			||||||
		list_del(tray->items, idx);
 | 
							list_del(tray->items, idx);
 | 
				
			||||||
		set_bar_dirty(tray->bar);
 | 
							set_bar_dirty(tray->bar);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@
 | 
				
			||||||
// TODO menu
 | 
					// TODO menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool sni_ready(struct swaybar_sni *sni) {
 | 
					static bool sni_ready(struct swaybar_sni *sni) {
 | 
				
			||||||
	return sni->status && (sni->status[0] == 'N' ?
 | 
						return sni->status && (sni->status[0] == 'N' ? // NeedsAttention
 | 
				
			||||||
			sni->attention_icon_name || sni->attention_icon_pixmap :
 | 
								sni->attention_icon_name || sni->attention_icon_pixmap :
 | 
				
			||||||
			sni->icon_name || sni->icon_pixmap);
 | 
								sni->icon_name || sni->icon_pixmap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -35,11 +35,12 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
 | 
				
			||||||
		const char *prop, list_t **dest) {
 | 
							const char *prop, list_t **dest) {
 | 
				
			||||||
	int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)");
 | 
						int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)");
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
 | 
							wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sd_bus_message_at_end(msg, 0)) {
 | 
						if (sd_bus_message_at_end(msg, 0)) {
 | 
				
			||||||
 | 
							wlr_log(WLR_DEBUG, "%s %s no. of icons = 0", sni->watcher_id, prop);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,14 +52,14 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
 | 
				
			||||||
	while (!sd_bus_message_at_end(msg, 0)) {
 | 
						while (!sd_bus_message_at_end(msg, 0)) {
 | 
				
			||||||
		ret = sd_bus_message_enter_container(msg, 'r', "iiay");
 | 
							ret = sd_bus_message_enter_container(msg, 'r', "iiay");
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0) {
 | 
				
			||||||
			wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
 | 
								wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int size;
 | 
							int size;
 | 
				
			||||||
		ret = sd_bus_message_read(msg, "ii", NULL, &size);
 | 
							ret = sd_bus_message_read(msg, "ii", NULL, &size);
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0) {
 | 
				
			||||||
			wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
 | 
								wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,7 +67,7 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
 | 
				
			||||||
		size_t npixels;
 | 
							size_t npixels;
 | 
				
			||||||
		ret = sd_bus_message_read_array(msg, 'y', &pixels, &npixels);
 | 
							ret = sd_bus_message_read_array(msg, 'y', &pixels, &npixels);
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0) {
 | 
				
			||||||
			wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
 | 
								wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,7 +79,10 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sd_bus_message_exit_container(msg);
 | 
							sd_bus_message_exit_container(msg);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						list_free_items_and_destroy(*dest);
 | 
				
			||||||
	*dest = pixmaps;
 | 
						*dest = pixmaps;
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "%s %s no. of icons = %d", sni->watcher_id, prop,
 | 
				
			||||||
 | 
								pixmaps->length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
| 
						 | 
					@ -103,15 +107,15 @@ static int get_property_callback(sd_bus_message *msg, void *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	if (sd_bus_message_is_method_error(msg, NULL)) {
 | 
						if (sd_bus_message_is_method_error(msg, NULL)) {
 | 
				
			||||||
		sd_bus_error err = *sd_bus_message_get_error(msg);
 | 
							wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop,
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, err.message);
 | 
									sd_bus_message_get_error(msg)->message);
 | 
				
			||||||
		ret = -sd_bus_error_get_errno(&err);
 | 
							ret = sd_bus_message_get_errno(msg);
 | 
				
			||||||
		goto cleanup;
 | 
							goto cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = sd_bus_message_enter_container(msg, 'v', type);
 | 
						ret = sd_bus_message_enter_container(msg, 'v', type);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop, strerror(-ret));
 | 
							wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
		goto cleanup;
 | 
							goto cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,14 +125,23 @@ static int get_property_callback(sd_bus_message *msg, void *data,
 | 
				
			||||||
			goto cleanup;
 | 
								goto cleanup;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							if (*type == 's' || *type == 'o') {
 | 
				
			||||||
 | 
								free(*(char **)dest);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = sd_bus_message_read(msg, type, dest);
 | 
							ret = sd_bus_message_read(msg, type, dest);
 | 
				
			||||||
		if (ret < 0) {
 | 
							if (ret < 0) {
 | 
				
			||||||
			wlr_log(WLR_DEBUG, "Failed to read property %s: %s", prop,
 | 
								wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
					strerror(-ret));
 | 
					 | 
				
			||||||
			goto cleanup;
 | 
								goto cleanup;
 | 
				
			||||||
		} else if (*type == 's' || *type == 'o') {
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (*type == 's' || *type == 'o') {
 | 
				
			||||||
			char **str = dest;
 | 
								char **str = dest;
 | 
				
			||||||
			*str = strdup(*str);
 | 
								*str = strdup(*str);
 | 
				
			||||||
 | 
								wlr_log(WLR_DEBUG, "%s %s = '%s'", sni->watcher_id, prop, *str);
 | 
				
			||||||
 | 
							} else if (*type == 'b') {
 | 
				
			||||||
 | 
								wlr_log(WLR_DEBUG, "%s %s = %s", sni->watcher_id, prop,
 | 
				
			||||||
 | 
										*(bool *)dest ? "true" : "false");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,62 +165,80 @@ static void sni_get_property_async(struct swaybar_sni *sni, const char *prop,
 | 
				
			||||||
			sni->path, "org.freedesktop.DBus.Properties", "Get",
 | 
								sni->path, "org.freedesktop.DBus.Properties", "Get",
 | 
				
			||||||
			get_property_callback, data, "ss", sni->interface, prop);
 | 
								get_property_callback, data, "ss", sni->interface, prop);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Failed to get property %s: %s", prop, strerror(-ret));
 | 
							wlr_log(WLR_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * There is a quirk in sd-bus that in some systems, it is unable to get the
 | 
				
			||||||
 | 
					 * well-known names on the bus, so it cannot identify if an incoming signal,
 | 
				
			||||||
 | 
					 * which uses the sender's unique name, actually matches the callback's matching
 | 
				
			||||||
 | 
					 * sender if the callback uses a well-known name, in which case it just calls
 | 
				
			||||||
 | 
					 * the callback and hopes for the best, resulting in false positives. In the
 | 
				
			||||||
 | 
					 * case of NewIcon & NewAttentionIcon, this doesn't affect anything, but it
 | 
				
			||||||
 | 
					 * means that for NewStatus, if the SNI does not definitely match the sender,
 | 
				
			||||||
 | 
					 * then the safe thing to do is to query the status independently.
 | 
				
			||||||
 | 
					 * This function returns 1 if the SNI definitely matches the signal sender,
 | 
				
			||||||
 | 
					 * which is returned by the calling function to indicate that signal matching
 | 
				
			||||||
 | 
					 * can stop since it has already found the required callback, otherwise, it
 | 
				
			||||||
 | 
					 * returns 0, which allows matching to continue.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int sni_check_msg_sender(struct swaybar_sni *sni, sd_bus_message *msg,
 | 
				
			||||||
 | 
							const char *signal) {
 | 
				
			||||||
 | 
						bool has_well_known_names =
 | 
				
			||||||
 | 
							sd_bus_creds_get_mask(sd_bus_message_get_creds(msg)) & SD_BUS_CREDS_WELL_KNOWN_NAMES;
 | 
				
			||||||
 | 
						if (sni->service[0] == ':' || has_well_known_names) {
 | 
				
			||||||
 | 
							wlr_log(WLR_DEBUG, "%s has new %s", sni->watcher_id, signal);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							wlr_log(WLR_DEBUG, "%s may have new %s", sni->watcher_id, signal);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int handle_new_icon(sd_bus_message *msg, void *data, sd_bus_error *error) {
 | 
					static int handle_new_icon(sd_bus_message *msg, void *data, sd_bus_error *error) {
 | 
				
			||||||
	struct swaybar_sni *sni = data;
 | 
						struct swaybar_sni *sni = data;
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "%s has new IconName", sni->watcher_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(sni->icon_name);
 | 
					 | 
				
			||||||
	sni->icon_name = NULL;
 | 
					 | 
				
			||||||
	sni_get_property_async(sni, "IconName", "s", &sni->icon_name);
 | 
						sni_get_property_async(sni, "IconName", "s", &sni->icon_name);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	list_free_items_and_destroy(sni->icon_pixmap);
 | 
					 | 
				
			||||||
	sni->icon_pixmap = NULL;
 | 
					 | 
				
			||||||
	sni_get_property_async(sni, "IconPixmap", NULL, &sni->icon_pixmap);
 | 
						sni_get_property_async(sni, "IconPixmap", NULL, &sni->icon_pixmap);
 | 
				
			||||||
 | 
						return sni_check_msg_sender(sni, msg, "icon");
 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int handle_new_attention_icon(sd_bus_message *msg, void *data,
 | 
					static int handle_new_attention_icon(sd_bus_message *msg, void *data,
 | 
				
			||||||
		sd_bus_error *error) {
 | 
							sd_bus_error *error) {
 | 
				
			||||||
	struct swaybar_sni *sni = data;
 | 
						struct swaybar_sni *sni = data;
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "%s has new AttentionIconName", sni->watcher_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(sni->attention_icon_name);
 | 
					 | 
				
			||||||
	sni->attention_icon_name = NULL;
 | 
					 | 
				
			||||||
	sni_get_property_async(sni, "AttentionIconName", "s", &sni->attention_icon_name);
 | 
						sni_get_property_async(sni, "AttentionIconName", "s", &sni->attention_icon_name);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	list_free_items_and_destroy(sni->attention_icon_pixmap);
 | 
					 | 
				
			||||||
	sni->attention_icon_pixmap = NULL;
 | 
					 | 
				
			||||||
	sni_get_property_async(sni, "AttentionIconPixmap", NULL, &sni->attention_icon_pixmap);
 | 
						sni_get_property_async(sni, "AttentionIconPixmap", NULL, &sni->attention_icon_pixmap);
 | 
				
			||||||
 | 
						return sni_check_msg_sender(sni, msg, "attention icon");
 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *error) {
 | 
					static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *error) {
 | 
				
			||||||
	char *status;
 | 
					 | 
				
			||||||
	int ret = sd_bus_message_read(msg, "s", &status);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Failed to read new status message: %s", strerror(-ret));
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
	struct swaybar_sni *sni = data;
 | 
						struct swaybar_sni *sni = data;
 | 
				
			||||||
 | 
						int ret = sni_check_msg_sender(sni, msg, "status");
 | 
				
			||||||
 | 
						if (ret == 1) {
 | 
				
			||||||
 | 
							char *status;
 | 
				
			||||||
 | 
							int r = sd_bus_message_read(msg, "s", &status);
 | 
				
			||||||
 | 
							if (r < 0) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "%s new status error: %s", sni->watcher_id, strerror(-ret));
 | 
				
			||||||
 | 
								ret = r;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			free(sni->status);
 | 
								free(sni->status);
 | 
				
			||||||
			sni->status = strdup(status);
 | 
								sni->status = strdup(status);
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "%s has new Status '%s'", sni->watcher_id, status);
 | 
								wlr_log(WLR_DEBUG, "%s has new status = '%s'", sni->watcher_id, status);
 | 
				
			||||||
			set_sni_dirty(sni);
 | 
								set_sni_dirty(sni);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							sni_get_property_async(sni, "Status", "s", &sni->status);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sni_match_signal(struct swaybar_sni *sni, char *signal,
 | 
					static void sni_match_signal(struct swaybar_sni *sni, sd_bus_slot **slot,
 | 
				
			||||||
		sd_bus_message_handler_t callback) {
 | 
							char *signal, sd_bus_message_handler_t callback) {
 | 
				
			||||||
	int ret = sd_bus_match_signal(sni->tray->bus, NULL, sni->service, sni->path,
 | 
						int ret = sd_bus_match_signal(sni->tray->bus, slot, sni->service, sni->path,
 | 
				
			||||||
			sni->interface, signal, callback, sni);
 | 
								sni->interface, signal, callback, sni);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Failed to subscribe to signal %s: %s", signal,
 | 
							wlr_log(WLR_ERROR, "Failed to subscribe to signal %s: %s", signal,
 | 
				
			||||||
				strerror(-ret));
 | 
									strerror(-ret));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -241,9 +272,10 @@ struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray) {
 | 
				
			||||||
	sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu);
 | 
						sni_get_property_async(sni, "ItemIsMenu", "b", &sni->item_is_menu);
 | 
				
			||||||
	sni_get_property_async(sni, "Menu", "o", &sni->menu);
 | 
						sni_get_property_async(sni, "Menu", "o", &sni->menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sni_match_signal(sni, "NewIcon", handle_new_icon);
 | 
						sni_match_signal(sni, &sni->new_icon_slot, "NewIcon", handle_new_icon);
 | 
				
			||||||
	sni_match_signal(sni, "NewAttentionIcon", handle_new_attention_icon);
 | 
						sni_match_signal(sni, &sni->new_attention_icon_slot, "NewAttentionIcon",
 | 
				
			||||||
	sni_match_signal(sni, "NewStatus", handle_new_status);
 | 
								handle_new_attention_icon);
 | 
				
			||||||
 | 
						sni_match_signal(sni, &sni->new_status_slot, "NewStatus", handle_new_status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sni;
 | 
						return sni;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -253,6 +285,10 @@ void destroy_sni(struct swaybar_sni *sni) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sd_bus_slot_unref(sni->new_icon_slot);
 | 
				
			||||||
 | 
						sd_bus_slot_unref(sni->new_attention_icon_slot);
 | 
				
			||||||
 | 
						sd_bus_slot_unref(sni->new_status_slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(sni->watcher_id);
 | 
						free(sni->watcher_id);
 | 
				
			||||||
	free(sni->service);
 | 
						free(sni->service);
 | 
				
			||||||
	free(sni->path);
 | 
						free(sni->path);
 | 
				
			||||||
| 
						 | 
					@ -294,18 +330,11 @@ static void handle_click(struct swaybar_sni *sni, int x, int y,
 | 
				
			||||||
		char *orientation = (dir = 'U' || dir == 'D') ? "vertical" : "horizontal";
 | 
							char *orientation = (dir = 'U' || dir == 'D') ? "vertical" : "horizontal";
 | 
				
			||||||
		int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
 | 
							int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service,
 | 
							sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, sni->path,
 | 
				
			||||||
				sni->path, sni->interface, "Scroll", NULL, NULL, "is",
 | 
									sni->interface, "Scroll", NULL, NULL, "is", delta*sign, orientation);
 | 
				
			||||||
				delta*sign, orientation);
 | 
					 | 
				
			||||||
		if (ret < 0) {
 | 
					 | 
				
			||||||
			wlr_log(WLR_DEBUG, "Failed to scroll on SNI: %s", strerror(-ret));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		int ret = sd_bus_call_method_async(sni->tray->bus, NULL, sni->service,
 | 
							sd_bus_call_method_async(sni->tray->bus, NULL, sni->service, sni->path,
 | 
				
			||||||
				sni->path, sni->interface, method, NULL, NULL, "ii", x, y);
 | 
									sni->interface, method, NULL, NULL, "ii", x, y);
 | 
				
			||||||
		if (ret < 0) {
 | 
					 | 
				
			||||||
			wlr_log(WLR_DEBUG, "Failed to click on SNI: %s", strerror(-ret));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -317,7 +346,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
 | 
				
			||||||
static enum hotspot_event_handling icon_hotspot_callback(
 | 
					static enum hotspot_event_handling icon_hotspot_callback(
 | 
				
			||||||
		struct swaybar_output *output, struct swaybar_hotspot *hotspot,
 | 
							struct swaybar_output *output, struct swaybar_hotspot *hotspot,
 | 
				
			||||||
		int x, int y, enum x11_button button, void *data) {
 | 
							int x, int y, enum x11_button button, void *data) {
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "Clicked on Status Notifier Item '%s'", (char *)data);
 | 
						wlr_log(WLR_DEBUG, "Clicked on %s", (char *)data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct swaybar_tray *tray = output->bar->tray;
 | 
						struct swaybar_tray *tray = output->bar->tray;
 | 
				
			||||||
	int idx = list_seq_find(tray->items, cmp_sni_id, data);
 | 
						int idx = list_seq_find(tray->items, cmp_sni_id, data);
 | 
				
			||||||
| 
						 | 
					@ -331,7 +360,7 @@ static enum hotspot_event_handling icon_hotspot_callback(
 | 
				
			||||||
		int global_y = output->output_y + (top_bar ? config->gaps.top + y:
 | 
							int global_y = output->output_y + (top_bar ? config->gaps.top + y:
 | 
				
			||||||
				(int) output->output_height - config->gaps.bottom - y);
 | 
									(int) output->output_height - config->gaps.bottom - y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "Guessing click at (%d, %d)", global_x, global_y);
 | 
							wlr_log(WLR_DEBUG, "Guessing click position at (%d, %d)", global_x, global_y);
 | 
				
			||||||
		handle_click(sni, global_x, global_y, button, 1); // TODO get delta from event
 | 
							handle_click(sni, global_x, global_y, button, 1); // TODO get delta from event
 | 
				
			||||||
		return HOTSPOT_IGNORE;
 | 
							return HOTSPOT_IGNORE;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -396,7 +425,7 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
 | 
				
			||||||
		icon_size = actual_size < ideal_size ?
 | 
							icon_size = actual_size < ideal_size ?
 | 
				
			||||||
			actual_size*(ideal_size/actual_size) : ideal_size;
 | 
								actual_size*(ideal_size/actual_size) : ideal_size;
 | 
				
			||||||
		icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size);
 | 
							icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size);
 | 
				
			||||||
	} else { // draw a sad face
 | 
						} else { // draw a :(
 | 
				
			||||||
		icon_size = ideal_size*0.8;
 | 
							icon_size = ideal_size*0.8;
 | 
				
			||||||
		icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size);
 | 
							icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size);
 | 
				
			||||||
		cairo_t *cairo_icon = cairo_create(icon);
 | 
							cairo_t *cairo_icon = cairo_create(icon);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ void destroy_tray(struct swaybar_tray *tray) {
 | 
				
			||||||
	finish_host(&tray->host_xdg);
 | 
						finish_host(&tray->host_xdg);
 | 
				
			||||||
	finish_host(&tray->host_kde);
 | 
						finish_host(&tray->host_kde);
 | 
				
			||||||
	for (int i = 0; i < tray->items->length; ++i) {
 | 
						for (int i = 0; i < tray->items->length; ++i) {
 | 
				
			||||||
		destroy_sni(tray->items->items[0]);
 | 
							destroy_sni(tray->items->items[i]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list_free(tray->items);
 | 
						list_free(tray->items);
 | 
				
			||||||
	destroy_watcher(tray->watcher_xdg);
 | 
						destroy_watcher(tray->watcher_xdg);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue