use n_queue for displayed notifications
This commit is contained in:
parent
91fa27fbf4
commit
1b04f51d67
288
container.c
288
container.c
@ -3,266 +3,6 @@
|
||||
|
||||
#include "container.h"
|
||||
|
||||
int l_push(list * l, void *data)
|
||||
{
|
||||
l_node *n;
|
||||
int ret;
|
||||
|
||||
/* invalid input */
|
||||
if (!l || !data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = l_init_node(data);
|
||||
if (!n) {
|
||||
/* something went wrong */
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = l_node_push(l, n);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int l_node_push(list * l, l_node * n)
|
||||
{
|
||||
l_node *end;
|
||||
|
||||
/* invalid input */
|
||||
if (!l || !n) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
n->next = NULL;
|
||||
|
||||
/* empty list */
|
||||
if (!l->head) {
|
||||
l->head = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (end = l->head; end->next; end = end->next) ;
|
||||
|
||||
if (end != n) {
|
||||
end->next = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *l_pop(list * l)
|
||||
{
|
||||
l_node *penultimate;
|
||||
void *data;
|
||||
|
||||
/* invalid input */
|
||||
if (!l) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* empty list */
|
||||
if (!l->head) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* len(l) == 1 */
|
||||
if (!l->head->next) {
|
||||
data = l->head->data;
|
||||
free(l->head);
|
||||
l->head = NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
for (penultimate = l->head;
|
||||
penultimate->next->next; penultimate = penultimate->next) ;
|
||||
data = penultimate->next->data;
|
||||
free(penultimate->next);
|
||||
penultimate->next = NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int l_insert(l_node * node, void *data)
|
||||
{
|
||||
int ret;
|
||||
l_node *to_be_inserted;
|
||||
|
||||
/* invalid input */
|
||||
if (!node || !data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
to_be_inserted = l_init_node(data);
|
||||
if (!to_be_inserted) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = l_node_insert(node, to_be_inserted);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int l_node_insert(l_node * node, l_node * to_be_inserted)
|
||||
{
|
||||
l_node *tmp;
|
||||
|
||||
/* invalid input */
|
||||
if (!node || !to_be_inserted) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = node->next;
|
||||
node->next = to_be_inserted;
|
||||
to_be_inserted->next = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *l_remove(list * l, l_node * node)
|
||||
{
|
||||
void *data;
|
||||
if (l != NULL) {
|
||||
l_node_remove(l, node);
|
||||
}
|
||||
|
||||
if (node == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = node->data;
|
||||
free(node);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
l_node *l_node_remove(list * l, l_node * node)
|
||||
{
|
||||
l_node *prev;
|
||||
l_node *next;
|
||||
|
||||
/* invalid input */
|
||||
if (!l || !node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* empty list */
|
||||
if (!l->head) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* node is head */
|
||||
if (l->head == node) {
|
||||
l->head = node->next;
|
||||
node->next = NULL;
|
||||
return node;
|
||||
}
|
||||
|
||||
/* find the predecessor of node */
|
||||
for (prev = l->head;
|
||||
prev->next && prev->next != node; prev = prev->next) ;
|
||||
|
||||
/* node not in list */
|
||||
if (prev->next != node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
next = node->next;
|
||||
prev->next = next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
l_node *l_init_node(void *data)
|
||||
{
|
||||
l_node *node;
|
||||
|
||||
node = malloc(sizeof(l_node));
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->data = data;
|
||||
node->next = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int l_length(list * l)
|
||||
{
|
||||
l_node *iter;
|
||||
int count;
|
||||
|
||||
if (!l || !l->head) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
iter = l->head;
|
||||
while (iter) {
|
||||
count++;
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int l_is_empty(list * l)
|
||||
{
|
||||
return l->head == NULL;
|
||||
}
|
||||
|
||||
int l_move(list * from, list * to, l_node * node)
|
||||
{
|
||||
|
||||
if (!from || !to || !node) {
|
||||
return -1;
|
||||
}
|
||||
node = l_node_remove(from, node);
|
||||
return l_node_push(to, node);
|
||||
}
|
||||
|
||||
list *l_init(void)
|
||||
{
|
||||
list *l = malloc(sizeof(list));
|
||||
l->head = NULL;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void l_sort(list * l, int (*f) (void *, void *))
|
||||
{
|
||||
list *old_list;
|
||||
|
||||
if (!l || l_length(l) < 2) {
|
||||
/* nothing to do */
|
||||
return;
|
||||
}
|
||||
|
||||
old_list = l_init();
|
||||
|
||||
old_list->head = l->head;
|
||||
l->head = NULL;
|
||||
|
||||
while (!l_is_empty(old_list)) {
|
||||
l_node *iter;
|
||||
l_node *max;
|
||||
|
||||
/* find max in old_list */
|
||||
max = old_list->head;
|
||||
for (iter = old_list->head; iter; iter = iter->next) {
|
||||
if (f(max->data, iter->data) < 0) {
|
||||
max = iter;
|
||||
}
|
||||
}
|
||||
|
||||
l_move(old_list, l, max);
|
||||
}
|
||||
|
||||
free(old_list);
|
||||
}
|
||||
|
||||
void n_stack_push(n_stack **s, notification *n)
|
||||
{
|
||||
if (!n || !s)
|
||||
@ -288,6 +28,29 @@ notification *n_stack_pop(n_stack **s)
|
||||
return n;
|
||||
}
|
||||
|
||||
void n_stack_remove(n_stack **s, notification *n)
|
||||
{
|
||||
if (!s || !*s || !n)
|
||||
return;
|
||||
|
||||
/* head is n */
|
||||
if ((*s)->n == n) {
|
||||
n_stack *tmp = *s;
|
||||
*s = (*s)->next;
|
||||
free(tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
for (n_stack *iter = *s; iter->next; iter = iter->next) {
|
||||
if (iter->next->n == n) {
|
||||
n_stack *tmp = iter->next;
|
||||
iter->next = iter->next->next;
|
||||
free(tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int n_stack_len(n_stack **s)
|
||||
{
|
||||
if (!s || !*s)
|
||||
@ -360,6 +123,11 @@ void n_queue_enqueue(n_queue **q, notification *n)
|
||||
cur->next = new;
|
||||
}
|
||||
|
||||
void n_queue_remove(n_queue **q, notification *n)
|
||||
{
|
||||
n_stack_remove(q, n);
|
||||
}
|
||||
|
||||
notification *n_queue_dequeue(n_queue **q)
|
||||
{
|
||||
return n_stack_pop(q);
|
||||
|
67
container.h
67
container.h
@ -3,15 +3,6 @@
|
||||
|
||||
#include "dunst.h"
|
||||
|
||||
typedef struct _l_node {
|
||||
struct _l_node *next;
|
||||
void *data;
|
||||
} l_node;
|
||||
|
||||
typedef struct _list {
|
||||
l_node *head;
|
||||
} list;
|
||||
|
||||
typedef struct _n_stack {
|
||||
notification *n;
|
||||
struct _n_stack *next;
|
||||
@ -21,52 +12,6 @@ typedef n_stack n_queue;
|
||||
|
||||
int cmp_notification(notification *a, notification *b);
|
||||
|
||||
/* append to end of list */
|
||||
int l_push(list * l, void *data);
|
||||
|
||||
/* same as append but with a l_node */
|
||||
int l_node_push(list * l, l_node * n);
|
||||
|
||||
/* remove and return last element of list */
|
||||
void *l_pop(list * l);
|
||||
|
||||
/* insert after node. */
|
||||
int l_insert(l_node * node, void *data);
|
||||
|
||||
/*
|
||||
* same as insert, but using a node_t
|
||||
*/
|
||||
int l_node_insert(l_node * node, l_node * to_be_inserted);
|
||||
|
||||
/*
|
||||
* remove l_node from list and return a pointer to its data
|
||||
*/
|
||||
void *l_remove(list * l, l_node * node);
|
||||
|
||||
/*
|
||||
* same as l_remove but returns the node instead of the data
|
||||
*/
|
||||
l_node *l_node_remove(list * l, l_node * node);
|
||||
|
||||
/*
|
||||
* initialize a node
|
||||
*/
|
||||
l_node *l_init_node(void *data);
|
||||
|
||||
/* return the length of the list */
|
||||
int l_length(list * l);
|
||||
|
||||
/* is list empty */
|
||||
int l_is_empty(list * l);
|
||||
|
||||
/* move node from 'from' to 'to' */
|
||||
int l_move(list * from, list * to, l_node * node);
|
||||
|
||||
void l_sort(list * l, int (*f) (void *, void *));
|
||||
|
||||
list *l_init(void);
|
||||
|
||||
|
||||
/************
|
||||
* stack
|
||||
*/
|
||||
@ -83,6 +28,12 @@ void n_stack_push(n_stack **s, notification *n);
|
||||
*/
|
||||
notification *n_stack_pop(n_stack **s);
|
||||
|
||||
/**
|
||||
* remove notification from stack
|
||||
*/
|
||||
|
||||
void n_stack_remove(n_stack **q, notification *n);
|
||||
|
||||
/**
|
||||
* return length of stack
|
||||
*/
|
||||
@ -107,6 +58,12 @@ void n_queue_enqueue(n_queue **q, notification *n);
|
||||
|
||||
notification *n_queue_dequeue(n_queue **q);
|
||||
|
||||
/**
|
||||
* remove notification from queue
|
||||
*/
|
||||
|
||||
void n_queue_remove(n_queue **q, notification *n);
|
||||
|
||||
/**
|
||||
* return length of queue
|
||||
*/
|
||||
|
101
dunst.c
101
dunst.c
@ -80,7 +80,7 @@ int next_notification_id = 1;
|
||||
|
||||
/* notification lists */
|
||||
n_queue *queue = NULL; /* all new notifications get into here */
|
||||
list *displayed_notifications = NULL; /* currently displayed notifications */
|
||||
n_queue *displayed = NULL; /* currently displayed notifications */
|
||||
n_stack *history = NULL; /* history of displayed notifications */
|
||||
|
||||
/* misc funtions */
|
||||
@ -96,7 +96,6 @@ void run(void);
|
||||
void setup(void);
|
||||
void update_screen_info();
|
||||
void usage(int exit_status);
|
||||
l_node *most_important(list * l);
|
||||
void draw_win(void);
|
||||
void hide_win(void);
|
||||
void move_all_to_history(void);
|
||||
@ -216,42 +215,30 @@ void apply_rules(notification * n)
|
||||
|
||||
void check_timeouts(void)
|
||||
{
|
||||
l_node *iter;
|
||||
notification *current;
|
||||
l_node *next;
|
||||
|
||||
/* nothing to do */
|
||||
if (l_is_empty(displayed_notifications)) {
|
||||
if (!displayed)
|
||||
return;
|
||||
}
|
||||
|
||||
iter = displayed_notifications->head;
|
||||
while (iter != NULL) {
|
||||
current = (notification *) iter->data;
|
||||
for (n_queue *iter = displayed; iter; iter = iter->next) {
|
||||
notification *n = iter->n;
|
||||
|
||||
/* don't timeout when user is idle */
|
||||
if (is_idle()) {
|
||||
current->start = now;
|
||||
iter = iter->next;
|
||||
n->start = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip hidden and sticky messages */
|
||||
if (current->start == 0 || current->timeout == 0) {
|
||||
iter = iter->next;
|
||||
if (n->start == 0 || n->timeout == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* remove old message */
|
||||
if (difftime(now, current->start) > current->timeout) {
|
||||
/* l_move changes iter->next, so we need to store it beforehand */
|
||||
next = iter->next;
|
||||
close_notification(current, 1);
|
||||
iter = next;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
iter = iter->next;
|
||||
if (difftime(now, n->start) > n->timeout) {
|
||||
/* close_notification may conflict with iter, so restart */
|
||||
close_notification(n, 1);
|
||||
check_timeouts();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,8 +250,8 @@ void update_lists()
|
||||
check_timeouts();
|
||||
|
||||
if (pause_display) {
|
||||
while (!l_is_empty(displayed_notifications)) {
|
||||
notification *n = (notification *) l_remove(displayed_notifications, displayed_notifications->head);
|
||||
while (displayed) {
|
||||
notification *n = n_queue_dequeue(&displayed);
|
||||
n_queue_enqueue(&queue, n);
|
||||
}
|
||||
return;
|
||||
@ -284,7 +271,7 @@ void update_lists()
|
||||
/* move notifications from queue to displayed */
|
||||
while (queue) {
|
||||
|
||||
if (limit > 0 && l_length(displayed_notifications) >= limit) {
|
||||
if (limit > 0 && n_queue_len(&displayed) >= limit) {
|
||||
/* the list is full */
|
||||
break;
|
||||
}
|
||||
@ -295,10 +282,7 @@ void update_lists()
|
||||
return;
|
||||
n->start = now;
|
||||
|
||||
l_push(displayed_notifications, n);
|
||||
|
||||
l_sort(displayed_notifications, cmp_notification);
|
||||
|
||||
n_queue_enqueue(&displayed, n);
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,10 +555,8 @@ void move_and_map(int width, int height)
|
||||
void fill_line_cache(int width)
|
||||
{
|
||||
/* create cache with all lines */
|
||||
for (l_node * iter = displayed_notifications->head; iter;
|
||||
iter = iter->next) {
|
||||
notification *n = (notification *) iter->data;
|
||||
add_notification_to_line_cache(n, width);
|
||||
for (n_queue *iter = displayed; iter; iter = iter->next) {
|
||||
add_notification_to_line_cache(iter->n, width);
|
||||
}
|
||||
|
||||
assert(line_cache.count > 0);
|
||||
@ -724,17 +706,15 @@ void handle_mouse_click(XEvent ev)
|
||||
|
||||
if (ev.xbutton.button == Button1) {
|
||||
int y = 0;
|
||||
notification *n;
|
||||
l_node *iter = displayed_notifications->head;
|
||||
assert(iter);
|
||||
for (; iter; iter = iter->next) {
|
||||
n = (notification *) iter->data;
|
||||
int height = font_h * n->line_count;
|
||||
notification *n = NULL;
|
||||
for (n_queue *iter = displayed; iter; iter = iter->next) {
|
||||
int height = font_h * iter->n->line_count;
|
||||
if (ev.xbutton.y > y && ev.xbutton.y < y + height)
|
||||
break;
|
||||
else
|
||||
y += height;
|
||||
}
|
||||
if (n)
|
||||
close_notification(n, 2);
|
||||
}
|
||||
}
|
||||
@ -767,10 +747,8 @@ void handleXEvents(void)
|
||||
if (close_ks.str
|
||||
&& XLookupKeysym(&ev.xkey, 0) == close_ks.sym
|
||||
&& close_ks.mask == ev.xkey.state) {
|
||||
if (!l_is_empty(displayed_notifications)) {
|
||||
notification *n = (notification *)
|
||||
displayed_notifications->head->data;
|
||||
close_notification(n, 2);
|
||||
if (displayed) {
|
||||
close_notification(displayed->n, 2);
|
||||
}
|
||||
}
|
||||
if (history_ks.str
|
||||
@ -789,16 +767,11 @@ void handleXEvents(void)
|
||||
|
||||
void move_all_to_history()
|
||||
{
|
||||
l_node *node;
|
||||
notification *n;
|
||||
|
||||
while (!l_is_empty(displayed_notifications)) {
|
||||
node = displayed_notifications->head;
|
||||
n = (notification *) node->data;
|
||||
close_notification(n, 2);
|
||||
while (displayed) {
|
||||
close_notification(displayed->n, 2);
|
||||
}
|
||||
|
||||
n = n_queue_dequeue(&queue);
|
||||
notification *n = n_queue_dequeue(&queue);
|
||||
while (n) {
|
||||
n_stack_push(&history, n);
|
||||
n = n_queue_dequeue(&queue);
|
||||
@ -885,9 +858,8 @@ int init_notification(notification * n, int id)
|
||||
}
|
||||
}
|
||||
|
||||
for (l_node * iter = displayed_notifications->head; iter;
|
||||
iter = iter->next) {
|
||||
notification *orig = (notification *) iter->data;
|
||||
for (n_queue *iter = displayed; iter; iter = iter->next) {
|
||||
notification *orig = iter->n;
|
||||
if (strcmp(orig->appname, n->appname) == 0
|
||||
&& strcmp(orig->msg, n->msg) == 0) {
|
||||
orig->dup_count++;
|
||||
@ -952,22 +924,20 @@ int close_notification_by_id(int id, int reason)
|
||||
{
|
||||
notification *target = NULL;
|
||||
|
||||
for (l_node *iter = displayed_notifications->head; iter; iter = iter->next) {
|
||||
notification *n = (notification *) iter->data;
|
||||
for (n_queue *iter = displayed; iter; iter = iter->next) {
|
||||
notification *n = iter->n;
|
||||
if (n->id == id) {
|
||||
l_remove(displayed_notifications, iter);
|
||||
n_queue_remove(&displayed, n);
|
||||
n_stack_push(&history, n);
|
||||
target = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (n_queue *iter = queue; iter && iter->next; iter = iter->next) {
|
||||
for (n_queue *iter = queue; iter; iter = iter->next) {
|
||||
notification *n = iter->next->n;
|
||||
if (n->id == id) {
|
||||
n_queue *tmp = iter->next;
|
||||
iter->next = iter->next->next;
|
||||
free(tmp);
|
||||
n_queue_remove(&queue, n);
|
||||
n_stack_push(&history, n);
|
||||
target = n;
|
||||
break;
|
||||
@ -1098,7 +1068,7 @@ void run(void)
|
||||
|
||||
/* move messages from notification_queue to displayed_notifications */
|
||||
update_lists();
|
||||
if (l_length(displayed_notifications) > 0) {
|
||||
if (displayed) {
|
||||
if (!visible) {
|
||||
map_win();
|
||||
} else {
|
||||
@ -1306,7 +1276,7 @@ void setup(void)
|
||||
void map_win(void)
|
||||
{
|
||||
/* window is already mapped or there's nothing to show */
|
||||
if (visible || l_is_empty(displayed_notifications)) {
|
||||
if (visible || !displayed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1576,7 +1546,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
now = time(&now);
|
||||
|
||||
displayed_notifications = l_init();
|
||||
r_line_cache_init(&line_cache);
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user