diff --git a/dbus.c b/dbus.c index 2fa1824ad..a7579cd93 100644 --- a/dbus.c +++ b/dbus.c @@ -30,12 +30,15 @@ #include #include "event.h" +#include "luaa.h" 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 signal_array_t dbus_signals; + static void a_dbus_cleanup_bus(DBusConnection *dbus_connection, ev_io *dbusio) { @@ -248,7 +251,11 @@ a_dbus_message_iter(DBusMessageIter *iter) static void a_dbus_process_request(DBusConnection *dbus_connection, DBusMessage *msg) { - if(globalconf.hooks.dbus == LUA_REFNIL) + const char *interface = dbus_message_get_interface(msg); + signal_t *sig = signal_array_getbyid(&dbus_signals, + a_strhash((const unsigned char *) interface)); + + if(!sig) return; lua_createtable(globalconf.L, 0, 5); @@ -274,11 +281,10 @@ a_dbus_process_request(DBusConnection *dbus_connection, DBusMessage *msg) lua_setfield(globalconf.L, -2, "type"); - const char *s = dbus_message_get_interface(msg); - lua_pushstring(globalconf.L, NONULL(s)); + lua_pushstring(globalconf.L, NONULL(interface)); lua_setfield(globalconf.L, -2, "interface"); - s = dbus_message_get_path(msg); + const char *s = dbus_message_get_path(msg); lua_pushstring(globalconf.L, NONULL(s)); lua_setfield(globalconf.L, -2, "path"); @@ -300,67 +306,85 @@ a_dbus_process_request(DBusConnection *dbus_connection, DBusMessage *msg) nargs += a_dbus_message_iter(&iter); if(dbus_message_get_no_reply(msg)) - luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.dbus, nargs, 0); - else - { - int n = lua_gettop(globalconf.L) - nargs; - luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.dbus, nargs, LUA_MULTRET); - n -= lua_gettop(globalconf.L); - - DBusMessage *reply = dbus_message_new_method_return(msg); - - dbus_message_iter_init_append(reply, &iter); - - /* i is negative */ - for(int i = n; i < 0; i += 2) + /* emit signals */ + foreach(func, sig->sigfuncs) { - /* i is the type name, i+1 the value */ - size_t len; - const char *type = lua_tolstring(globalconf.L, i, &len); + for(int i = 0; i < nargs; i++) + lua_pushvalue(globalconf.L, - nargs); + luaA_object_push(globalconf.L, (void *) *func); + luaA_dofunction(globalconf.L, nargs, 0); + } + else + foreach(func, sig->sigfuncs) + { + int n = lua_gettop(globalconf.L); - if(!type || len != 1) - break; + for(int i = 0; i < nargs; i++) + lua_pushvalue(globalconf.L, - nargs); + luaA_object_push(globalconf.L, (void *) *func); + luaA_dofunction(globalconf.L, nargs, LUA_MULTRET); - switch(*type) + n -= lua_gettop(globalconf.L); + + DBusMessage *reply = dbus_message_new_method_return(msg); + + dbus_message_iter_init_append(reply, &iter); + + /* i is negative */ + for(int i = n; i < 0; i += 2) { - case DBUS_TYPE_BOOLEAN: + /* i is the type name, i+1 the value */ + size_t len; + const char *type = lua_tolstring(globalconf.L, i, &len); + + if(!type || len != 1) { - dbus_bool_t b = lua_toboolean(globalconf.L, i + 1); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b); + luaA_warn(globalconf.L, + "your D-Bus signal handling method returned bad data"); + return; } - break; + + switch(*type) + { + case DBUS_TYPE_BOOLEAN: + { + dbus_bool_t b = lua_toboolean(globalconf.L, i + 1); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b); + } + break; #define DBUS_MSG_RETURN_HANDLE_TYPE_STRING(dbustype) \ - case dbustype: \ - if((s = lua_tostring(globalconf.L, i + 1))) \ + case dbustype: \ + if((s = lua_tostring(globalconf.L, i + 1))) \ dbus_message_iter_append_basic(&iter, dbustype, &s); \ - break; - DBUS_MSG_RETURN_HANDLE_TYPE_STRING(DBUS_TYPE_STRING) - DBUS_MSG_RETURN_HANDLE_TYPE_STRING(DBUS_TYPE_BYTE) + break; + DBUS_MSG_RETURN_HANDLE_TYPE_STRING(DBUS_TYPE_STRING) + DBUS_MSG_RETURN_HANDLE_TYPE_STRING(DBUS_TYPE_BYTE) #undef DBUS_MSG_RETURN_HANDLE_TYPE_STRING #define DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(type, dbustype) \ - case dbustype: \ - { \ - type num = lua_tonumber(globalconf.L, i + 1); \ - dbus_message_iter_append_basic(&iter, dbustype, &num); \ - } \ - break; - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16) - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16) - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32) - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32) - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64) - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64) - DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(double, DBUS_TYPE_DOUBLE) + case dbustype: \ + { \ + type num = lua_tonumber(globalconf.L, i + 1); \ + dbus_message_iter_append_basic(&iter, dbustype, &num); \ + } \ + break; + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16) + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16) + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32) + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32) + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64) + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64) + DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(double, DBUS_TYPE_DOUBLE) #undef DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER + } + + lua_remove(globalconf.L, i); + lua_remove(globalconf.L, i + 1); } - lua_remove(globalconf.L, i); - lua_remove(globalconf.L, i + 1); + dbus_connection_send(dbus_connection, reply, NULL); + dbus_message_unref(reply); } - - dbus_connection_send(dbus_connection, reply, NULL); - dbus_message_unref(reply); - } + lua_pop(globalconf.L, nargs); } static void @@ -622,12 +646,48 @@ luaA_dbus_remove_match(lua_State *L) return 0; } +/** Add a signal receiver on the D-Bus. + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam A string with the interface name. + * \lparam The function to call. + */ +static int +luaA_dbus_add_signal(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + luaA_checkfunction(L, 2); + signal_add(&dbus_signals, name, luaA_object_ref(L, 2)); + return 0; +} + +/** Add a signal receiver on the D-Bus. + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam A string with the interface name. + * \lparam The function to call. + */ +static int +luaA_dbus_remove_signal(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + luaA_checkfunction(L, 2); + const void *func = lua_topointer(L, 2); + signal_remove(&dbus_signals, name, func); + luaA_object_unref(L, (void *) func); + return 0; +} + const struct luaL_reg awesome_dbus_lib[] = { { "request_name", luaA_dbus_request_name }, { "release_name", luaA_dbus_release_name }, { "add_match", luaA_dbus_add_match }, { "remove_match", luaA_dbus_remove_match }, + { "add_signal", luaA_dbus_add_signal }, + { "remove_signal", luaA_dbus_remove_signal }, { NULL, NULL } }; diff --git a/hooks.c b/hooks.c index f1241936a..f6aec9b16 100644 --- a/hooks.c +++ b/hooks.c @@ -214,26 +214,6 @@ luaA_hooks_exit(lua_State *L) HANDLE_HOOK(L, globalconf.hooks.exit); } -#ifdef WITH_DBUS -/** Set the function to be called when a D-Bus event is received. - * The first argument passed to this function is the type of the message we - * receive: signal, method_call, method_return or error. - * The second argument is the path. - * The other arguments are a variable list of arguments. - * The function can return values using pair of type, value. - * For example: return "s", "hello", "i", 32 - * \param L The Lua VM state. - * \return The number of elements pushed on stack. - * \luastack - * \lparam A function to call on D-Bus events. - */ -static int -luaA_hooks_dbus(lua_State *L) -{ - HANDLE_HOOK(L, globalconf.hooks.dbus); -} -#endif - const struct luaL_reg awesome_hooks_lib[] = { { "focus", luaA_hooks_focus }, @@ -249,8 +229,5 @@ const struct luaL_reg awesome_hooks_lib[] = { "startup_notification", luaA_hooks_startup_notification }, { "timer", luaA_hooks_timer }, { "exit", luaA_hooks_exit }, -#ifdef WITH_DBUS - { "dbus", luaA_hooks_dbus }, -#endif { NULL, NULL } }; diff --git a/lib/awful/hooks.lua.in b/lib/awful/hooks.lua.in index e57d3a6ed..a84f5917d 100644 --- a/lib/awful/hooks.lua.in +++ b/lib/awful/hooks.lua.in @@ -123,18 +123,6 @@ for name, hook in pairs(capi.hooks) do end) end end - elseif name == "dbus" then - _M[name].register = function (interface, f) - if not _M[name].callbacks then - _M[name].callbacks = {} - hook(function (msg, ...) - if _M[name].callbacks[msg.interface] then - return _M[name].callbacks[msg.interface](msg, ...) - end - end) - end - _M[name].callbacks[interface] = f - end else _M[name].register = function (f) if not _M[name].callbacks then diff --git a/lib/awful/remote.lua.in b/lib/awful/remote.lua.in index ce3579a80..3abacab89 100644 --- a/lib/awful/remote.lua.in +++ b/lib/awful/remote.lua.in @@ -19,7 +19,7 @@ local type = type module("awful.remote") if dbus then - hooks.dbus.register("org.naquadah.awesome.awful.Remote", function(data, code) + dbus.add_signal("org.naquadah.awesome.awful.Remote", function(data, code) if data.member == "Eval" then local f, e = loadstring(code) if f then diff --git a/lib/naughty.lua.in b/lib/naughty.lua.in index b4feb065e..3ad2f0ca7 100644 --- a/lib/naughty.lua.in +++ b/lib/naughty.lua.in @@ -401,8 +401,8 @@ end -- DBUS/Notification support -- Notify -if hooks.dbus then - hooks.dbus.register("org.freedesktop.Notifications", function (data, appname, replaces_id, icon, title, text, actions, hints, expire) +if capi.dbus then + capi.dbus.add_signal("org.freedesktop.Notifications", function (data, appname, replaces_id, icon, title, text, actions, hints, expire) args = { preset = { } } if data.member == "Notify" then if text ~= "" then @@ -476,7 +476,7 @@ if hooks.dbus then end end) - hooks.dbus.register("org.freedesktop.DBus.Introspectable", + capi.dbus.add_signal("org.freedesktop.DBus.Introspectable", function (data, text) if data.member == "Introspect" then local xml = [=[