diff --git a/hooks.c b/hooks.c index f6aec9b16..54055c6dc 100644 --- a/hooks.c +++ b/hooks.c @@ -163,20 +163,6 @@ luaA_hooks_property(lua_State *L) HANDLE_HOOK(L, globalconf.hooks.property); } -/** Set the function called on each startup-notification events - * This function is called with a table and various fields set to describe the - * vents. - * \param L The Lua VM state. - * \return The number of elements pushed on stack. - * \luastack - * \lparam A function to call on each startup-notification event. - */ -static int -luaA_hooks_startup_notification(lua_State *L) -{ - HANDLE_HOOK(L, globalconf.hooks.startup_notification); -} - /** Set the function to be called every N seconds. * \param L The Lua VM state. * \return The number of elements pushed on stack. @@ -226,7 +212,6 @@ const struct luaL_reg awesome_hooks_lib[] = { "clients", luaA_hooks_clients }, { "tags", luaA_hooks_tags }, { "tagged", luaA_hooks_tagged }, - { "startup_notification", luaA_hooks_startup_notification }, { "timer", luaA_hooks_timer }, { "exit", luaA_hooks_exit }, { NULL, NULL } diff --git a/lib/awful/startup_notification.lua.in b/lib/awful/startup_notification.lua.in index 1f061e9ff..f6caac5d6 100644 --- a/lib/awful/startup_notification.lua.in +++ b/lib/awful/startup_notification.lua.in @@ -5,11 +5,11 @@ --------------------------------------------------------------------------- -- Grab environment we need -local hooks = require("awful.hooks") local ipairs = ipairs local table = table local capi = { + awesome = awesome, root = root } @@ -43,16 +43,12 @@ local function register_event(event_id) update_cursor() end -local function startup_hook(event) - if event.type == "initiated" then - register_event(event.id) - elseif event.type == "canceled" - or event.type == "completed" - or event.type == "timedout" then - unregister_event(event.id) - end -end +local function unregister_hook(event) unregister_event(event.id) end +local function register_hook(event) register_event(event.id) end -hooks.startup_notification.register(startup_hook) +capi.awesome.add_signal("spawn::initiated", register_hook) +capi.awesome.add_signal("spawn::canceled", unregister_hook) +capi.awesome.add_signal("spawn::completed", unregister_hook) +capi.awesome.add_signal("spawn::timeout", unregister_hook) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/luaa.c b/luaa.c index cef0fff6c..bd877c9c0 100644 --- a/luaa.c +++ b/luaa.c @@ -619,6 +619,67 @@ luaA_awesome_newindex(lua_State *L) return 0; } +/** Add a global signal. + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam A string with the event name. + * \lparam The function to call. + */ +static int +luaA_awesome_add_signal(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + luaA_checkfunction(L, 2); + signal_add(&global_signals, name, luaA_object_ref(L, 2)); + return 0; +} + +/** Remove a global signal. + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam A string with the event name. + * \lparam The function to call. + */ +static int +luaA_awesome_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(&global_signals, name, func); + luaA_object_unref(L, (void *) func); + return 0; +} + +/** Emit a global signal. + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam A string with the event name. + * \lparam The function to call. + */ +static int +luaA_awesome_emit_signal(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + signal_t *sigfound = signal_array_getbyid(&global_signals, + a_strhash((const unsigned char *) name)); + if(sigfound) + { + int nargs = lua_gettop(L) - 1; + foreach(ref, sigfound->sigfuncs) + { + for(int i = 0; i < nargs; i++) + lua_pushvalue(L, - nargs); + luaA_object_push(L, (void *) *ref); + luaA_dofunction(L, nargs, 0); + } + } + return 0; +} + /** Initialize the Lua VM * \param xdg An xdg handle to use to get XDG basedir. */ @@ -632,6 +693,9 @@ luaA_init(xdgHandle* xdg) { "exec", luaA_exec }, { "spawn", luaA_spawn }, { "restart", luaA_restart }, + { "add_signal", luaA_awesome_add_signal }, + { "remove_signal", luaA_awesome_remove_signal }, + { "emit_signal", luaA_awesome_emit_signal }, { "__index", luaA_awesome_index }, { "__newindex", luaA_awesome_newindex }, { NULL, NULL } @@ -715,7 +779,6 @@ luaA_init(xdgHandle* xdg) globalconf.hooks.tags = LUA_REFNIL; globalconf.hooks.tagged = LUA_REFNIL; globalconf.hooks.property = LUA_REFNIL; - globalconf.hooks.startup_notification = LUA_REFNIL; globalconf.hooks.timer = LUA_REFNIL; globalconf.hooks.exit = LUA_REFNIL; diff --git a/luaa.h b/luaa.h index 8adf7e4d5..e7d13fb7d 100644 --- a/luaa.h +++ b/luaa.h @@ -239,5 +239,8 @@ bool luaA_isloop(lua_State *, int); } \ } while(0); +/** Global signals */ +signal_array_t global_signals; + #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/spawn.c b/spawn.c index 2998dec6f..72d4e83bb 100644 --- a/spawn.c +++ b/spawn.c @@ -67,16 +67,24 @@ spawn_sequence_remove(SnStartupSequence *s) static void spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents) { - if(spawn_sequence_remove(w->data) - && globalconf.hooks.startup_notification != LUA_REFNIL) + if(spawn_sequence_remove(w->data)) { - /* send a timeout event to hook function */ - lua_createtable(globalconf.L, 0, 2); - lua_pushstring(globalconf.L, sn_startup_sequence_get_id(w->data)); - lua_setfield(globalconf.L, -2, "id"); - lua_pushliteral(globalconf.L, "timedout"); - lua_setfield(globalconf.L, -2, "type"); - luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.startup_notification, 1, 0); + signal_t *sig = signal_array_getbyid(&global_signals, + a_strhash((const unsigned char *) "spawn::timeout")); + if(sig) + { + /* send a timeout signal */ + lua_createtable(globalconf.L, 0, 2); + lua_pushstring(globalconf.L, sn_startup_sequence_get_id(w->data)); + lua_setfield(globalconf.L, -2, "id"); + foreach(func, sig->sigfuncs) + { + lua_pushvalue(globalconf.L, -1); + luaA_object_push(globalconf.L, (void *) *func); + luaA_dofunction(globalconf.L, 1, 0); + } + lua_pop(globalconf.L, 1); + } } sn_startup_sequence_unref(w->data); p_delete(&w); @@ -85,9 +93,6 @@ spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents) static void spawn_monitor_event(SnMonitorEvent *event, void *data) { - if(globalconf.hooks.startup_notification == LUA_REFNIL) - return; - SnStartupSequence *sequence = sn_monitor_event_get_startup_sequence(event); SnMonitorEventType event_type = sn_monitor_event_get_type(event); @@ -95,14 +100,15 @@ spawn_monitor_event(SnMonitorEvent *event, void *data) lua_pushstring(globalconf.L, sn_startup_sequence_get_id(sequence)); lua_setfield(globalconf.L, -2, "id"); + const char *event_type_str = NULL; + switch(event_type) { case SN_MONITOR_EVENT_INITIATED: /* ref the sequence for the array */ sn_startup_sequence_ref(sequence); SnStartupSequence_array_append(&sn_waits, sequence); - lua_pushliteral(globalconf.L, "initiated"); - lua_setfield(globalconf.L, -2, "type"); + event_type_str = "spawn::initiated"; /* Add a timeout function so we do not wait for this event to complete * for ever */ @@ -114,16 +120,13 @@ spawn_monitor_event(SnMonitorEvent *event, void *data) ev_timer_start(globalconf.loop, ev_timeout); break; case SN_MONITOR_EVENT_CHANGED: - lua_pushliteral(globalconf.L, "change"); - lua_setfield(globalconf.L, -2, "type"); + event_type_str = "spawn::change"; break; case SN_MONITOR_EVENT_COMPLETED: - lua_pushliteral(globalconf.L, "completed"); - lua_setfield(globalconf.L, -2, "type"); + event_type_str = "spawn::completed"; break; case SN_MONITOR_EVENT_CANCELED: - lua_pushliteral(globalconf.L, "canceled"); - lua_setfield(globalconf.L, -2, "type"); + event_type_str = "spawn::canceled"; break; } @@ -174,7 +177,20 @@ spawn_monitor_event(SnMonitorEvent *event, void *data) break; } - luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.startup_notification, 1, 0); + /* send the signal */ + signal_t *sig = signal_array_getbyid(&global_signals, + a_strhash((const unsigned char *) event_type_str)); + + if(sig) + { + foreach(func, sig->sigfuncs) + { + lua_pushvalue(globalconf.L, -1); + luaA_object_push(globalconf.L, (void *) *func); + luaA_dofunction(globalconf.L, 1, 0); + } + lua_pop(globalconf.L, 1); + } } /** Tell the spawn module that an app has been started. diff --git a/structs.h b/structs.h index c808dcff8..b741b0f4a 100644 --- a/structs.h +++ b/structs.h @@ -120,8 +120,6 @@ struct awesome_t int timer; /** Command to run on awesome exit */ int exit; - /** Startup notification hooks */ - int startup_notification; } hooks; /** The event loop */ struct ev_loop *loop;