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.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "dbus.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
#ifdef WITH_DBUS
|
#ifdef WITH_DBUS
|
||||||
|
|
||||||
|
@ -27,9 +30,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "dbus.h"
|
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
extern awesome_t globalconf;
|
extern awesome_t globalconf;
|
||||||
|
|
||||||
|
@ -37,56 +38,193 @@ static DBusError err;
|
||||||
static DBusConnection *dbus_connection = NULL;
|
static DBusConnection *dbus_connection = NULL;
|
||||||
ev_io dbusio = { .fd = -1 };
|
ev_io dbusio = { .fd = -1 };
|
||||||
|
|
||||||
/** Check a dbus object path format and its number of element.
|
static int
|
||||||
* \param path The path.
|
a_dbus_message_iter(DBusMessageIter *iter)
|
||||||
* \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)
|
|
||||||
{
|
{
|
||||||
int i;
|
int nargs = 0;
|
||||||
|
|
||||||
for(i = 0; path[i]; i++);
|
do
|
||||||
if(i != nelem)
|
{
|
||||||
return false;
|
switch(dbus_message_iter_get_arg_type(iter))
|
||||||
return (!a_strcmp(path[0], "org") && !a_strcmp(path[1], "awesome"));
|
{
|
||||||
|
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
|
static void
|
||||||
a_dbus_process_request_do(DBusMessage *msg)
|
a_dbus_process_request(DBusMessage *msg)
|
||||||
{
|
{
|
||||||
int i;
|
if(globalconf.hooks.dbus == LUA_REFNIL)
|
||||||
DBusMessageIter iter;
|
|
||||||
char **path, *cmd;
|
|
||||||
|
|
||||||
if(!dbus_message_get_path_decomposed(msg, &path))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* path is:
|
lua_newtable(globalconf.L);
|
||||||
* /org/awesome */
|
|
||||||
if(!a_dbus_path_check(path, 2))
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
if(!dbus_message_iter_init(msg, &iter))
|
switch(dbus_message_get_type(msg))
|
||||||
{
|
{
|
||||||
dbus_error_free(&err);
|
case DBUS_MESSAGE_TYPE_SIGNAL:
|
||||||
goto bailout;
|
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:
|
const char *s = dbus_message_get_interface(msg);
|
||||||
for(i = 0; path[i]; i++)
|
lua_pushstring(globalconf.L, NONULL(s));
|
||||||
p_delete(&path[i]);
|
lua_setfield(globalconf.L, -2, "interface");
|
||||||
p_delete(&path);
|
|
||||||
|
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
|
static void
|
||||||
|
@ -111,8 +249,8 @@ a_dbus_process_requests(EV_P_ ev_io *w, int revents)
|
||||||
dbus_message_unref(msg);
|
dbus_message_unref(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(dbus_message_is_method_call(msg, "org.awesome", "do"))
|
else
|
||||||
a_dbus_process_request_do(msg);
|
a_dbus_process_request(msg);
|
||||||
|
|
||||||
dbus_message_unref(msg);
|
dbus_message_unref(msg);
|
||||||
|
|
||||||
|
@ -196,8 +334,6 @@ a_dbus_cleanup(void)
|
||||||
|
|
||||||
#else /* HAVE_DBUS */
|
#else /* HAVE_DBUS */
|
||||||
|
|
||||||
#include "dbus.h"
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
a_dbus_init(void)
|
a_dbus_init(void)
|
||||||
{
|
{
|
||||||
|
|
21
hooks.c
21
hooks.c
|
@ -174,6 +174,24 @@ luaA_hooks_timer(lua_State *L)
|
||||||
return 0;
|
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[] =
|
const struct luaL_reg awesome_hooks_lib[] =
|
||||||
{
|
{
|
||||||
{ "focus", luaA_hooks_focus },
|
{ "focus", luaA_hooks_focus },
|
||||||
|
@ -187,5 +205,8 @@ const struct luaL_reg awesome_hooks_lib[] =
|
||||||
{ "tags", luaA_hooks_tags },
|
{ "tags", luaA_hooks_tags },
|
||||||
{ "tagged", luaA_hooks_tagged },
|
{ "tagged", luaA_hooks_tagged },
|
||||||
{ "timer", luaA_hooks_timer },
|
{ "timer", luaA_hooks_timer },
|
||||||
|
#ifdef WITH_DBUS
|
||||||
|
{ "dbus", luaA_hooks_dbus },
|
||||||
|
#endif
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
-- Grab environment we need
|
-- Grab environment we need
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local table = table
|
local table = table
|
||||||
|
local unpack = unpack
|
||||||
local ipairs = ipairs
|
local ipairs = ipairs
|
||||||
local type = type
|
local type = type
|
||||||
local math = math
|
local math = math
|
||||||
|
@ -50,32 +51,8 @@ end
|
||||||
-- Autodeclare awful.hooks.* functions
|
-- Autodeclare awful.hooks.* functions
|
||||||
-- mapped to awesome hooks.* functions
|
-- mapped to awesome hooks.* functions
|
||||||
for name, hook in pairs(capi.hooks) do
|
for name, hook in pairs(capi.hooks) do
|
||||||
if name ~= 'timer' then
|
_M[name] = {}
|
||||||
_M[name] = {}
|
if name == 'timer' then
|
||||||
_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] = {}
|
|
||||||
_M[name].register = function (time, f, runnow)
|
_M[name].register = function (time, f, runnow)
|
||||||
if type(time) ~= 'number' or type(f) ~= 'function' or time <= 0 then
|
if type(time) ~= 'number' or type(f) ~= 'function' or time <= 0 then
|
||||||
return
|
return
|
||||||
|
@ -119,6 +96,44 @@ for name, hook in pairs(capi.hooks) do
|
||||||
end
|
end
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
3
luaa.c
3
luaa.c
|
@ -823,6 +823,9 @@ luaA_init(void)
|
||||||
globalconf.hooks.tagged = LUA_REFNIL;
|
globalconf.hooks.tagged = LUA_REFNIL;
|
||||||
globalconf.hooks.property = LUA_REFNIL;
|
globalconf.hooks.property = LUA_REFNIL;
|
||||||
globalconf.hooks.timer = 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) */
|
/* add Lua lib path (/usr/share/awesome/lib by default) */
|
||||||
luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?.lua\"");
|
luaA_dostring(L, "package.path = package.path .. \";" AWESOME_LUA_LIB_PATH "/?.lua\"");
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xcb_property.h>
|
#include <xcb/xcb_property.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "swindow.h"
|
#include "swindow.h"
|
||||||
|
@ -351,6 +352,10 @@ struct awesome_t
|
||||||
luaA_ref property;
|
luaA_ref property;
|
||||||
/** Command to run on time */
|
/** Command to run on time */
|
||||||
luaA_ref timer;
|
luaA_ref timer;
|
||||||
|
#ifdef WITH_DBUS
|
||||||
|
/** Command to run on dbus events */
|
||||||
|
luaA_ref dbus;
|
||||||
|
#endif
|
||||||
} hooks;
|
} hooks;
|
||||||
/** The event loop */
|
/** The event loop */
|
||||||
struct ev_loop *loop;
|
struct ev_loop *loop;
|
||||||
|
|
Loading…
Reference in New Issue