Collect events in the main thread
This commit is contained in:
parent
3dd4e69235
commit
27a63e3414
68
wdmtg.c
68
wdmtg.c
|
@ -243,6 +243,41 @@ x_text_property(xcb_window_t window, xcb_atom_t property)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// --- Async Queue Source ------------------------------------------------------
|
||||
|
||||
static gboolean
|
||||
async_queue_source_prepare(G_GNUC_UNUSED GSource *source,
|
||||
G_GNUC_UNUSED gint *timeout_)
|
||||
{
|
||||
return g_async_queue_length(g.queue) > 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
async_queue_source_dispatch(G_GNUC_UNUSED GSource *source,
|
||||
GSourceFunc callback, gpointer user_data)
|
||||
{
|
||||
// I don't want to call it once per message, prefer batch processing
|
||||
if (callback)
|
||||
return callback(user_data);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static GSource *
|
||||
async_queue_source_new(void)
|
||||
{
|
||||
static GSourceFuncs funcs = {
|
||||
.prepare = async_queue_source_prepare,
|
||||
.check = NULL,
|
||||
.dispatch = async_queue_source_dispatch,
|
||||
.finalize = NULL,
|
||||
};
|
||||
|
||||
GSource *source = g_source_new(&funcs, sizeof *source);
|
||||
g_source_set_name(source, "AsyncQueueSource");
|
||||
return source;
|
||||
}
|
||||
|
||||
// --- Generator ---------------------------------------------------------------
|
||||
|
||||
static void
|
||||
|
@ -252,6 +287,9 @@ push_event(void) {
|
|||
event->title = g_strdup(gen.current_title);
|
||||
event->idle = gen.current_idle;
|
||||
g_async_queue_push(g.queue, event);
|
||||
|
||||
// This is the best thing GLib exposes (GWakeUp is internal)
|
||||
g_main_context_wakeup(g_main_context_default());
|
||||
}
|
||||
|
||||
static char *
|
||||
|
@ -309,11 +347,8 @@ update_current_window(void)
|
|||
}
|
||||
|
||||
free(gpr);
|
||||
if (update_window_title(new_title)) {
|
||||
printf("Window changed: %s\n",
|
||||
gen.current_title ? gen.current_title : "(none)");
|
||||
if (update_window_title(new_title))
|
||||
push_event();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -324,10 +359,8 @@ on_x_property_notify(const xcb_property_notify_event_t *ev)
|
|||
update_current_window();
|
||||
} else if (ev->window == gen.current_window &&
|
||||
ev->atom == gen.atom_net_wm_name) {
|
||||
if (update_window_title(x_window_title(ev->window))) {
|
||||
printf("Title changed: %s\n", gen.current_title);
|
||||
if (update_window_title(x_window_title(ev->window)))
|
||||
push_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,7 +390,6 @@ static void
|
|||
on_x_alarm_notify(const xcb_sync_alarm_notify_event_t *ev)
|
||||
{
|
||||
if (ev->alarm == gen.idle_alarm_inactive) {
|
||||
printf("User is inactive\n");
|
||||
gen.current_idle = true;
|
||||
push_event();
|
||||
|
||||
|
@ -369,7 +401,6 @@ on_x_alarm_notify(const xcb_sync_alarm_notify_event_t *ev)
|
|||
set_idle_alarm(&gen.idle_alarm_active,
|
||||
XCB_SYNC_TESTTYPE_NEGATIVE_COMPARISON, minus_one);
|
||||
} else if (ev->alarm == gen.idle_alarm_active) {
|
||||
printf("User is active\n");
|
||||
gen.current_idle = false;
|
||||
push_event();
|
||||
|
||||
|
@ -508,6 +539,18 @@ generator_cleanup(void)
|
|||
|
||||
// --- Main --------------------------------------------------------------------
|
||||
|
||||
static gboolean
|
||||
on_queue_incoming(G_GNUC_UNUSED gpointer user_data)
|
||||
{
|
||||
struct event *event = NULL;
|
||||
while ((event = g_async_queue_try_pop(g.queue))) {
|
||||
printf("Event: ts: %ld, title: %s, idle: %d\n",
|
||||
event->timestamp, event->title ?: "(none)", event->idle);
|
||||
event_free(event);
|
||||
}
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static sqlite3 *
|
||||
database_init(const gchar *db_path)
|
||||
{
|
||||
|
@ -642,10 +685,9 @@ main(int argc, char *argv[])
|
|||
g.db = database_init(db_path);
|
||||
g_free(db_path);
|
||||
|
||||
// TODO: somehow read events from the async queue
|
||||
// TODO: how in the name of fuck would our custom source wake up a sleeping
|
||||
// main loop? There is g_main_context_wakeup() but...
|
||||
// - GWakeUp is internal, apparently
|
||||
GSource *queue_source = async_queue_source_new();
|
||||
g_source_set_callback(queue_source, on_queue_incoming, NULL, NULL);
|
||||
g_source_attach(queue_source, g_main_context_default());
|
||||
|
||||
// TODO: listen for connections on the control socket
|
||||
|
||||
|
|
Loading…
Reference in New Issue