diff --git a/mouse.c b/mouse.c index 5c80b17bc..df149a02d 100644 --- a/mouse.c +++ b/mouse.c @@ -33,11 +33,15 @@ #include "math.h" #include "common/util.h" #include "common/xutil.h" +#include "common/luaclass.h" #include "globalconf.h" #include "objects/client.h" #include "objects/drawin.h" #include "objects/screen.h" +static int miss_index_handler = LUA_REFNIL; +static int miss_newindex_handler = LUA_REFNIL; + /** Mouse library. * * @table mouse @@ -119,6 +123,39 @@ mouse_warp_pointer(xcb_window_t window, int16_t x, int16_t y) 0, 0, 0, 0, x, y); } +/** + * Allow the a Lua handler to be implemented for custom properties and + * functions. + * \param L A lua state + * \param handler A function on the LUA_REGISTRYINDEX + */ +static int +luaA_mouse_call_handler(lua_State *L, int handler) +{ + int nargs = lua_gettop(L); + + /* Push error handling function and move it before args */ + lua_pushcfunction(L, luaA_dofunction_error); + lua_insert(L, - nargs - 1); + int error_func_pos = 1; + + /* push function and move it before args */ + lua_rawgeti(L, LUA_REGISTRYINDEX, handler); + lua_insert(L, - nargs - 1); + + if(lua_pcall(L, nargs, LUA_MULTRET, error_func_pos)) + { + warn("%s", lua_tostring(L, -1)); + /* Remove error function and error string */ + lua_pop(L, 2); + return 0; + } + /* Remove error function */ + lua_remove(L, error_func_pos); + + return lua_gettop(L); +} + /** Mouse library. * \param L The Lua VM state. * \return The number of elements pushed on stack. @@ -133,8 +170,13 @@ luaA_mouse_index(lua_State *L) int16_t mouse_x, mouse_y; /* attr is not "screen"?! */ - if (A_STRNEQ(attr, "screen")) - return luaA_default_index(L); + if (A_STRNEQ(attr, "screen")) { + if (miss_index_handler != LUA_REFNIL) { + return luaA_mouse_call_handler(L, miss_index_handler); + } + else + return luaA_default_index(L); + } if (!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL, NULL)) { @@ -162,8 +204,14 @@ luaA_mouse_newindex(lua_State *L) const char *attr = luaL_checkstring(L, 2); screen_t *screen; - if (A_STRNEQ(attr, "screen")) - return luaA_default_newindex(L); + if (A_STRNEQ(attr, "screen")) { + /* Call the lua mouse property handler */ + if (miss_newindex_handler != LUA_REFNIL) { + return luaA_mouse_call_handler(L, miss_newindex_handler); + } + else + return luaA_default_newindex(L); + } screen = luaA_checkscreen(L, 3); mouse_warp_pointer(globalconf.screen->root, screen->geometry.x, screen->geometry.y); @@ -271,12 +319,32 @@ luaA_mouse_object_under_pointer(lua_State *L) return 0; } +/** + * Add a custom property handler (getter). + */ +static int +luaA_mouse_set_index_miss_handler(lua_State *L) +{ + return luaA_registerfct(L, 1, &miss_index_handler); +} + +/** + * Add a custom property handler (setter). + */ +static int +luaA_mouse_set_newindex_miss_handler(lua_State *L) +{ + return luaA_registerfct(L, 1, &miss_newindex_handler); +} + const struct luaL_Reg awesome_mouse_methods[] = { { "__index", luaA_mouse_index }, { "__newindex", luaA_mouse_newindex }, { "coords", luaA_mouse_coords }, { "object_under_pointer", luaA_mouse_object_under_pointer }, + { "set_index_miss_handler", luaA_mouse_set_index_miss_handler}, + { "set_newindex_miss_handler", luaA_mouse_set_newindex_miss_handler}, { NULL, NULL } }; const struct luaL_Reg awesome_mouse_meta[] =