dbus: add D-Bus hooks
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
53a830aea1
commit
a4254b195d
222
dbus.c
222
dbus.c
|
@ -18,7 +18,10 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "dbus.h"
|
||||
#include "client.h"
|
||||
|
||||
#ifdef WITH_DBUS
|
||||
|
||||
|
@ -27,9 +30,7 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "dbus.h"
|
||||
#include "widget.h"
|
||||
#include "client.h"
|
||||
|
||||
extern awesome_t globalconf;
|
||||
|
||||
|
@ -37,56 +38,193 @@ static DBusError err;
|
|||
static DBusConnection *dbus_connection = NULL;
|
||||
ev_io dbusio = { .fd = -1 };
|
||||
|
||||
/** Check a dbus object path format and its number of element.
|
||||
* \param path The path.
|
||||
* \param nelem The number of element it should have.
|
||||
* \return true if the path is ok, false otherwise.
|
||||
*/
|
||||
static bool
|
||||
a_dbus_path_check(char **path, int nelem)
|
||||
static int
|
||||
a_dbus_message_iter(DBusMessageIter *iter)
|
||||
{
|
||||
int i;
|
||||
int nargs = 0;
|
||||
|
||||
for(i = 0; path[i]; i++);
|
||||
if(i != nelem)
|
||||
return false;
|
||||
return (!a_strcmp(path[0], "org") && !a_strcmp(path[1], "awesome"));
|
||||
do
|
||||
{
|
||||
switch(dbus_message_iter_get_arg_type(iter))
|
||||
{
|
||||
case DBUS_TYPE_INVALID:
|
||||
break;
|
||||
case DBUS_TYPE_VARIANT:
|
||||
{
|
||||
DBusMessageIter subiter;
|
||||
dbus_message_iter_recurse(iter, &subiter);
|
||||
a_dbus_message_iter(&subiter);
|
||||
}
|
||||
nargs++;
|
||||
break;
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
{
|
||||
DBusMessageIter subiter;
|
||||
|
||||
/* initialize a sub iterator */
|
||||
dbus_message_iter_recurse(iter, &subiter);
|
||||
/* create a new table to store the dict */
|
||||
a_dbus_message_iter(&subiter);
|
||||
}
|
||||
nargs++;
|
||||
break;
|
||||
case DBUS_TYPE_ARRAY:
|
||||
{
|
||||
int array_type = dbus_message_iter_get_element_type(iter);
|
||||
|
||||
/* create a new table to store all the value */
|
||||
lua_newtable(globalconf.L);
|
||||
|
||||
if(dbus_type_is_fixed(array_type))
|
||||
switch(array_type)
|
||||
{
|
||||
int datalen;
|
||||
#define DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(type, dbustype) \
|
||||
case dbustype: \
|
||||
{ \
|
||||
type *data; \
|
||||
dbus_message_iter_get_fixed_array(iter, &data, &datalen); \
|
||||
for(int i = 0; i < datalen; i++) \
|
||||
{ \
|
||||
lua_pushnumber(globalconf.L, data[i]); \
|
||||
lua_rawseti(globalconf.L, -2, i + 1); \
|
||||
} \
|
||||
} \
|
||||
break;
|
||||
DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16)
|
||||
DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16)
|
||||
DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32)
|
||||
DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32)
|
||||
DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64)
|
||||
DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64)
|
||||
#undef DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER
|
||||
}
|
||||
else if(array_type == DBUS_TYPE_DICT_ENTRY)
|
||||
{
|
||||
DBusMessageIter subiter;
|
||||
|
||||
/* initialize a sub iterator */
|
||||
dbus_message_iter_recurse(iter, &subiter);
|
||||
/* get the keys and the values
|
||||
* n is the number of entry in * dict */
|
||||
int n = a_dbus_message_iter(&subiter);
|
||||
|
||||
for(int i = 0; i < n; i ++)
|
||||
lua_rawset(globalconf.L, - (n * 2) - 1 + i * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBusMessageIter subiter;
|
||||
|
||||
/* prepare to dig into the array*/
|
||||
dbus_message_iter_recurse(iter, &subiter);
|
||||
|
||||
/* now iterate over every element of the array */
|
||||
int n = a_dbus_message_iter(&subiter);
|
||||
|
||||
for(int i = n; i > 0; i--)
|
||||
{
|
||||
lua_rawseti(globalconf.L, - i - 1, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
nargs++;
|
||||
break;
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
{
|
||||
bool b;
|
||||
dbus_message_iter_get_basic(iter, &b);
|
||||
lua_pushboolean(globalconf.L, b);
|
||||
}
|
||||
nargs++;
|
||||
break;
|
||||
case DBUS_TYPE_BYTE:
|
||||
{
|
||||
char c;
|
||||
dbus_message_iter_get_basic(iter, &c);
|
||||
lua_pushlstring(globalconf.L, &c, 1);
|
||||
}
|
||||
nargs++;
|
||||
break;
|
||||
#define DBUS_MSG_HANDLE_TYPE_NUMBER(type, dbustype) \
|
||||
case dbustype: \
|
||||
{ \
|
||||
type ui; \
|
||||
dbus_message_iter_get_basic(iter, &ui); \
|
||||
lua_pushnumber(globalconf.L, ui); \
|
||||
} \
|
||||
nargs++; \
|
||||
break;
|
||||
DBUS_MSG_HANDLE_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16)
|
||||
DBUS_MSG_HANDLE_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16)
|
||||
DBUS_MSG_HANDLE_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32)
|
||||
DBUS_MSG_HANDLE_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32)
|
||||
DBUS_MSG_HANDLE_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64)
|
||||
DBUS_MSG_HANDLE_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64)
|
||||
#undef DBUS_MSG_HANDLE_TYPE_NUMBER
|
||||
case DBUS_TYPE_STRING:
|
||||
{
|
||||
char *s;
|
||||
dbus_message_iter_get_basic(iter, &s);
|
||||
lua_pushstring(globalconf.L, s);
|
||||
}
|
||||
nargs++;
|
||||
break;
|
||||
}
|
||||
} while(dbus_message_iter_next(iter));
|
||||
|
||||
return nargs;
|
||||
}
|
||||
|
||||
static void
|
||||
a_dbus_process_request_do(DBusMessage *msg)
|
||||
a_dbus_process_request(DBusMessage *msg)
|
||||
{
|
||||
int i;
|
||||
DBusMessageIter iter;
|
||||
char **path, *cmd;
|
||||
|
||||
if(!dbus_message_get_path_decomposed(msg, &path))
|
||||
if(globalconf.hooks.dbus == LUA_REFNIL)
|
||||
return;
|
||||
|
||||
/* path is:
|
||||
* /org/awesome */
|
||||
if(!a_dbus_path_check(path, 2))
|
||||
goto bailout;
|
||||
lua_newtable(globalconf.L);
|
||||
|
||||
if(!dbus_message_iter_init(msg, &iter))
|
||||
switch(dbus_message_get_type(msg))
|
||||
{
|
||||
dbus_error_free(&err);
|
||||
goto bailout;
|
||||
case DBUS_MESSAGE_TYPE_SIGNAL:
|
||||
lua_pushliteral(globalconf.L, "signal");
|
||||
break;
|
||||
case DBUS_MESSAGE_TYPE_METHOD_CALL:
|
||||
lua_pushliteral(globalconf.L, "method_call");
|
||||
break;
|
||||
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
|
||||
lua_pushliteral(globalconf.L, "method_return");
|
||||
break;
|
||||
case DBUS_MESSAGE_TYPE_ERROR:
|
||||
lua_pushliteral(globalconf.L, "error");
|
||||
break;
|
||||
default:
|
||||
lua_pushliteral(globalconf.L, "unknown");
|
||||
break;
|
||||
}
|
||||
else if(DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter))
|
||||
{
|
||||
dbus_error_free(&err);
|
||||
goto bailout;
|
||||
}
|
||||
else
|
||||
dbus_message_iter_get_basic(&iter, &cmd);
|
||||
|
||||
luaA_dostring(globalconf.L, cmd);
|
||||
lua_setfield(globalconf.L, -2, "type");
|
||||
|
||||
bailout:
|
||||
for(i = 0; path[i]; i++)
|
||||
p_delete(&path[i]);
|
||||
p_delete(&path);
|
||||
const char *s = dbus_message_get_interface(msg);
|
||||
lua_pushstring(globalconf.L, NONULL(s));
|
||||
lua_setfield(globalconf.L, -2, "interface");
|
||||
|
||||
s = dbus_message_get_path(msg);
|
||||
lua_pushstring(globalconf.L, NONULL(s));
|
||||
lua_setfield(globalconf.L, -2, "path");
|
||||
|
||||
s = dbus_message_get_member(msg);
|
||||
lua_pushstring(globalconf.L, NONULL(s));
|
||||
lua_setfield(globalconf.L, -2, "member");
|
||||
|
||||
/* + 1 for the table above */
|
||||
DBusMessageIter iter;
|
||||
int nargs = 1;
|
||||
|
||||
if(dbus_message_iter_init(msg, &iter))
|
||||
nargs += a_dbus_message_iter(&iter);
|
||||
|
||||
luaA_dofunction(globalconf.L, globalconf.hooks.dbus, nargs, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -111,8 +249,8 @@ a_dbus_process_requests(EV_P_ ev_io *w, int revents)
|
|||
dbus_message_unref(msg);
|
||||
return;
|
||||
}
|
||||
else if(dbus_message_is_method_call(msg, "org.awesome", "do"))
|
||||
a_dbus_process_request_do(msg);
|
||||
else
|
||||
a_dbus_process_request(msg);
|
||||
|
||||
dbus_message_unref(msg);
|
||||
|
||||
|
@ -196,8 +334,6 @@ a_dbus_cleanup(void)
|
|||
|
||||
#else /* HAVE_DBUS */
|
||||
|
||||
#include "dbus.h"
|
||||
|
||||
bool
|
||||
a_dbus_init(void)
|
||||
{
|
||||
|
|
21
hooks.c
21
hooks.c
|
@ -174,6 +174,24 @@ luaA_hooks_timer(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#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.
|
||||
* \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)
|
||||
{
|
||||
return luaA_registerfct(L, 1, &globalconf.hooks.dbus);
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct luaL_reg awesome_hooks_lib[] =
|
||||
{
|
||||
{ "focus", luaA_hooks_focus },
|
||||
|
@ -187,5 +205,8 @@ const struct luaL_reg awesome_hooks_lib[] =
|
|||
{ "tags", luaA_hooks_tags },
|
||||
{ "tagged", luaA_hooks_tagged },
|
||||
{ "timer", luaA_hooks_timer },
|
||||
#ifdef WITH_DBUS
|
||||
{ "dbus", luaA_hooks_dbus },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
-- Grab environment we need
|
||||
local pairs = pairs
|
||||
local table = table
|
||||
local unpack = unpack
|
||||
local ipairs = ipairs
|
||||
local type = type
|
||||
local math = math
|
||||
|
@ -50,32 +51,8 @@ end
|
|||
-- Autodeclare awful.hooks.* functions
|
||||
-- mapped to awesome hooks.* functions
|
||||
for name, hook in pairs(capi.hooks) do
|
||||
if name ~= 'timer' then
|
||||
_M[name] = {}
|
||||
_M[name].register = function (f)
|
||||
if not _M[name].callbacks then
|
||||
_M[name].callbacks = {}
|
||||
hook(function (...)
|
||||
for i, callback in ipairs(_M[name].callbacks) do
|
||||
callback(...)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
table.insert(_M[name].callbacks, f)
|
||||
end
|
||||
_M[name].unregister = function (f)
|
||||
if _M[name].callbacks then
|
||||
for k, h in ipairs(_M[name].callbacks) do
|
||||
if h == f then
|
||||
table.remove(_M[name].callbacks, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
_M[name] = {}
|
||||
if name == 'timer' then
|
||||
_M[name].register = function (time, f, runnow)
|
||||
if type(time) ~= 'number' or type(f) ~= 'function' or time <= 0 then
|
||||
return
|
||||
|
@ -119,6 +96,44 @@ 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, unpack(arg))
|
||||
end
|
||||
end)
|
||||
end
|
||||
_M[name].callbacks[interface] = f
|
||||
end
|
||||
else
|
||||
_M[name].register = function (f)
|
||||
if not _M[name].callbacks then
|
||||
_M[name].callbacks = {}
|
||||
hook(function (...)
|
||||
for i, callback in ipairs(_M[name].callbacks) do
|
||||
callback(...)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
table.insert(_M[name].callbacks, f)
|
||||
end
|
||||
end
|
||||
|
||||
if name ~= "timer" then
|
||||
_M[name].unregister = function (f)
|
||||
if _M[name].callbacks then
|
||||
for k, h in ipairs(_M[name].callbacks) do
|
||||
if h == f then
|
||||
table.remove(_M[name].callbacks, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
3
luaa.c
3
luaa.c
|
@ -823,6 +823,9 @@ luaA_init(void)
|
|||
globalconf.hooks.tagged = LUA_REFNIL;
|
||||
globalconf.hooks.property = LUA_REFNIL;
|
||||
globalconf.hooks.timer = LUA_REFNIL;
|
||||
#ifdef WITH_DBUS
|
||||
globalconf.hooks.dbus = LUA_REFNIL;
|
||||
#endif
|
||||
|
||||
/* add Lua lib path (/usr/share/awesome/lib by default) */
|
||||
luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?.lua\"");
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xcb_property.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "luaa.h"
|
||||
#include "layout.h"
|
||||
#include "swindow.h"
|
||||
|
@ -351,6 +352,10 @@ struct awesome_t
|
|||
luaA_ref property;
|
||||
/** Command to run on time */
|
||||
luaA_ref timer;
|
||||
#ifdef WITH_DBUS
|
||||
/** Command to run on dbus events */
|
||||
luaA_ref dbus;
|
||||
#endif
|
||||
} hooks;
|
||||
/** The event loop */
|
||||
struct ev_loop *loop;
|
||||
|
|
Loading…
Reference in New Issue