Use glib instead of libev

This commit ports awesome from libev to the glib main loop. This means that
awesome has fewer dependencies, because we were already depending on glib before
and now no longer need glib.

However, the main reason for this change is that, thanks to lgi, we have glib
bindings for lua. This means that lua code can add all kinds of event sources to
the main loop (timeouts, fd watchers, SIGCHLD watchers, ....). Yay

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2012-11-21 21:01:12 +01:00
parent dbf20000a5
commit ea30119410
8 changed files with 100 additions and 137 deletions

View File

@ -35,6 +35,8 @@
#include <X11/Xlib-xcb.h>
#include <glib-unix.h>
#include "awesome.h"
#include "spawn.h"
#include "objects/client.h"
@ -76,8 +78,6 @@ awesome_atexit(bool restart)
/* Disconnect *after* closing lua */
xcb_disconnect(globalconf.connection);
ev_default_destroy();
}
/** Scan X to find windows to manage.
@ -156,13 +156,7 @@ scan(xcb_query_tree_cookie_t tree_c)
}
static void
a_refresh_cb(EV_P_ ev_prepare *w, int revents)
{
awesome_refresh();
}
static void
a_xcb_check_cb(EV_P_ ev_check *w, int revents)
a_xcb_check(void)
{
xcb_generic_event_t *mouse = NULL, *event;
@ -200,13 +194,25 @@ a_xcb_check_cb(EV_P_ ev_check *w, int revents)
}
}
static void
a_xcb_io_cb(EV_P_ ev_io *w, int revents)
static gboolean
a_xcb_io_cb(GIOChannel *source, GIOCondition cond, gpointer data)
{
/* a_xcb_check_cb() already handled all events */
/* a_xcb_check() already handled all events */
if(xcb_connection_has_error(globalconf.connection))
fatal("X server connection broke");
return TRUE;
}
static gint
a_glib_poll(GPollFD *ufds, guint nfsd, gint timeout)
{
guint res;
awesome_refresh();
res = g_poll(ufds, nfsd, timeout);
a_xcb_check();
return res;
}
static void
@ -218,13 +224,13 @@ signal_fatal(int signum)
}
/** Function to exit on some signals.
* \param w the signal received, unused
* \param revents currently unused
* \param data currently unused
*/
static void
exit_on_signal(EV_P_ ev_signal *w, int revents)
static gboolean
exit_on_signal(gpointer data)
{
ev_unloop(EV_A_ 1);
g_main_loop_quit(globalconf.loop);
return TRUE;
}
void
@ -235,13 +241,13 @@ awesome_restart(void)
}
/** Function to restart awesome on some signals.
* \param w the signal received, unused
* \param revents Currently unused
* \param data currently unused
*/
static void
restart_on_signal(EV_P_ ev_signal *w, int revents)
static gboolean
restart_on_signal(gpointer data)
{
awesome_restart();
return TRUE;
}
/** Print help and exit(2) with given exit_code.
@ -285,14 +291,6 @@ main(int argc, char **argv)
{ NULL, 0, NULL, 0 }
};
/* event loop watchers */
ev_io xio = { .fd = -1 };
ev_check xcheck;
ev_prepare a_refresh;
ev_signal sigint;
ev_signal sigterm;
ev_signal sighup;
/* clear the globalconf structure */
p_clear(&globalconf, 1);
globalconf.keygrabber = LUA_REFNIL;
@ -354,18 +352,10 @@ main(int argc, char **argv)
break;
}
globalconf.loop = ev_default_loop(EVFLAG_NOSIGFD);
/* register function for signals */
ev_signal_init(&sigint, exit_on_signal, SIGINT);
ev_signal_init(&sigterm, exit_on_signal, SIGTERM);
ev_signal_init(&sighup, restart_on_signal, SIGHUP);
ev_signal_start(globalconf.loop, &sigint);
ev_signal_start(globalconf.loop, &sigterm);
ev_signal_start(globalconf.loop, &sighup);
ev_unref(globalconf.loop);
ev_unref(globalconf.loop);
ev_unref(globalconf.loop);
g_unix_signal_add(SIGINT, exit_on_signal, NULL);
g_unix_signal_add(SIGTERM, exit_on_signal, NULL);
g_unix_signal_add(SIGHUP, restart_on_signal, NULL);
struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 };
sigemptyset(&sa.sa_mask);
@ -408,19 +398,17 @@ main(int argc, char **argv)
xcb_prefetch_extension_data(globalconf.connection, &xcb_xinerama_id);
xcb_prefetch_extension_data(globalconf.connection, &xcb_shape_id);
/* Setup the main context */
g_main_context_set_poll_func(g_main_context_default(), &a_glib_poll);
/* initialize dbus */
a_dbus_init();
/* Get the file descriptor corresponding to the X connection */
xfd = xcb_get_file_descriptor(globalconf.connection);
ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ);
ev_io_start(globalconf.loop, &xio);
ev_check_init(&xcheck, &a_xcb_check_cb);
ev_check_start(globalconf.loop, &xcheck);
ev_unref(globalconf.loop);
ev_prepare_init(&a_refresh, &a_refresh_cb);
ev_prepare_start(globalconf.loop, &a_refresh);
ev_unref(globalconf.loop);
GIOChannel *channel = g_io_channel_unix_new(xfd);
g_io_add_watch(channel, G_IO_IN, a_xcb_io_cb, NULL);
g_io_channel_unref(channel);
/* Grab server */
xcb_grab_server(globalconf.connection);
@ -531,15 +519,10 @@ main(int argc, char **argv)
xcb_flush(globalconf.connection);
/* main event loop */
ev_loop(globalconf.loop, 0);
/* cleanup event loop */
ev_ref(globalconf.loop);
ev_check_stop(globalconf.loop, &xcheck);
ev_ref(globalconf.loop);
ev_prepare_stop(globalconf.loop, &a_refresh);
ev_ref(globalconf.loop);
ev_io_stop(globalconf.loop, &xio);
globalconf.loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(globalconf.loop);
g_main_loop_unref(globalconf.loop);
globalconf.loop = NULL;
awesome_atexit(false);

View File

@ -159,9 +159,6 @@ macro(a_find_library variable library)
endif()
endmacro()
# Check for libev
a_find_library(LIB_EV ev)
# Check for backtrace_symbols()
include(CheckFunctionExists)
check_function_exists(backtrace_symbols HAS_EXECINFO)
@ -198,7 +195,6 @@ endif()
set(AWESOME_REQUIRED_LDFLAGS
${AWESOME_COMMON_REQUIRED_LDFLAGS}
${AWESOME_REQUIRED_LDFLAGS}
${LIB_EV}
${LUA_LIBRARIES})
set(AWESOME_REQUIRED_INCLUDE_DIRS

58
dbus.c
View File

@ -22,10 +22,10 @@
#include "config.h"
#include "dbus.h"
#include <glib.h>
#ifdef WITH_DBUS
#include <ev.h>
#include <dbus/dbus.h>
#include <unistd.h>
#include <fcntl.h>
@ -35,8 +35,8 @@
static DBusConnection *dbus_connection_session = NULL;
static DBusConnection *dbus_connection_system = NULL;
ev_io dbusio_ses = { .fd = -1 };
ev_io dbusio_sys = { .fd = -1 };
static GSource *session_source = NULL;
static GSource *system_source = NULL;
static signal_array_t dbus_signals;
@ -45,17 +45,14 @@ static signal_array_t dbus_signals;
* \param dbusio The D-Bus event watcher
*/
static void
a_dbus_cleanup_bus(DBusConnection *dbus_connection, ev_io *dbusio)
a_dbus_cleanup_bus(DBusConnection *dbus_connection, GSource **source)
{
if(!dbus_connection)
return;
if(dbusio->fd >= 0)
{
ev_ref(EV_DEFAULT_UC);
ev_io_stop(EV_DEFAULT_UC_ dbusio);
dbusio->fd = -1;
}
if (*source != NULL)
g_source_destroy(*source);
*source = NULL;
/* This is a shared connection owned by libdbus
* Do not close it, only unref
@ -462,7 +459,7 @@ a_dbus_process_request(DBusConnection *dbus_connection, DBusMessage *msg)
* \param dbusio The D-Bus event watcher
*/
static void
a_dbus_process_requests_on_bus(DBusConnection *dbus_connection, ev_io *dbusio)
a_dbus_process_requests_on_bus(DBusConnection *dbus_connection, GSource **source)
{
DBusMessage *msg;
int nmsg = 0;
@ -476,7 +473,7 @@ a_dbus_process_requests_on_bus(DBusConnection *dbus_connection, ev_io *dbusio)
if(dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
{
a_dbus_cleanup_bus(dbus_connection, dbusio);
a_dbus_cleanup_bus(dbus_connection, source);
dbus_message_unref(msg);
return;
}
@ -496,20 +493,22 @@ a_dbus_process_requests_on_bus(DBusConnection *dbus_connection, ev_io *dbusio)
* \param w The D-Bus event watcher
* \param revents (not used)
*/
static void
a_dbus_process_requests_session(EV_P_ ev_io *w, int revents)
static gboolean
a_dbus_process_requests_session(GIOChannel *source, GIOCondition cond, gpointer data)
{
a_dbus_process_requests_on_bus(dbus_connection_session, w);
a_dbus_process_requests_on_bus(dbus_connection_session, &session_source);
return TRUE;
}
/** Foreword D-Bus process system requests on too the correct function.
* \param w The D-Bus event watcher
* \param revents (not used)
*/
static void
a_dbus_process_requests_system(EV_P_ ev_io *w, int revents)
static gboolean
a_dbus_process_requests_system(GIOChannel *source, GIOCondition cond, gpointer data)
{
a_dbus_process_requests_on_bus(dbus_connection_system, w);
a_dbus_process_requests_on_bus(dbus_connection_system, &system_source);
return TRUE;
}
/** Attempt to request a D-Bus name
@ -588,13 +587,12 @@ a_dbus_release_name(DBusConnection *dbus_connection, const char *name)
/** Attempt to create a new connection to D-Bus
* \param type The bus type to use when connecting to D-Bus
* \param type_name The bus type name eg: "session" or "system"
* \param dbusio The D-Bus event watcher
* \param cb Function callback to use when processing requests
* \param source A new GSource that will be used for watching the dbus connection.
* \return The requested D-Bus connection on success, NULL on failure.
*/
static DBusConnection *
a_dbus_connect(DBusBusType type, const char *type_name,
ev_io *dbusio, void *cb)
a_dbus_connect(DBusBusType type, const char *type_name, GIOFunc cb, GSource **source)
{
int fd;
DBusConnection *dbus_connection;
@ -614,16 +612,16 @@ a_dbus_connect(DBusBusType type, const char *type_name,
dbus_connection_set_exit_on_disconnect(dbus_connection, false);
if(dbus_connection_get_unix_fd(dbus_connection, &fd))
{
fcntl(fd, F_SETFD, FD_CLOEXEC);
GIOChannel *channel = g_io_channel_unix_new(fd);
*source = g_io_create_watch(channel, G_IO_IN);
g_io_channel_unref(channel);
ev_io_init(dbusio, cb, fd, EV_READ);
ev_io_start(EV_DEFAULT_UC_ dbusio);
ev_unref(EV_DEFAULT_UC);
fcntl(fd, F_SETFD, FD_CLOEXEC);
}
else
{
warn("cannot get D-Bus connection file descriptor");
a_dbus_cleanup_bus(dbus_connection, dbusio);
a_dbus_cleanup_bus(dbus_connection, source);
}
}
@ -636,9 +634,9 @@ void
a_dbus_init(void)
{
dbus_connection_session = a_dbus_connect(DBUS_BUS_SESSION, "session",
&dbusio_ses, a_dbus_process_requests_session);
a_dbus_process_requests_session, &session_source);
dbus_connection_system = a_dbus_connect(DBUS_BUS_SYSTEM, "system",
&dbusio_sys, a_dbus_process_requests_system);
a_dbus_process_requests_system, &system_source);
}
/** Cleanup the D-Bus session and system
@ -646,8 +644,8 @@ a_dbus_init(void)
void
a_dbus_cleanup(void)
{
a_dbus_cleanup_bus(dbus_connection_session, &dbusio_ses);
a_dbus_cleanup_bus(dbus_connection_system, &dbusio_sys);
a_dbus_cleanup_bus(dbus_connection_session, &session_source);
a_dbus_cleanup_bus(dbus_connection_system, &system_source);
}
/** Retrieve the D-Bus bus by it's name

View File

@ -25,7 +25,7 @@
#define SN_API_NOT_YET_FROZEN
#include <libsn/sn.h>
#include <ev.h>
#include <glib.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_keysyms.h>
@ -94,8 +94,8 @@ typedef struct
lua_State *L;
/** All errors messages from loading config files */
buffer_t startup_errors;
/** The event loop */
struct ev_loop *loop;
/** main loop that awesome is running on */
GMainLoop *loop;
/** The key grabber function */
int keygrabber;
/** The mouse pointer grabber function */

4
luaa.c
View File

@ -21,8 +21,6 @@
#define _GNU_SOURCE
#include <ev.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
@ -69,7 +67,7 @@ static char *conffile;
static int
luaA_quit(lua_State *L)
{
ev_unloop(globalconf.loop, 1);
g_main_loop_quit(globalconf.loop);
return 0;
}

2
luaa.h
View File

@ -22,8 +22,6 @@
#ifndef AWESOME_LUA_H
#define AWESOME_LUA_H
#include <ev.h>
#include <lua.h>
#include <lauxlib.h>

View File

@ -19,8 +19,6 @@
*
*/
#include <ev.h>
#include "globalconf.h"
#include "luaa.h"
#include "timer.h"
@ -30,27 +28,26 @@ typedef struct
{
LUA_OBJECT_HEADER
bool started;
struct ev_timer timer;
guint source_id;
double timeout;
} atimer_t;
static lua_class_t timer_class;
LUA_OBJECT_FUNCS(timer_class, atimer_t, timer)
static void
ev_timer_emit_signal(struct ev_loop *loop, struct ev_timer *w, int revents)
static gboolean
timer_emit_signal(gpointer data)
{
luaA_object_push(globalconf.L, w->data);
luaA_object_push(globalconf.L, data);
luaA_object_emit_signal(globalconf.L, -1, "timeout", 0);
lua_pop(globalconf.L, 1);
return TRUE;
}
static int
luaA_timer_new(lua_State *L)
{
luaA_class_new(L, &timer_class);
atimer_t *timer = luaA_checkudata(L, -1, &timer_class);
timer->timer.data = timer;
ev_set_cb(&timer->timer, ev_timer_emit_signal);
return 1;
}
@ -58,7 +55,7 @@ static int
luaA_timer_set_timeout(lua_State *L, atimer_t *timer)
{
double timeout = luaL_checknumber(L, -1);
ev_timer_set(&timer->timer, timeout, timeout);
timer->timeout = timeout;
luaA_object_emit_signal(L, -3, "property::timeout", 0);
return 0;
}
@ -66,7 +63,7 @@ luaA_timer_set_timeout(lua_State *L, atimer_t *timer)
static int
luaA_timer_get_timeout(lua_State *L, atimer_t *timer)
{
lua_pushnumber(L, timer->timer.repeat);
lua_pushnumber(L, timer->timeout);
return 1;
}
@ -79,8 +76,8 @@ luaA_timer_start(lua_State *L)
else
{
luaA_object_ref(L, 1);
ev_timer_start(globalconf.loop, &timer->timer);
timer->started = true;
timer->source_id = g_timeout_add(timer->timeout * 1000, timer_emit_signal, timer);
}
return 0;
}
@ -91,7 +88,7 @@ luaA_timer_stop(lua_State *L)
atimer_t *timer = luaA_checkudata(L, 1, &timer_class);
if(timer->started)
{
ev_timer_stop(globalconf.loop, &timer->timer);
g_source_remove(timer->source_id);
luaA_object_unref(L, timer);
timer->started = false;
}
@ -105,13 +102,12 @@ luaA_timer_again(lua_State *L)
{
atimer_t *timer = luaA_checkudata(L, 1, &timer_class);
ev_timer_again(globalconf.loop, &timer->timer);
if(!timer->started)
{
if (timer->started)
g_source_remove(timer->source_id);
else
luaA_object_ref(L, 1);
timer->started = true;
}
timer->source_id = g_timeout_add(timer->timeout * 1000, timer_emit_signal, timer);
return 0;
}

32
spawn.c
View File

@ -64,10 +64,10 @@ spawn_sequence_remove(SnStartupSequence *s)
return false;
}
static void
spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents)
static gboolean
spawn_monitor_timeout(gpointer sequence)
{
if(spawn_sequence_remove(w->data))
if(spawn_sequence_remove(sequence))
{
signal_t *sig = signal_array_getbyid(&global_signals,
a_strhash((const unsigned char *) "spawn::timeout"));
@ -75,7 +75,7 @@ spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents)
{
/* send a timeout signal */
lua_createtable(globalconf.L, 0, 2);
lua_pushstring(globalconf.L, sn_startup_sequence_get_id(w->data));
lua_pushstring(globalconf.L, sn_startup_sequence_get_id(sequence));
lua_setfield(globalconf.L, -2, "id");
foreach(func, sig->sigfuncs)
{
@ -88,8 +88,8 @@ spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents)
else
warn("spawn::timeout signal is missing");
}
sn_startup_sequence_unref(w->data);
p_delete(&w);
sn_startup_sequence_unref(sequence);
return FALSE;
}
static void
@ -114,12 +114,9 @@ spawn_monitor_event(SnMonitorEvent *event, void *data)
/* Add a timeout function so we do not wait for this event to complete
* for ever */
struct ev_timer *ev_timeout = p_new(struct ev_timer, 1);
ev_timer_init(ev_timeout, spawn_monitor_timeout, AWESOME_SPAWN_TIMEOUT, 0.);
g_timeout_add_seconds(AWESOME_SPAWN_TIMEOUT, spawn_monitor_timeout, sequence);
/* ref the sequence for the callback event */
sn_startup_sequence_ref(sequence);
ev_timeout->data = sequence;
ev_timer_start(globalconf.loop, ev_timeout);
break;
case SN_MONITOR_EVENT_CHANGED:
event_type_str = "spawn::change";
@ -252,12 +249,12 @@ spawn_init(void)
signal_add(&global_signals, "spawn::timeout");
}
static void
spawn_launchee_timeout(struct ev_loop *loop, ev_timer *w, int revents)
static gboolean
spawn_launchee_timeout(gpointer context)
{
sn_launcher_context_complete(w->data);
sn_launcher_context_unref(w->data);
p_delete(&w);
sn_launcher_context_complete(context);
sn_launcher_context_unref(context);
return FALSE;
}
static void
@ -335,10 +332,7 @@ luaA_spawn(lua_State *L)
/* app will have AWESOME_SPAWN_TIMEOUT seconds to complete,
* or the timeout function will terminate the launch sequence anyway */
struct ev_timer *ev_timeout = p_new(struct ev_timer, 1);
ev_timer_init(ev_timeout, spawn_launchee_timeout, AWESOME_SPAWN_TIMEOUT, 0.);
ev_timeout->data = context;
ev_timer_start(globalconf.loop, ev_timeout);
g_timeout_add_seconds(AWESOME_SPAWN_TIMEOUT, spawn_launchee_timeout, context);
sn_launcher_context_setup_child_process(context);
}