Hello community, here is the log from the commit of package mako for openSUSE:Factory checked in at 2019-07-22 12:21:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mako (Old) and /work/SRC/openSUSE:Factory/.mako.new.4126 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mako" Mon Jul 22 12:21:37 2019 rev:3 rq:717447 version:1.4 Changes: -------- --- /work/SRC/openSUSE:Factory/mako/mako.changes 2019-04-23 14:37:14.301519484 +0200 +++ /work/SRC/openSUSE:Factory/.mako.new.4126/mako.changes 2019-07-22 12:21:39.639644369 +0200 @@ -1,0 +2,11 @@ +Sat Jul 20 17:41:42 UTC 2019 - Michael Aquilina <michaelaquil...@gmail.com> + +- Update to 1.4 + * Icon support is now complete + * Touchscreens are now supported + * makoctl can now list current notifications + * makoctl can now list and invoke notification actions + * A D-Bus service file has been added + * Various bug fixes + +------------------------------------------------------------------- Old: ---- v1.3.tar.gz New: ---- v1.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mako.spec ++++++ --- /var/tmp/diff_new_pack.Oen5Wd/_old 2019-07-22 12:21:40.211644220 +0200 +++ /var/tmp/diff_new_pack.Oen5Wd/_new 2019-07-22 12:21:40.215644218 +0200 @@ -12,12 +12,12 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # Name: mako -Version: 1.3 +Version: 1.4 Release: 0 Summary: A Wayland notification daemon License: MIT @@ -50,6 +50,9 @@ %files %license LICENSE %doc README.md +%dir %{_datadir}/dbus-1/ +%dir %{_datadir}/dbus-1/services/ +%{_datadir}/dbus-1/services/fr.emersion.mako.service %{_bindir}/%{name}* %{_mandir}/man?/%{name}* ++++++ v1.3.tar.gz -> v1.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/README.md new/mako-1.4/README.md --- old/mako-1.3/README.md 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/README.md 2019-07-19 12:57:01.000000000 +0200 @@ -6,6 +6,8 @@ <img src="https://sr.ht/meoc.png" alt="mako screenshot"> </p> +Feel free to join the IRC channel: ##emersion on irc.freenode.net. + ## Running If you're using Sway you can start mako on launch by putting `exec mako` in @@ -23,7 +25,8 @@ * pango * cairo * systemd or elogind (for the sd-bus library) -* dbus (with user-session support) +* gdk-pixbuf (optional, for icons support) +* dbus (runtime dependency, user-session support is required) Then run: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/config.c new/mako-1.4/config.c --- old/mako-1.3/config.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/config.c 2019-07-19 12:57:01.000000000 +0200 @@ -58,9 +58,10 @@ config->sort_criteria = MAKO_SORT_CRITERIA_TIME; config->sort_asc = 0; - config->button_bindings.left = MAKO_BUTTON_BINDING_INVOKE_DEFAULT_ACTION; - config->button_bindings.right = MAKO_BUTTON_BINDING_DISMISS; - config->button_bindings.middle = MAKO_BUTTON_BINDING_NONE; + config->button_bindings.left = MAKO_BINDING_INVOKE_DEFAULT_ACTION; + config->button_bindings.right = MAKO_BINDING_DISMISS; + config->button_bindings.middle = MAKO_BINDING_NONE; + config->touch = MAKO_BINDING_DISMISS; config->anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/criteria.c new/mako-1.4/criteria.c --- old/mako-1.3/criteria.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/criteria.c 2019-07-19 12:57:01.000000000 +0200 @@ -262,8 +262,13 @@ } criteria->spec.group_index = true; return true; + } else if (strcmp(key, "summary") == 0) { + // TODO: convert to regex, currently only exact matching + criteria->summary = strdup(value); + criteria->spec.summary = true; + return true; } else { - // TODO: summary + body, once we support regex and they're useful. + // TODO: body, once we support regex and they're useful. // Anything left must be one of the boolean fields, defined using // standard syntax. Continue on. } @@ -305,7 +310,7 @@ assert(false && "Criteria parser fell through"); } -// Retreive the global critiera from a given mako_config. This just so happens +// Retreive the global criteria from a given mako_config. This just so happens // to be the first criteria in the list. struct mako_criteria *global_criteria(struct mako_config *config) { struct mako_criteria *criteria = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/dbus/dbus.c new/mako-1.4/dbus/dbus.c --- old/mako-1.3/dbus/dbus.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/dbus/dbus.c 2019-07-19 12:57:01.000000000 +0200 @@ -32,6 +32,9 @@ ret = sd_bus_request_name(state->bus, service_name, 0); if (ret < 0) { fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-ret)); + if (ret == -EEXIST) { + fprintf(stderr, "Is a notification daemon already running?\n"); + } goto error; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/dbus/mako.c new/mako-1.4/dbus/mako.c --- old/mako-1.3/dbus/mako.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/dbus/mako.c 2019-07-19 12:57:01.000000000 +0200 @@ -45,22 +45,31 @@ sd_bus_error *ret_error) { struct mako_state *state = data; + uint32_t id = 0; const char *action_key; - int ret = sd_bus_message_read(msg, "s", &action_key); + int ret = sd_bus_message_read(msg, "us", &id, &action_key); if (ret < 0) { return ret; } + if (id == 0) { + id = state->last_id; + } + if (wl_list_empty(&state->notifications)) { goto done; } - struct mako_notification *notif = - wl_container_of(state->notifications.next, notif, link); - struct mako_action *action; - wl_list_for_each(action, ¬if->actions, link) { - if (strcmp(action->key, action_key) == 0) { - notify_action_invoked(action); + struct mako_notification *notif; + wl_list_for_each(notif, &state->notifications, link) { + if (notif->id == id) { + struct mako_action *action; + wl_list_for_each(action, ¬if->actions, link) { + if (strcmp(action->key, action_key) == 0) { + notify_action_invoked(action); + break; + } + } break; } } @@ -69,6 +78,121 @@ return sd_bus_reply_method_return(msg, ""); } +static int handle_list_notifications(sd_bus_message *msg, void *data, + sd_bus_error *ret_error) { + struct mako_state *state = data; + + sd_bus_message *reply = NULL; + int ret = sd_bus_message_new_method_return(msg, &reply); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_open_container(reply, 'a', "a{sv}"); + if (ret < 0) { + return ret; + } + + struct mako_notification *notif; + wl_list_for_each(notif, &state->notifications, link) { + ret = sd_bus_message_open_container(reply, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_append(reply, "{sv}", "app-name", + "s", notif->app_name); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_append(reply, "{sv}", "app-icon", + "s", notif->app_icon); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_append(reply, "{sv}", "summary", + "s", notif->summary); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_append(reply, "{sv}", "body", + "s", notif->body); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_append(reply, "{sv}", "id", + "u", notif->id); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_open_container(reply, 'e', "sv"); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_append_basic(reply, 's', "actions"); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_open_container(reply, 'v', "a{ss}"); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_open_container(reply, 'a', "{ss}"); + if (ret < 0) { + return ret; + } + + struct mako_action *action; + wl_list_for_each(action, ¬if->actions, link) { + ret = sd_bus_message_append(reply, "{ss}", action->key, action->title); + if (ret < 0) { + return ret; + } + } + + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + } + + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + + ret = sd_bus_send(NULL, reply, NULL); + if (ret < 0) { + return ret; + } + + sd_bus_message_unref(reply); + return 0; +} + static int handle_reload(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { struct mako_state *state = data; @@ -110,7 +234,8 @@ SD_BUS_VTABLE_START(0), SD_BUS_METHOD("DismissAllNotifications", "", "", handle_dismiss_all_notifications, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("DismissLastNotification", "", "", handle_dismiss_last_notification, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("InvokeAction", "s", "", handle_invoke_action, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("InvokeAction", "us", "", handle_invoke_action, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListNotifications", "", "aa{sv}", handle_list_notifications, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reload", "", "", handle_reload, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/dbus/xdg.c new/mako-1.4/dbus/xdg.c --- old/mako-1.3/dbus/xdg.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/dbus/xdg.c 2019-07-19 12:57:01.000000000 +0200 @@ -217,6 +217,83 @@ return ret; } notif->progress = progress; + } else if (strcmp(hint, "image-data") == 0 || strcmp(hint, "icon_data") == 0) { + ret = sd_bus_message_enter_container(msg, 'v', "(iiibiiay)"); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_enter_container(msg, 'r', "iiibiiay"); + if (ret < 0) { + return ret; + } + + struct mako_image_data *image_data = calloc(1, sizeof(struct mako_image_data)); + if (image_data == NULL) { + return -1; + } + + ret = sd_bus_message_read(msg, "iiibii", &image_data->width, + &image_data->height, &image_data->rowstride, + &image_data->has_alpha, &image_data->bits_per_sample, + &image_data->channels); + if (ret < 0) { + free(image_data); + return ret; + } + + // Calculate the expected useful data length without padding in last row + // len = size before last row + size of last row + // = (height - 1) * rowstride + width * ceil(channels * bits_pre_sample / 8.0) + size_t image_len = (image_data->height - 1) * image_data->rowstride + + image_data->width * ((image_data->channels * + image_data->bits_per_sample + 7) / 8); + uint8_t *data = calloc(image_len, sizeof(uint8_t)); + if (data == NULL) { + free(image_data); + return -1; + } + + ret = sd_bus_message_enter_container(msg, 'a', "y"); + if (ret < 0) { + free(data); + free(image_data); + return ret; + } + + // Ignore the extra padding bytes in the last row if exist + for (size_t index = 0; index < image_len; index++) { + uint8_t tmp; + ret = sd_bus_message_read(msg, "y", &tmp); + if (ret < 0){ + free(data); + free(image_data); + return ret; + } + data[index] = tmp; + } + + image_data->data = data; + if (notif->image_data != NULL) { + free(notif->image_data->data); + free(notif->image_data); + } + notif->image_data = image_data; + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + return ret; + } } else { ret = sd_bus_message_skip(msg, "v"); if (ret < 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/fr.emersion.mako.service.in new/mako-1.4/fr.emersion.mako.service.in --- old/mako-1.3/fr.emersion.mako.service.in 1970-01-01 01:00:00.000000000 +0100 +++ new/mako-1.4/fr.emersion.mako.service.in 2019-07-19 12:57:01.000000000 +0200 @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.freedesktop.Notifications +Exec=@bindir@/mako diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/icon.c new/mako-1.4/icon.c --- old/mako-1.3/icon.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/icon.c 2019-07-19 12:57:01.000000000 +0200 @@ -7,6 +7,7 @@ #include <stdio.h> #include <stdlib.h> #include <assert.h> +#include <ctype.h> #include <cairo/cairo.h> #include "mako.h" @@ -33,11 +34,46 @@ return pixbuf; } +static GdkPixbuf *load_image_data(struct mako_image_data *image_data) { + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(image_data->data, GDK_COLORSPACE_RGB, + image_data->has_alpha, image_data->bits_per_sample, image_data->width, + image_data->height, image_data->rowstride, NULL, NULL); + if (!pixbuf) { + fprintf(stderr, "Failed to load icon\n"); + return NULL; + } + return pixbuf; +} + static double fit_to_square(int width, int height, int square_size) { double longest = width > height ? width : height; return longest > square_size ? square_size/longest : 1.0; } +static char hex_val(char digit) { + assert(isxdigit(digit)); + if (digit >= 'a') { + return digit - 'a' + 10; + } else if (digit >= 'A') { + return digit - 'A' + 10; + } else { + return digit - '0'; + } +} + +static void url_decode(char *dst, const char *src) { + while (src[0]) { + if (src[0] == '%' && isxdigit(src[1]) && isxdigit(src[2])) { + dst[0] = 16*hex_val(src[1]) + hex_val(src[2]); + dst++; src += 3; + } else { + dst[0] = src[0]; + dst++; src++; + } + } + dst[0] = '\0'; +} + // Attempt to find a full path for a notification's icon_name, which may be: // - An absolute path, which will simply be returned (as a new string) // - A file:// URI, which will be converted to an absolute path @@ -56,8 +92,14 @@ return strdup(icon_name); } if (strstr(icon_name, "file://") == icon_name) { - // Just chop off the scheme. - return strdup(icon_name + strlen("file://")); + // Chop off the scheme and URL decode + char *icon_path = malloc(strlen(icon_name) + 1 - strlen("file://")); + if (icon_path == NULL) { + return icon_path; + } + + url_decode(icon_path, icon_name + strlen("file://")); + return icon_path; } // Determine the largest scale factor of any attached output. @@ -184,16 +226,24 @@ } struct mako_icon *create_icon(struct mako_notification *notif) { - char *path = resolve_icon(notif); - if (path == NULL) { - return NULL; + GdkPixbuf *image = NULL; + if (notif->image_data != NULL) { + image = load_image_data(notif->image_data); } - GdkPixbuf *image = load_image(path); - free(path); if (image == NULL) { - return NULL; + char *path = resolve_icon(notif); + if (path == NULL) { + return NULL; + } + + image = load_image(path); + free(path); + if (image == NULL) { + return NULL; + } } + int image_width = gdk_pixbuf_get_width(image); int image_height = gdk_pixbuf_get_height(image); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/include/config.h new/mako-1.4/include/config.h --- old/mako-1.3/include/config.h 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/include/config.h 2019-07-19 12:57:01.000000000 +0200 @@ -7,11 +7,11 @@ #include "types.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -enum mako_button_binding { - MAKO_BUTTON_BINDING_NONE, - MAKO_BUTTON_BINDING_DISMISS, - MAKO_BUTTON_BINDING_DISMISS_ALL, - MAKO_BUTTON_BINDING_INVOKE_DEFAULT_ACTION, +enum mako_binding { + MAKO_BINDING_NONE, + MAKO_BINDING_DISMISS, + MAKO_BINDING_DISMISS_ALL, + MAKO_BINDING_INVOKE_DEFAULT_ACTION, }; enum mako_sort_criteria { @@ -81,8 +81,10 @@ struct mako_style superstyle; struct { - enum mako_button_binding left, right, middle; + enum mako_binding left, right, middle; } button_bindings; + + enum mako_binding touch; }; void init_default_config(struct mako_config *config); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/include/icon.h new/mako-1.4/include/icon.h --- old/mako-1.3/include/icon.h 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/include/icon.h 2019-07-19 12:57:01.000000000 +0200 @@ -11,6 +11,16 @@ cairo_surface_t *image; }; +struct mako_image_data { + int32_t width; + int32_t height; + int32_t rowstride; + uint32_t has_alpha; + int32_t bits_per_sample; + int32_t channels; + uint8_t *data; +}; + struct mako_icon *create_icon(struct mako_notification *notif); void destroy_icon(struct mako_icon *icon); void draw_icon(cairo_t *cairo, struct mako_icon *icon, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/include/notification.h new/mako-1.4/include/notification.h --- old/mako-1.3/include/notification.h 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/include/notification.h 2019-07-19 12:57:01.000000000 +0200 @@ -40,6 +40,7 @@ char *category; char *desktop_entry; int32_t progress; + struct mako_image_data *image_data; struct mako_hotspot hotspot; struct mako_timer *timer; @@ -87,6 +88,9 @@ char *buf); void notification_handle_button(struct mako_notification *notif, uint32_t button, enum wl_pointer_button_state state); +void notification_handle_touch(struct mako_notification *notif); +void notification_execute_binding(struct mako_notification *notif, + enum mako_binding binding); void insert_notification(struct mako_state *state, struct mako_notification *notif); int group_notifications(struct mako_state *state, struct mako_criteria *criteria); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/include/wayland.h new/mako-1.4/include/wayland.h --- old/mako-1.3/include/wayland.h 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/include/wayland.h 2019-07-19 12:57:01.000000000 +0200 @@ -27,6 +27,11 @@ struct wl_pointer *wl_pointer; int32_t x, y; } pointer; + + struct { + struct wl_touch *wl_touch; + int32_t x, y; + } touch; }; bool init_wayland(struct mako_state *state); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/mako.1.scd new/mako-1.4/mako.1.scd --- old/mako-1.3/mako.1.scd 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/mako.1.scd 2019-07-19 12:57:01.000000000 +0200 @@ -114,7 +114,7 @@ *--progress-color* [over|source] _color_ Set popup progress indicator color to _color_. See *COLOR* for more - information. To draw the progess indicator on top of the background + information. To draw the progress indicator on top of the background color, use the *over* attribute. To replace the background color, use the *source* attribute (this can be useful when the notification is semi-transparent). @@ -203,7 +203,9 @@ key=value -Is equivalent to passing *--key=value* to mako from the command line. +Is equivalent to passing *--key=value* to mako from the command line. Note that +any quotes used within your shell are unnecessary and also invalid in the +config file. Empty lines and lines that begin with # are ignored. @@ -224,10 +226,12 @@ meaning that if multiple criteria match a notification, the last occurrence of any given style option will "win". -The following fields are available in critiera: +The following fields are available in criteria: - _app-name_ (string) - _app-icon_ (string) +- _summary_ (string) + - An exact match on the summary of the notification. - _urgency_ (one of "low", "normal", "high") - _category_ (string) - _desktop-entry_ (string) @@ -249,7 +253,7 @@ \[app-name=Google\\ Chrome\] -Quotes within quotes may also be escaped, and a literal backslack may be +Quotes within quotes may also be escaped, and a literal backslash may be specified as \\\\. No spaces are allowed around the equal sign. Escaping equal signs within values is unnecessary. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/makoctl new/mako-1.4/makoctl --- old/mako-1.3/makoctl 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/makoctl 2019-07-19 12:57:01.000000000 +0200 @@ -1,30 +1,32 @@ -#!/bin/sh - -set -e +#!/bin/sh -eu usage() { echo "Usage: makoctl <command> [options...]" echo "" echo "Commands:" - echo " dismiss [-a|--all] Dismiss the last or all notifications" - echo " invoke [action] Invoke an action on the last notification" - echo " reload Reload the configuration file" - echo " help Show this help" + echo " dismiss [-a|--all] Dismiss the last or all notifications" + echo " invoke [-n id] [action] Invoke an action on the notification" + echo " with the given id, or the last" + echo " notification if none is given" + echo " list List notifications" + echo " reload Reload the configuration file" + echo " help Show this help" } call() { - busctl --user call org.freedesktop.Notifications /fr/emersion/Mako \ + busctl -j --user call org.freedesktop.Notifications /fr/emersion/Mako \ fr.emersion.Mako "$@" } -if [ $# -eq 0 ] || [ $# -gt 2 ]; then +if [ $# -eq 0 ] || [ $# -gt 5 ]; then usage exit 1 fi case "$1" in "dismiss") - case "$2" in + [ $# -lt 2 ] && action="" || action="$2" + case "$action" in "-a"|"--all") call DismissAllNotifications ;; @@ -38,11 +40,21 @@ esac ;; "invoke") - action="$2" - if [ -z "$action" ] ; then - action="default" + id=0 + if [ $# -gt 1 ] && [ $2 == "-n" ]; then + id="$3" + shift 2 + fi + + action="default" + if [ $# -gt 1 ]; then + action="$2" fi - call InvokeAction "s" "$action" + + call InvokeAction "us" "$id" "$action" + ;; +"list") + call ListNotifications ;; "reload") call Reload diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/makoctl.1.scd new/mako-1.4/makoctl.1.scd --- old/mako-1.3/makoctl.1.scd 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/makoctl.1.scd 2019-07-19 12:57:01.000000000 +0200 @@ -26,6 +26,9 @@ Invokes an action on the first notification. If _action_ is not specified, invokes the default action. +*list* + Retrieve a list of current notifications. + *reload* Reloads the configuration file. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/meson.build new/mako-1.4/meson.build --- old/mako-1.3/meson.build 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/meson.build 2019-07-19 12:57:01.000000000 +0200 @@ -1,7 +1,7 @@ project( 'mako', 'c', - version: '1.2.0', + version: '1.3.0', license: 'MIT', meson_version: '>=0.47.0', default_options: [ @@ -92,6 +92,16 @@ install_mode: 'rwxr-xr-x', ) +conf_data = configuration_data() +conf_data.set('bindir', join_paths(get_option('prefix'), get_option('bindir'))) + +configure_file( + configuration: conf_data, + input: 'fr.emersion.mako.service.in', + output: '@BASENAME@', + install_dir: datadir + '/dbus-1/services', +) + scdoc = find_program('scdoc', required: get_option('man-pages')) if scdoc.found() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/notification.c new/mako-1.4/notification.c --- old/mako-1.3/notification.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/notification.c 2019-07-19 12:57:01.000000000 +0200 @@ -48,6 +48,10 @@ free(notif->body); free(notif->category); free(notif->desktop_entry); + if (notif->image_data != NULL) { + free(notif->image_data->data); + free(notif->image_data); + } notif->app_name = NULL; notif->app_icon = NULL; @@ -55,6 +59,7 @@ notif->body = NULL; notif->category = NULL; notif->desktop_entry = NULL; + notif->image_data = NULL; destroy_icon(notif->icon); notif->icon = NULL; @@ -183,9 +188,9 @@ struct mako_hidden_format_data *format_data = data; switch (variable) { case 'h': - return mako_asprintf("%d", format_data->hidden); + return mako_asprintf("%zu", format_data->hidden); case 't': - return mako_asprintf("%d", format_data->count); + return mako_asprintf("%zu", format_data->count); } return NULL; } @@ -264,7 +269,7 @@ return len; } -static enum mako_button_binding get_button_binding(struct mako_config *config, +static enum mako_binding get_binding(struct mako_config *config, uint32_t button) { switch (button) { case BTN_LEFT: @@ -274,25 +279,21 @@ case BTN_MIDDLE: return config->button_bindings.middle; } - return MAKO_BUTTON_BINDING_NONE; + return MAKO_BINDING_NONE; } -void notification_handle_button(struct mako_notification *notif, uint32_t button, - enum wl_pointer_button_state state) { - if (state != WL_POINTER_BUTTON_STATE_PRESSED) { - return; - } - - switch (get_button_binding(¬if->state->config, button)) { - case MAKO_BUTTON_BINDING_NONE: +void notification_execute_binding(struct mako_notification *notif, + enum mako_binding binding) { + switch (binding) { + case MAKO_BINDING_NONE: break; - case MAKO_BUTTON_BINDING_DISMISS: + case MAKO_BINDING_DISMISS: close_notification(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED); break; - case MAKO_BUTTON_BINDING_DISMISS_ALL: + case MAKO_BINDING_DISMISS_ALL: close_all_notifications(notif->state, MAKO_NOTIFICATION_CLOSE_DISMISSED); break; - case MAKO_BUTTON_BINDING_INVOKE_DEFAULT_ACTION:; + case MAKO_BINDING_INVOKE_DEFAULT_ACTION:; struct mako_action *action; wl_list_for_each(action, ¬if->actions, link) { if (strcmp(action->key, DEFAULT_ACTION_KEY) == 0) { @@ -305,6 +306,21 @@ } } +void notification_handle_button(struct mako_notification *notif, uint32_t button, + enum wl_pointer_button_state state) { + if (state != WL_POINTER_BUTTON_STATE_PRESSED) { + return; + } + + notification_execute_binding(notif, + get_binding(¬if->state->config, button)); +} + +void notification_handle_touch(struct mako_notification *notif) { + notification_execute_binding(notif, + notif->state->config.touch); +} + /* * Searches through the notifications list and returns the next position at * which to insert. If no results for the specified urgency are found, @@ -388,7 +404,7 @@ } // If count is zero, we don't need to worry about changing anything. The - // notification's style has its grouping critiera set to none. + // notification's style has its grouping criteria set to none. if (count == 1) { // If we matched a single notification, it means that it has grouping diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mako-1.3/wayland.c new/mako-1.4/wayland.c --- old/mako-1.3/wayland.c 2019-04-19 04:32:04.000000000 +0200 +++ new/mako-1.4/wayland.c 2019-07-19 12:57:01.000000000 +0200 @@ -96,6 +96,37 @@ free(output); } +static void touch_handle_motion(void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + struct mako_seat *seat = data; + seat->touch.x = wl_fixed_to_int(surface_x); + seat->touch.y = wl_fixed_to_int(surface_y); +} + +static void touch_handle_down(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, struct wl_surface *sfc, int32_t id, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + struct mako_seat *seat = data; + seat->touch.x = wl_fixed_to_int(surface_x); + seat->touch.y = wl_fixed_to_int(surface_y); +} + +static void touch_handle_up(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) { + struct mako_seat *seat = data; + struct mako_state *state = seat->state; + + struct mako_notification *notif; + wl_list_for_each(notif, &state->notifications, link) { + if (hotspot_at(¬if->hotspot, seat->touch.x, seat->touch.y)) { + notification_handle_touch(notif); + break; + } + } + + set_dirty(state); +} static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { @@ -129,6 +160,15 @@ .axis = noop, }; +static const struct wl_touch_listener touch_listener = { + .down = touch_handle_down, + .up = touch_handle_up, + .motion = touch_handle_motion, + .frame = noop, + .cancel = noop, + .shape = noop, + .orientation = noop, +}; static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { @@ -143,6 +183,15 @@ wl_pointer_add_listener(seat->pointer.wl_pointer, &pointer_listener, seat); } + if (seat->touch.wl_touch != NULL) { + wl_touch_release(seat->touch.wl_touch); + seat->touch.wl_touch = NULL; + } + if (capabilities & WL_SEAT_CAPABILITY_TOUCH) { + seat->touch.wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_add_listener(seat->touch.wl_touch, + &touch_listener, seat); + } } static const struct wl_seat_listener seat_listener = {