Skip to content
Snippets Groups Projects
Commit f2195ba4 authored by Cédric Roux's avatar Cédric Roux
Browse files

notification system (from user input to application basically)

parent e742718c
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,7 @@ CC=gcc ...@@ -2,7 +2,7 @@ CC=gcc
CFLAGS=-Wall -g -pthread CFLAGS=-Wall -g -pthread
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \ 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) gui.a: $(OBJS)
ar cr gui.a $(OBJS) ar cr gui.a $(OBJS)
......
...@@ -36,4 +36,19 @@ void gunlock(gui *gui); ...@@ -36,4 +36,19 @@ void gunlock(gui *gui);
int new_color(gui *gui, char *color); 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_ */ #endif /* _GUI_H_ */
...@@ -143,6 +143,24 @@ struct repack_event { ...@@ -143,6 +143,24 @@ struct repack_event {
int id; 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 */ /* main structure */
/*************************************************************************/ /*************************************************************************/
...@@ -161,6 +179,9 @@ struct gui { ...@@ -161,6 +179,9 @@ struct gui {
void *xwin; /* set by a toplevel_window when void *xwin; /* set by a toplevel_window when
* it paints itself, to be used * it paints itself, to be used
* by its children */ * by its children */
struct notifier *notifiers;
int notifiers_count;
unsigned long next_notifier_id;
}; };
/*************************************************************************/ /*************************************************************************/
...@@ -178,4 +199,7 @@ void gui_events(gui *gui); ...@@ -178,4 +199,7 @@ void gui_events(gui *gui);
struct widget *find_widget(struct gui *g, int id); 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_ */ #endif /* _GUI_DEFS_H_ */
#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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment