X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=obt%2Fxqueue.c;h=c04b226b55ca1f9bcf2efca3e618a07226a63420;hb=d67b818ae90c5574166d08422d3e9a68d8d65e16;hp=2304ea426c4acf06045cb89d43ae6447aae25b6f;hpb=55b84316bb699fa530efe78d75ae8e1d57c1b57f;p=chaz%2Fopenbox diff --git a/obt/xqueue.c b/obt/xqueue.c index 2304ea42..c04b226b 100644 --- a/obt/xqueue.c +++ b/obt/xqueue.c @@ -78,8 +78,8 @@ static inline void grow(void) { if (qend < qstart) { /* it wraps around to 0 right now */ for (i = 0; i <= qend; ++i) - q[newsz+i] = q[i]; - qend = newsz + qend; + q[qsz+i] = q[i]; + qend = qsz + qend; } qsz = newsz; @@ -113,7 +113,7 @@ static gboolean read_events(gboolean block) return sth; /* return if we read anything */ } -static void pop(gulong p) +static void pop(const gulong p) { /* remove the event */ --qnum; @@ -318,3 +318,94 @@ gboolean xqueue_pending_local(void) if (!qnum) read_events(FALSE); return qnum != 0; } + +typedef struct _ObtXQueueCB { + ObtXQueueFunc func; + gpointer data; +} ObtXQueueCB; + +static ObtXQueueCB *callbacks = NULL; +static guint n_callbacks = 0; + +static gboolean event_read(GSource *source, GSourceFunc callback, + gpointer data) +{ + XEvent ev; + + while (xqueue_next_local(&ev)) { + guint i; + for (i = 0; i < n_callbacks; ++i) + callbacks[i].func(&ev, callbacks[i].data); + } + + return TRUE; /* repeat */ +} + +static gboolean x_source_prepare(GSource *source, gint *timeout) +{ + *timeout = -1; + return XPending(obt_display); +} + +static gboolean x_source_check(GSource *source) +{ + return XPending(obt_display); +} + +struct x_source { + GSource source; + + GPollFD pfd; +}; + +static GSourceFuncs x_source_funcs = { + x_source_prepare, + x_source_check, + event_read, + NULL +}; + +void xqueue_listen(void) +{ + GSource *source = g_source_new(&x_source_funcs, sizeof(struct x_source)); + struct x_source *x_source = (struct x_source *)source; + GPollFD *pfd = &x_source->pfd; + + *pfd = (GPollFD){ ConnectionNumber(obt_display), G_IO_IN, G_IO_IN }; + g_source_add_poll(source, pfd); + g_source_attach(source, NULL); +} + +void xqueue_add_callback(ObtXQueueFunc f, gpointer data) +{ + guint i; + + g_return_if_fail(f != NULL); + + for (i = 0; i < n_callbacks; ++i) + if (callbacks[i].func == f && callbacks[i].data == data) + return; + + callbacks = g_renew(ObtXQueueCB, callbacks, n_callbacks + 1); + callbacks[n_callbacks].func = f; + callbacks[n_callbacks].data = data; + ++n_callbacks; +} + +void xqueue_remove_callback(ObtXQueueFunc f, gpointer data) +{ + guint i; + + g_return_if_fail(f != NULL); + + for (i = 0; i < n_callbacks; ++i) { + if (callbacks[i].func == f && callbacks[i].data == data) { + /* remove it */ + for (; i < n_callbacks - 1; ++i) + callbacks[i] = callbacks[i+1]; + callbacks = g_renew(ObtXQueueCB, callbacks, n_callbacks - 1); + --n_callbacks; + break; + } + } +}