diff --git a/config.c b/config.c index 2372f45..ec88885 100644 --- a/config.c +++ b/config.c @@ -149,6 +149,8 @@ void finish_style(struct mako_style *style) { finish_binding(&style->button_bindings.right); finish_binding(&style->touch_binding); finish_binding(&style->notify_binding); + finish_binding(&style->timeout_binding); + finish_binding(&style->dismiss_binding); free(style->icon_path); free(style->font); free(style->format); @@ -390,6 +392,16 @@ bool apply_style(struct mako_style *target, const struct mako_style *style) { target->spec.notify_binding = true; } + if (style->spec.timeout_binding) { + copy_binding(&target->timeout_binding, &style->timeout_binding); + target->spec.timeout_binding = true; + } + + if (style->spec.dismiss_binding) { + copy_binding(&target->dismiss_binding, &style->dismiss_binding); + target->spec.dismiss_binding = true; + } + return true; } @@ -678,6 +690,12 @@ static bool apply_style_option(struct mako_style *style, const char *name, } else if (strcmp(name, "on-notify") == 0) { copy_binding(&style->notify_binding, &binding); style->spec.notify_binding = true; + } else if (strcmp(name, "on-timeout") == 0) { + copy_binding(&style->timeout_binding, &binding); + style->spec.timeout_binding = true; + } else if (strcmp(name, "on-dismiss") == 0) { + copy_binding(&style->dismiss_binding, &binding); + style->spec.dismiss_binding = true; } else { return false; } diff --git a/dbus/mako.c b/dbus/mako.c index b2d1491..18549f5 100644 --- a/dbus/mako.c +++ b/dbus/mako.c @@ -19,7 +19,13 @@ static int handle_dismiss_all_notifications(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { struct mako_state *state = data; - close_all_notifications(state, MAKO_NOTIFICATION_CLOSE_DISMISSED); + int add_to_history = 1; + int ret = sd_bus_message_read(msg, "b", &add_to_history); + if (ret < 0) { + return ret; + } + + close_all_notifications(state, MAKO_NOTIFICATION_CLOSE_DISMISSED, add_to_history); struct mako_surface *surface; wl_list_for_each(surface, &state->surfaces, link) { @@ -29,7 +35,7 @@ static int handle_dismiss_all_notifications(sd_bus_message *msg, void *data, return sd_bus_reply_method_return(msg, ""); } -static int handle_dismiss_group_notifications(sd_bus_message *msg, void *data, +static int handle_dismiss_last_group_notifications(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { struct mako_state *state = data; @@ -37,11 +43,17 @@ static int handle_dismiss_group_notifications(sd_bus_message *msg, void *data, goto done; } + int add_to_history = 1; + int ret = sd_bus_message_read(msg, "b", &add_to_history); + if (ret < 0) { + return ret; + } + struct mako_notification *notif = wl_container_of(state->notifications.next, notif, link); struct mako_surface *surface = notif->surface; - close_group_notifications(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED); + close_group_notifications(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, add_to_history); set_dirty(surface); done: @@ -56,22 +68,55 @@ static int handle_dismiss_last_notification(sd_bus_message *msg, void *data, goto done; } + int add_to_history = 1; + int ret = sd_bus_message_read(msg, "b", &add_to_history); + if (ret < 0) { + return ret; + } + struct mako_notification *notif = wl_container_of(state->notifications.next, notif, link); - close_notification(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, true); - set_dirty(notif->surface); + + struct mako_surface *surface = notif->surface; + close_notification(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, add_to_history); + + set_dirty(surface); done: return sd_bus_reply_method_return(msg, ""); } +static int handle_dismiss_group_notifications(sd_bus_message *msg, void *data, + sd_bus_error *ret_error) { + struct mako_state *state = data; + + uint32_t id = 0; + int add_to_history = 1; + int ret = sd_bus_message_read(msg, "ub", &id, &add_to_history); + if (ret < 0) { + return ret; + } + + struct mako_notification *notif; + wl_list_for_each(notif, &state->notifications, link) { + if (notif->id == id || id == 0) { + struct mako_surface *surface = notif->surface; + close_group_notifications(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, add_to_history); + set_dirty(surface); + break; + } + } + + return sd_bus_reply_method_return(msg, ""); +} + static int handle_dismiss_notification(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { struct mako_state *state = data; uint32_t id = 0; - int dismiss_group = 0; - int ret = sd_bus_message_read(msg, "ub", &id, &dismiss_group); + int add_to_history = 1; + int ret = sd_bus_message_read(msg, "ub", &id, &add_to_history); if (ret < 0) { return ret; } @@ -79,12 +124,9 @@ static int handle_dismiss_notification(sd_bus_message *msg, void *data, struct mako_notification *notif; wl_list_for_each(notif, &state->notifications, link) { if (notif->id == id || id == 0) { - if (dismiss_group) { - close_group_notifications(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED); - } else { - close_notification(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, true); - } - set_dirty(notif->surface); + struct mako_surface *surface = notif->surface; + close_notification(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, add_to_history); + set_dirty(surface); break; } } @@ -436,9 +478,10 @@ static int handle_set_modes(sd_bus_message *msg, void *data, static const sd_bus_vtable service_vtable[] = { SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("DismissAllNotifications", "", "", handle_dismiss_all_notifications, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("DismissGroupNotifications", "", "", handle_dismiss_group_notifications, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("DismissLastNotification", "", "", handle_dismiss_last_notification, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DismissAllNotifications", "b", "", handle_dismiss_all_notifications, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DismissLastGroupNotifications", "b", "", handle_dismiss_last_group_notifications, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DismissLastNotification", "b", "", handle_dismiss_last_notification, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DismissGroupNotifications", "ub", "", handle_dismiss_group_notifications, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("DismissNotification", "ub", "", handle_dismiss_notification, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("InvokeAction", "us", "", handle_invoke_action, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RestoreNotification", "", "", handle_restore_action, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/dbus/xdg.c b/dbus/xdg.c index b772f57..e66f152 100644 --- a/dbus/xdg.c +++ b/dbus/xdg.c @@ -88,6 +88,7 @@ static void handle_notification_timer(void *data) { notif->timer = NULL; close_notification(notif, MAKO_NOTIFICATION_CLOSE_EXPIRED, true); + notification_execute_binding(notif, ¬if->style.timeout_binding, NULL); set_dirty(surface); } @@ -440,7 +441,8 @@ static int handle_close_notification(sd_bus_message *msg, void *data, struct mako_state *state = data; uint32_t id; - int ret = sd_bus_message_read(msg, "u", &id); + bool add_to_history = true; + int ret = sd_bus_message_read(msg, "ub", &id, &add_to_history); if (ret < 0) { return ret; } @@ -449,7 +451,8 @@ static int handle_close_notification(sd_bus_message *msg, void *data, struct mako_notification *notif = get_notification(state, id); if (notif) { struct mako_surface *surface = notif->surface; - close_notification(notif, MAKO_NOTIFICATION_CLOSE_REQUEST, true); + close_notification(notif, MAKO_NOTIFICATION_CLOSE_REQUEST, add_to_history); + notification_execute_binding(notif, ¬if->style.dismiss_binding, NULL); set_dirty(surface); } @@ -488,6 +491,7 @@ void notify_notification_closed(struct mako_notification *notif, sd_bus_emit_signal(state->bus, service_path, service_interface, "NotificationClosed", "uu", notif->id, reason); + notification_execute_binding(notif, ¬if->style.dismiss_binding, NULL); } void notify_action_invoked(struct mako_action *action, diff --git a/include/config.h b/include/config.h index 013923a..95d3ca6 100644 --- a/include/config.h +++ b/include/config.h @@ -49,7 +49,7 @@ struct mako_style_spec { struct { bool left, right, middle; } button_bindings; - bool touch_binding, notify_binding; + bool touch_binding, notify_binding, timeout_binding, dismiss_binding; }; @@ -98,7 +98,7 @@ struct mako_style { struct { struct mako_binding left, right, middle; } button_bindings; - struct mako_binding touch_binding, notify_binding; + struct mako_binding touch_binding, notify_binding, timeout_binding, dismiss_binding; }; struct mako_config { diff --git a/include/notification.h b/include/notification.h index 9a395ba..b3a9037 100644 --- a/include/notification.h +++ b/include/notification.h @@ -88,9 +88,11 @@ void close_notification(struct mako_notification *notif, enum mako_notification_close_reason reason, bool add_to_history); void close_group_notifications(struct mako_notification *notif, - enum mako_notification_close_reason reason); + enum mako_notification_close_reason reason, + bool add_to_history); void close_all_notifications(struct mako_state *state, - enum mako_notification_close_reason reason); + enum mako_notification_close_reason reason, + bool add_to_history); char *format_hidden_text(char variable, bool *markup, void *data); char *format_notif_text(char variable, bool *markup, void *data); size_t format_text(const char *format, char *buf, mako_format_func_t func, void *data); diff --git a/mako.5.scd b/mako.5.scd index 557bc16..2f3368a 100644 --- a/mako.5.scd +++ b/mako.5.scd @@ -60,6 +60,16 @@ Supported options: Default: none +*on-timeout*=_action_ + Performs the action when the notification times out. + + Default: none + +*on-dismiss*=_action_ + Performs the action when the notification is dismissed. + + Default: none + Supported actions: *none* diff --git a/makoctl b/makoctl index b5298fe..3231c2d 100755 --- a/makoctl +++ b/makoctl @@ -8,8 +8,9 @@ usage() { echo " given id, or the last notification" echo " if none is given" echo " [-a|--all] Dismiss all notifications" - echo " [-g|--group] Dismiss all the notifications" - echo " in the last notification's group" + echo " [-g|--group] Dismiss all the notifications in the" + echo " [--no-history] Dismiss without adding the history" + echo " last or given notification's group" echo " restore Restore the most recently expired" echo " notification from the history buffer" echo " invoke [-n id] [action] Invoke an action on the notification" @@ -58,6 +59,7 @@ case "$1" in "dismiss") all=0 group=0 + add_to_history=1 id=0 while [ $# -gt 1 ]; do case "$2" in @@ -67,6 +69,9 @@ case "$1" in "-g"|"--group") group=1 ;; + "--no-history") + add_to_history=0 + ;; "-n") if [ $# -lt 3 ]; then echo >&2 "$0: Expected after '-n'" @@ -84,9 +89,11 @@ case "$1" in done if [ $all -eq 1 ]; then - call DismissAllNotifications + call DismissAllNotifications "b" "$add_to_history" + elif [ $group -eq 1 ]; then + call DismissGroupNotifications "ub" "$id" "$add_to_history" else - call DismissNotification "ub" "$id" "$group" + call DismissNotification "ub" "$id" "$add_to_history" fi ;; "invoke") diff --git a/notification.c b/notification.c index b82279f..ad1fcad 100644 --- a/notification.c +++ b/notification.c @@ -168,12 +168,13 @@ struct mako_notification *get_tagged_notification(struct mako_state *state, } void close_group_notifications(struct mako_notification *top_notif, - enum mako_notification_close_reason reason) { + enum mako_notification_close_reason reason, + bool add_to_history) { struct mako_state *state = top_notif->state; if (top_notif->style.group_criteria_spec.none) { // No grouping, just close the notification - close_notification(top_notif, reason, true); + close_notification(top_notif, reason, add_to_history); return; } @@ -183,7 +184,7 @@ void close_group_notifications(struct mako_notification *top_notif, struct mako_notification *notif, *tmp; wl_list_for_each_safe(notif, tmp, &state->notifications, link) { if (match_criteria(notif_criteria, notif)) { - close_notification(notif, reason, true); + close_notification(notif, reason, add_to_history); } } @@ -191,10 +192,11 @@ void close_group_notifications(struct mako_notification *top_notif, } void close_all_notifications(struct mako_state *state, - enum mako_notification_close_reason reason) { + enum mako_notification_close_reason reason, + bool add_to_history) { struct mako_notification *notif, *tmp; wl_list_for_each_safe(notif, tmp, &state->notifications, link) { - close_notification(notif, reason, true); + close_notification(notif, reason, add_to_history); } } @@ -386,10 +388,10 @@ void notification_execute_binding(struct mako_notification *notif, close_notification(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, false); break; case MAKO_BINDING_DISMISS_GROUP: - close_group_notifications(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED); + close_group_notifications(notif, MAKO_NOTIFICATION_CLOSE_DISMISSED, true); break; case MAKO_BINDING_DISMISS_ALL: - close_all_notifications(notif->state, MAKO_NOTIFICATION_CLOSE_DISMISSED); + close_all_notifications(notif->state, MAKO_NOTIFICATION_CLOSE_DISMISSED, true); break; case MAKO_BINDING_INVOKE_ACTION: assert(binding->action_name != NULL);