From f2195ba4e3fa66e04c7cc77df90789e2b78f04ac Mon Sep 17 00:00:00 2001 From: Cedric Roux <cedric.roux@eurecom.fr> Date: Fri, 29 Apr 2016 15:51:44 +0200 Subject: [PATCH] notification system (from user input to application basically) --- common/utils/T/tracer/gui/Makefile | 2 +- common/utils/T/tracer/gui/gui.h | 15 ++++ common/utils/T/tracer/gui/gui_defs.h | 24 ++++++ common/utils/T/tracer/gui/notify.c | 120 +++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 common/utils/T/tracer/gui/notify.c diff --git a/common/utils/T/tracer/gui/Makefile b/common/utils/T/tracer/gui/Makefile index 13820114dd..cc6a409e75 100644 --- a/common/utils/T/tracer/gui/Makefile +++ b/common/utils/T/tracer/gui/Makefile @@ -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) diff --git a/common/utils/T/tracer/gui/gui.h b/common/utils/T/tracer/gui/gui.h index 7646b0849e..b1321c1e49 100644 --- a/common/utils/T/tracer/gui/gui.h +++ b/common/utils/T/tracer/gui/gui.h @@ -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_ */ diff --git a/common/utils/T/tracer/gui/gui_defs.h b/common/utils/T/tracer/gui/gui_defs.h index 8f680c9503..9bb22c9daa 100644 --- a/common/utils/T/tracer/gui/gui_defs.h +++ b/common/utils/T/tracer/gui/gui_defs.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_ */ diff --git a/common/utils/T/tracer/gui/notify.c b/common/utils/T/tracer/gui/notify.c new file mode 100644 index 0000000000..dc6bc2fd59 --- /dev/null +++ b/common/utils/T/tracer/gui/notify.c @@ -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; +} -- GitLab