notification system (from user input to application basically)
This commit is contained in:
@@ -2,7 +2,7 @@ CC=gcc
|
||||
CFLAGS=-Wall -g -pthread
|
||||
|
||||
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
|
||||
gui.o label.o event.o xy_plot.o text_list.o
|
||||
gui.o label.o event.o xy_plot.o text_list.o notify.o
|
||||
|
||||
gui.a: $(OBJS)
|
||||
ar cr gui.a $(OBJS)
|
||||
|
||||
@@ -36,4 +36,19 @@ void gunlock(gui *gui);
|
||||
|
||||
int new_color(gui *gui, char *color);
|
||||
|
||||
/* notifications */
|
||||
/* known notifications:
|
||||
* - text_list:
|
||||
* - scrollup { }
|
||||
* - scrolldown { }
|
||||
* //- click { int line, int button }
|
||||
*/
|
||||
|
||||
/* same type as in gui_defs.h */
|
||||
typedef void (*notifier)(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data);
|
||||
unsigned long register_notifier(gui *g, char *notification, widget *w,
|
||||
notifier handler, void *private);
|
||||
void unregister_notifier(gui *g, unsigned long notifier_id);
|
||||
|
||||
#endif /* _GUI_H_ */
|
||||
|
||||
@@ -143,6 +143,24 @@ struct repack_event {
|
||||
int id;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* notifications */
|
||||
/*************************************************************************/
|
||||
|
||||
/* same type as in gui.h */
|
||||
typedef void (*notifier)(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data);
|
||||
|
||||
struct notifier {
|
||||
notifier handler;
|
||||
unsigned long id;
|
||||
char *notification;
|
||||
widget *w;
|
||||
void *private;
|
||||
/* done is used bu gui_notify */
|
||||
int done;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* main structure */
|
||||
/*************************************************************************/
|
||||
@@ -161,6 +179,9 @@ struct gui {
|
||||
void *xwin; /* set by a toplevel_window when
|
||||
* it paints itself, to be used
|
||||
* by its children */
|
||||
struct notifier *notifiers;
|
||||
int notifiers_count;
|
||||
unsigned long next_notifier_id;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -178,4 +199,7 @@ void gui_events(gui *gui);
|
||||
|
||||
struct widget *find_widget(struct gui *g, int id);
|
||||
|
||||
void gui_notify(struct gui *g, char *notification, widget *w,
|
||||
void *notification_data);
|
||||
|
||||
#endif /* _GUI_DEFS_H_ */
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned long register_notifier(gui *_g, char *notification, widget *w,
|
||||
notifier handler, void *private)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
unsigned long ret;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (g->next_notifier_id == 2UL * 1024 * 1024 * 1024)
|
||||
{ printf("%s:%d: report a bug\n", __FILE__, __LINE__); abort(); }
|
||||
|
||||
g->notifiers = realloc(g->notifiers,
|
||||
(g->notifiers_count+1) * sizeof(struct notifier));
|
||||
if (g->notifiers == NULL) abort();
|
||||
|
||||
ret = g->next_notifier_id;
|
||||
|
||||
g->notifiers[g->notifiers_count].handler = handler;
|
||||
g->notifiers[g->notifiers_count].id = g->next_notifier_id;
|
||||
g->next_notifier_id++;
|
||||
g->notifiers[g->notifiers_count].notification = strdup(notification);
|
||||
if (g->notifiers[g->notifiers_count].notification == NULL) abort();
|
||||
g->notifiers[g->notifiers_count].w = w;
|
||||
g->notifiers[g->notifiers_count].private = private;
|
||||
/* initialize done to 1 so as not to call the handler if it's created
|
||||
* by the call of another one that is in progress
|
||||
*/
|
||||
g->notifiers[g->notifiers_count].done = 1;
|
||||
|
||||
g->notifiers_count++;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unregister_notifier(gui *_g, unsigned long notifier_id)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
int i;
|
||||
|
||||
glock(g);
|
||||
|
||||
for (i = 0; i < g->notifiers_count; i++)
|
||||
if (g->notifiers[i].id == notifier_id) break;
|
||||
|
||||
if (i == g->notifiers_count) {
|
||||
printf("%s:%d: notifier_id %ld not found\n", __FILE__, __LINE__,
|
||||
notifier_id);
|
||||
abort();
|
||||
}
|
||||
|
||||
free(g->notifiers[i].notification);
|
||||
|
||||
memmove(g->notifiers + i, g->notifiers + i + 1,
|
||||
(g->notifiers_count-1 - i) * sizeof(struct notifier));
|
||||
|
||||
g->notifiers_count--;
|
||||
g->notifiers = realloc(g->notifiers,
|
||||
g->notifiers_count * sizeof(struct notifier));
|
||||
if (g->notifiers == NULL) abort();
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
/* called with lock ON */
|
||||
void gui_notify(struct gui *g, char *notification, widget *w,
|
||||
void *notification_data)
|
||||
{
|
||||
void *private;
|
||||
notifier handler;
|
||||
int i;
|
||||
|
||||
/* this function is not re-entrant, for the moment keep as is
|
||||
* and if the need is there, we'll make a new thread to handle
|
||||
* notifications (or something)
|
||||
* for now let's crash in case of recursive call
|
||||
*/
|
||||
static int inside = 0;
|
||||
if (inside)
|
||||
{printf("%s:%d: BUG! contact the authors\n", __FILE__, __LINE__);abort();}
|
||||
inside = 1;
|
||||
|
||||
/* clear all handlers */
|
||||
/* TODO: speedup */
|
||||
for (i = 0; i < g->notifiers_count; i++) g->notifiers[i].done = 0;
|
||||
|
||||
/* calling the handler may modify the list of notifiers, we
|
||||
* need to be careful here
|
||||
*/
|
||||
loop:
|
||||
for (i = 0; i < g->notifiers_count; i++) {
|
||||
if (g->notifiers[i].done == 1 ||
|
||||
g->notifiers[i].w != w ||
|
||||
strcmp(g->notifiers[i].notification, notification) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i == g->notifiers_count) goto done;
|
||||
|
||||
g->notifiers[i].done = 1;
|
||||
|
||||
handler = g->notifiers[i].handler;
|
||||
private = g->notifiers[i].private;
|
||||
|
||||
gunlock(g);
|
||||
handler(private, g, notification, w, notification_data);
|
||||
glock(g);
|
||||
|
||||
goto loop;
|
||||
|
||||
done:
|
||||
inside = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user