Skip to content

Commit

Permalink
dynamic timeouts
Browse files Browse the repository at this point in the history
Compute notification timeouts on every config change, rather than only
on notification creation.
  • Loading branch information
chayleaf committed Aug 24, 2024
1 parent 4d48aca commit 6148c2d
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 50 deletions.
50 changes: 46 additions & 4 deletions criteria.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,38 @@ struct mako_criteria *global_criteria(struct mako_config *config) {
return criteria;
}

// Iterate through `criteria_list`, applying the style from each matching
static void timespec_add(struct timespec *t, int delta_ms) {
static const long ms = 1000000, s = 1000000000;

int delta_ms_low = delta_ms % 1000;
int delta_s_high = delta_ms / 1000;

t->tv_sec += delta_s_high;

t->tv_nsec += (long)delta_ms_low * ms;
if (t->tv_nsec >= s) {
t->tv_nsec -= s;
++t->tv_sec;
}
}

static void handle_notification_timer(void *data) {
struct mako_notification *notif = data;
struct mako_surface *surface = notif->surface;
notif->timer = NULL;

close_notification(notif, MAKO_NOTIFICATION_CLOSE_EXPIRED, true);
set_dirty(surface);
}

// Iterate through the criteria list, applying the style from each matching
// criteria to `notif`. Returns the number of criteria that matched, or -1 if
// a failure occurs.
ssize_t apply_each_criteria(struct wl_list *criteria_list,
struct mako_notification *notif) {
ssize_t apply_each_criteria(struct mako_state *state, struct mako_notification *notif) {
ssize_t match_count = 0;

struct mako_criteria *criteria;
wl_list_for_each(criteria, criteria_list, link) {
wl_list_for_each(criteria, &state->config.criteria, link) {
if (!match_criteria(criteria, notif)) {
continue;
}
Expand All @@ -447,6 +470,25 @@ ssize_t apply_each_criteria(struct wl_list *criteria_list,
}
}

int32_t expire_timeout = notif->requested_timeout;
if (expire_timeout < 0 || notif->style.ignore_timeout) {
expire_timeout = notif->style.default_timeout;
}

if (expire_timeout > 0) {
struct timespec at = notif->at;
timespec_add(&at, expire_timeout);
if (notif->timer) {
notif->timer->at = at;
} else {
notif->timer = add_event_loop_timer(&state->event_loop, &at,
handle_notification_timer, notif);
}
} else if (notif->timer) {
destroy_timer(notif->timer);
notif->timer = NULL;
}

if (!notif->surface) {
notif->surface = create_surface(notif->state, notif->style.output,
notif->style.layer, notif->style.anchor);
Expand Down
2 changes: 1 addition & 1 deletion dbus/mako.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ static void reapply_config(struct mako_state *state) {

finish_style(&notif->style);
init_empty_style(&notif->style);
apply_each_criteria(&state->config.criteria, notif);
apply_each_criteria(state, notif);

// Having to do this for every single notification really hurts... but
// it does do The Right Thing (tm).
Expand Down
21 changes: 1 addition & 20 deletions dbus/xdg.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,6 @@ static int handle_get_capabilities(sd_bus_message *msg, void *data,
return 0;
}

static void handle_notification_timer(void *data) {
struct mako_notification *notif = data;
struct mako_surface *surface = notif->surface;
notif->timer = NULL;

close_notification(notif, MAKO_NOTIFICATION_CLOSE_EXPIRED, true);
set_dirty(surface);
}

static int handle_notify(sd_bus_message *msg, void *data,
sd_bus_error *ret_error) {
struct mako_state *state = data;
Expand Down Expand Up @@ -382,7 +373,7 @@ static int handle_notify(sd_bus_message *msg, void *data,
insert_notification(state, notif);
}

int match_count = apply_each_criteria(&state->config.criteria, notif);
int match_count = apply_each_criteria(state, notif);
if (match_count == -1) {
// We encountered an allocation failure or similar while applying
// criteria. The notification may be partially matched, but the worst
Expand All @@ -398,16 +389,6 @@ static int handle_notify(sd_bus_message *msg, void *data,
return -1;
}

int32_t expire_timeout = notif->requested_timeout;
if (expire_timeout < 0 || notif->style.ignore_timeout) {
expire_timeout = notif->style.default_timeout;
}

if (expire_timeout > 0) {
notif->timer = add_event_loop_timer(&state->event_loop, expire_timeout,
handle_notification_timer, notif);
}

if (notif->style.icons) {
notif->icon = create_icon(notif);
}
Expand Down
22 changes: 2 additions & 20 deletions event-loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,6 @@ void finish_event_loop(struct mako_event_loop *loop) {
}
}

static void timespec_add(struct timespec *t, int delta_ms) {
static const long ms = 1000000, s = 1000000000;

int delta_ms_low = delta_ms % 1000;
int delta_s_high = delta_ms / 1000;

t->tv_sec += delta_s_high;

t->tv_nsec += (long)delta_ms_low * ms;
if (t->tv_nsec >= s) {
t->tv_nsec -= s;
++t->tv_sec;
}
}

static bool timespec_less(struct timespec *t1, struct timespec *t2) {
if (t1->tv_sec != t2->tv_sec) {
return t1->tv_sec < t2->tv_sec;
Expand Down Expand Up @@ -124,7 +109,7 @@ static void update_event_loop_timer(struct mako_event_loop *loop) {
}

struct mako_timer *add_event_loop_timer(struct mako_event_loop *loop,
int delay_ms, mako_event_loop_timer_func_t func, void *data) {
struct timespec *at, mako_event_loop_timer_func_t func, void *data) {
struct mako_timer *timer = calloc(1, sizeof(struct mako_timer));
if (timer == NULL) {
fprintf(stderr, "allocation failed\n");
Expand All @@ -133,10 +118,7 @@ struct mako_timer *add_event_loop_timer(struct mako_event_loop *loop,
timer->event_loop = loop;
timer->func = func;
timer->user_data = data;
wl_list_insert(&loop->timers, &timer->link);

clock_gettime(CLOCK_MONOTONIC, &timer->at);
timespec_add(&timer->at, delay_ms);
timer->at = *at;

update_event_loop_timer(loop);
return timer;
Expand Down
4 changes: 2 additions & 2 deletions include/criteria.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <wayland-client.h>
#include "config.h"
#include "types.h"
#include "mako.h"

struct mako_config;
struct mako_notification;
Expand Down Expand Up @@ -53,8 +54,7 @@ bool parse_criteria(const char *string, struct mako_criteria *criteria);
bool apply_criteria_field(struct mako_criteria *criteria, char *token);

struct mako_criteria *global_criteria(struct mako_config *config);
ssize_t apply_each_criteria(struct wl_list *criteria_list,
struct mako_notification *notif);
ssize_t apply_each_criteria(struct mako_state *state, struct mako_notification *notif);
struct mako_criteria *create_criteria_from_notification(
struct mako_notification *notif, struct mako_criteria_spec *spec);

Expand Down
2 changes: 1 addition & 1 deletion include/event-loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ bool init_event_loop(struct mako_event_loop *loop, sd_bus *bus,
void finish_event_loop(struct mako_event_loop *loop);
int run_event_loop(struct mako_event_loop *loop);
struct mako_timer *add_event_loop_timer(struct mako_event_loop *loop,
int delay_ms, mako_event_loop_timer_func_t func, void *data);
struct timespec *at, mako_event_loop_timer_func_t func, void *data);

void destroy_timer(struct mako_timer *timer);

Expand Down
1 change: 1 addition & 0 deletions include/notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct mako_notification {

struct mako_hotspot hotspot;
struct mako_timer *timer;
struct timespec at;
};

struct mako_action {
Expand Down
2 changes: 2 additions & 0 deletions notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ void reset_notification(struct mako_notification *notif) {

destroy_icon(notif->icon);
notif->icon = NULL;

clock_gettime(CLOCK_MONOTONIC, &notif->at);
}

struct mako_notification *create_notification(struct mako_state *state) {
Expand Down
4 changes: 2 additions & 2 deletions render.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ void render(struct mako_surface *surface, struct pool_buffer *buffer, int scale,
// Immediately before rendering we need to re-match all of the criteria
// so that matches against the anchor and output work even if the
// output was automatically assigned by the compositor.
int rematch_count = apply_each_criteria(&state->config.criteria, notif);
int rematch_count = apply_each_criteria(state, notif);
if (rematch_count == -1) {
// We encountered an allocation failure or similar while applying
// criteria. The notification may be partially matched, but the
Expand Down Expand Up @@ -427,7 +427,7 @@ void render(struct mako_surface *surface, struct pool_buffer *buffer, int scale,
struct mako_notification *hidden_notif = create_notification(state);
hidden_notif->surface = surface;
hidden_notif->hidden = true;
apply_each_criteria(&state->config.criteria, hidden_notif);
apply_each_criteria(state, hidden_notif);

struct mako_style *style = &hidden_notif->style;

Expand Down

0 comments on commit 6148c2d

Please sign in to comment.