use n_queue for displayed notifications

This commit is contained in:
Sascha Kruse 2012-12-12 12:48:21 +01:00
parent 91fa27fbf4
commit 1b04f51d67
3 changed files with 76 additions and 382 deletions

View File

@ -3,266 +3,6 @@
#include "container.h" #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) void n_stack_push(n_stack **s, notification *n)
{ {
if (!n || !s) if (!n || !s)
@ -288,6 +28,29 @@ notification *n_stack_pop(n_stack **s)
return n; 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) int n_stack_len(n_stack **s)
{ {
if (!s || !*s) if (!s || !*s)
@ -360,6 +123,11 @@ void n_queue_enqueue(n_queue **q, notification *n)
cur->next = new; cur->next = new;
} }
void n_queue_remove(n_queue **q, notification *n)
{
n_stack_remove(q, n);
}
notification *n_queue_dequeue(n_queue **q) notification *n_queue_dequeue(n_queue **q)
{ {
return n_stack_pop(q); return n_stack_pop(q);

View File

@ -3,15 +3,6 @@
#include "dunst.h" #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 { typedef struct _n_stack {
notification *n; notification *n;
struct _n_stack *next; struct _n_stack *next;
@ -21,52 +12,6 @@ typedef n_stack n_queue;
int cmp_notification(notification *a, notification *b); 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 * stack
*/ */
@ -83,6 +28,12 @@ void n_stack_push(n_stack **s, notification *n);
*/ */
notification *n_stack_pop(n_stack **s); notification *n_stack_pop(n_stack **s);
/**
* remove notification from stack
*/
void n_stack_remove(n_stack **q, notification *n);
/** /**
* return length of stack * return length of stack
*/ */
@ -107,6 +58,12 @@ void n_queue_enqueue(n_queue **q, notification *n);
notification *n_queue_dequeue(n_queue **q); notification *n_queue_dequeue(n_queue **q);
/**
* remove notification from queue
*/
void n_queue_remove(n_queue **q, notification *n);
/** /**
* return length of queue * return length of queue
*/ */

101
dunst.c
View File

@ -80,7 +80,7 @@ int next_notification_id = 1;
/* notification lists */ /* notification lists */
n_queue *queue = NULL; /* all new notifications get into here */ 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 */ n_stack *history = NULL; /* history of displayed notifications */
/* misc funtions */ /* misc funtions */
@ -96,7 +96,6 @@ void run(void);
void setup(void); void setup(void);
void update_screen_info(); void update_screen_info();
void usage(int exit_status); void usage(int exit_status);
l_node *most_important(list * l);
void draw_win(void); void draw_win(void);
void hide_win(void); void hide_win(void);
void move_all_to_history(void); void move_all_to_history(void);
@ -216,42 +215,30 @@ void apply_rules(notification * n)
void check_timeouts(void) void check_timeouts(void)
{ {
l_node *iter;
notification *current;
l_node *next;
/* nothing to do */ /* nothing to do */
if (l_is_empty(displayed_notifications)) { if (!displayed)
return; return;
}
iter = displayed_notifications->head; for (n_queue *iter = displayed; iter; iter = iter->next) {
while (iter != NULL) { notification *n = iter->n;
current = (notification *) iter->data;
/* don't timeout when user is idle */ /* don't timeout when user is idle */
if (is_idle()) { if (is_idle()) {
current->start = now; n->start = now;
iter = iter->next;
continue; continue;
} }
/* skip hidden and sticky messages */ /* skip hidden and sticky messages */
if (current->start == 0 || current->timeout == 0) { if (n->start == 0 || n->timeout == 0) {
iter = iter->next;
continue; continue;
} }
/* remove old message */ /* remove old message */
if (difftime(now, current->start) > current->timeout) { if (difftime(now, n->start) > n->timeout) {
/* l_move changes iter->next, so we need to store it beforehand */ /* close_notification may conflict with iter, so restart */
next = iter->next; close_notification(n, 1);
close_notification(current, 1); check_timeouts();
iter = next; return;
continue;
} else {
iter = iter->next;
} }
} }
} }
@ -263,8 +250,8 @@ void update_lists()
check_timeouts(); check_timeouts();
if (pause_display) { if (pause_display) {
while (!l_is_empty(displayed_notifications)) { while (displayed) {
notification *n = (notification *) l_remove(displayed_notifications, displayed_notifications->head); notification *n = n_queue_dequeue(&displayed);
n_queue_enqueue(&queue, n); n_queue_enqueue(&queue, n);
} }
return; return;
@ -284,7 +271,7 @@ void update_lists()
/* move notifications from queue to displayed */ /* move notifications from queue to displayed */
while (queue) { while (queue) {
if (limit > 0 && l_length(displayed_notifications) >= limit) { if (limit > 0 && n_queue_len(&displayed) >= limit) {
/* the list is full */ /* the list is full */
break; break;
} }
@ -295,10 +282,7 @@ void update_lists()
return; return;
n->start = now; n->start = now;
l_push(displayed_notifications, n); n_queue_enqueue(&displayed, n);
l_sort(displayed_notifications, cmp_notification);
} }
} }
@ -571,10 +555,8 @@ void move_and_map(int width, int height)
void fill_line_cache(int width) void fill_line_cache(int width)
{ {
/* create cache with all lines */ /* create cache with all lines */
for (l_node * iter = displayed_notifications->head; iter; for (n_queue *iter = displayed; iter; iter = iter->next) {
iter = iter->next) { add_notification_to_line_cache(iter->n, width);
notification *n = (notification *) iter->data;
add_notification_to_line_cache(n, width);
} }
assert(line_cache.count > 0); assert(line_cache.count > 0);
@ -724,17 +706,15 @@ void handle_mouse_click(XEvent ev)
if (ev.xbutton.button == Button1) { if (ev.xbutton.button == Button1) {
int y = 0; int y = 0;
notification *n; notification *n = NULL;
l_node *iter = displayed_notifications->head; for (n_queue *iter = displayed; iter; iter = iter->next) {
assert(iter); int height = font_h * iter->n->line_count;
for (; iter; iter = iter->next) {
n = (notification *) iter->data;
int height = font_h * n->line_count;
if (ev.xbutton.y > y && ev.xbutton.y < y + height) if (ev.xbutton.y > y && ev.xbutton.y < y + height)
break; break;
else else
y += height; y += height;
} }
if (n)
close_notification(n, 2); close_notification(n, 2);
} }
} }
@ -767,10 +747,8 @@ void handleXEvents(void)
if (close_ks.str if (close_ks.str
&& XLookupKeysym(&ev.xkey, 0) == close_ks.sym && XLookupKeysym(&ev.xkey, 0) == close_ks.sym
&& close_ks.mask == ev.xkey.state) { && close_ks.mask == ev.xkey.state) {
if (!l_is_empty(displayed_notifications)) { if (displayed) {
notification *n = (notification *) close_notification(displayed->n, 2);
displayed_notifications->head->data;
close_notification(n, 2);
} }
} }
if (history_ks.str if (history_ks.str
@ -789,16 +767,11 @@ void handleXEvents(void)
void move_all_to_history() void move_all_to_history()
{ {
l_node *node; while (displayed) {
notification *n; close_notification(displayed->n, 2);
while (!l_is_empty(displayed_notifications)) {
node = displayed_notifications->head;
n = (notification *) node->data;
close_notification(n, 2);
} }
n = n_queue_dequeue(&queue); notification *n = n_queue_dequeue(&queue);
while (n) { while (n) {
n_stack_push(&history, n); n_stack_push(&history, n);
n = n_queue_dequeue(&queue); n = n_queue_dequeue(&queue);
@ -885,9 +858,8 @@ int init_notification(notification * n, int id)
} }
} }
for (l_node * iter = displayed_notifications->head; iter; for (n_queue *iter = displayed; iter; iter = iter->next) {
iter = iter->next) { notification *orig = iter->n;
notification *orig = (notification *) iter->data;
if (strcmp(orig->appname, n->appname) == 0 if (strcmp(orig->appname, n->appname) == 0
&& strcmp(orig->msg, n->msg) == 0) { && strcmp(orig->msg, n->msg) == 0) {
orig->dup_count++; orig->dup_count++;
@ -952,22 +924,20 @@ int close_notification_by_id(int id, int reason)
{ {
notification *target = NULL; notification *target = NULL;
for (l_node *iter = displayed_notifications->head; iter; iter = iter->next) { for (n_queue *iter = displayed; iter; iter = iter->next) {
notification *n = (notification *) iter->data; notification *n = iter->n;
if (n->id == id) { if (n->id == id) {
l_remove(displayed_notifications, iter); n_queue_remove(&displayed, n);
n_stack_push(&history, n); n_stack_push(&history, n);
target = n; target = n;
break; 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; notification *n = iter->next->n;
if (n->id == id) { if (n->id == id) {
n_queue *tmp = iter->next; n_queue_remove(&queue, n);
iter->next = iter->next->next;
free(tmp);
n_stack_push(&history, n); n_stack_push(&history, n);
target = n; target = n;
break; break;
@ -1098,7 +1068,7 @@ void run(void)
/* move messages from notification_queue to displayed_notifications */ /* move messages from notification_queue to displayed_notifications */
update_lists(); update_lists();
if (l_length(displayed_notifications) > 0) { if (displayed) {
if (!visible) { if (!visible) {
map_win(); map_win();
} else { } else {
@ -1306,7 +1276,7 @@ void setup(void)
void map_win(void) void map_win(void)
{ {
/* window is already mapped or there's nothing to show */ /* window is already mapped or there's nothing to show */
if (visible || l_is_empty(displayed_notifications)) { if (visible || !displayed) {
return; return;
} }
@ -1576,7 +1546,6 @@ int main(int argc, char *argv[])
{ {
now = time(&now); now = time(&now);
displayed_notifications = l_init();
r_line_cache_init(&line_cache); r_line_cache_init(&line_cache);