notification system (from user input to application basically)
This commit is contained in:
@@ -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);
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
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);
|
|||||||
|
|
||||||
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_ */
|
||||||
|
|||||||
@@ -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