From ab4c151ed8f6ba151a3631a0b95966f249a58e08 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 25 Aug 2010 23:00:36 +0200 Subject: [PATCH] Add signals before using them This commit makes it an error if an unknown signal is connected, disconnected or emitted. All signals have to be added before they can be used. Signed-off-by: Uli Schlachter --- common/luaclass.c | 11 +++++++++ common/luaclass.h | 8 +++++++ common/luaobject.c | 8 +++++-- common/luaobject.h | 7 ++++++ common/signal.h | 30 ++++++++++++++++++------ dbus.c | 3 +++ lib/awful/client.lua.in | 3 +++ lib/awful/layout/init.lua.in | 2 ++ lib/awful/screen.lua.in | 4 ++++ lib/awful/tag.lua.in | 8 +++++++ luaa.c | 4 ++++ objects/button.c | 5 ++++ objects/client.c | 45 ++++++++++++++++++++++++++++++++++++ objects/key.c | 5 ++++ objects/tag.c | 6 +++++ objects/timer.c | 3 +++ objects/wibox.c | 14 +++++++++++ objects/widget.c | 6 +++++ objects/window.c | 6 +++++ screen.c | 32 ++++++++++++++++++++++--- spawn.c | 10 ++++++++ 21 files changed, 208 insertions(+), 12 deletions(-) diff --git a/common/luaclass.c b/common/luaclass.c index 3eba715a..f747ab41 100644 --- a/common/luaclass.c +++ b/common/luaclass.c @@ -244,6 +244,17 @@ luaA_class_setup(lua_State *L, lua_class_t *class, class->checker = checker; class->parent = parent; + signal_add(&class->signals, "new"); + + /** @todo This is ugly :/ */ + /* Copy all signals from the parent */ + if (parent) + foreach(sig, parent->signals) + { + signal_t s = { .id = sig->id }; + signal_array_insert(&class->signals, s); + } + lua_class_array_append(&luaA_classes, class); } diff --git a/common/luaclass.h b/common/luaclass.h index 96a89f0a..13ae0af6 100644 --- a/common/luaclass.h +++ b/common/luaclass.h @@ -106,6 +106,13 @@ luaA_checkudataornil(lua_State *L, int udx, lua_class_t *class) #define LUA_CLASS_FUNCS(prefix, lua_class) \ static inline int \ + luaA_##prefix##_class_add_signal(lua_State *L) \ + { \ + signal_add(&(lua_class).signals, luaL_checkstring(L, 1)); \ + return 0; \ + } \ + \ + static inline int \ luaA_##prefix##_class_connect_signal(lua_State *L) \ { \ luaA_class_connect_signal_from_stack(L, &(lua_class), \ @@ -130,6 +137,7 @@ luaA_checkudataornil(lua_State *L, int udx, lua_class_t *class) } #define LUA_CLASS_METHODS(class) \ + { "add_signal", luaA_##class##_class_add_signal }, \ { "connect_signal", luaA_##class##_class_connect_signal }, \ { "disconnect_signal", luaA_##class##_class_disconnect_signal }, \ { "emit_signal", luaA_##class##_class_emit_signal }, diff --git a/common/luaobject.c b/common/luaobject.c index 8a8c240b..30b37d3f 100644 --- a/common/luaobject.c +++ b/common/luaobject.c @@ -223,7 +223,9 @@ signal_object_emit(lua_State *L, signal_array_t *arr, const char *name, int narg lua_remove(L, - nargs - nbfunc - 1 + i); luaA_dofunction(L, nargs, 0); } - } + } else + warn("Trying to emit unknown signal '%s'", name); + /* remove args */ lua_pop(L, nargs); } @@ -266,7 +268,9 @@ luaA_object_emit_signal(lua_State *L, int oud, lua_remove(L, - nargs - nbfunc - 2 + i); luaA_dofunction(L, nargs + 1, 0); } - } + } else + luaL_error(L, "Trying to emit unknown signal '%s'", name); + /* Then emit signal on the class */ lua_pushvalue(L, oud); lua_insert(L, - nargs - 1); diff --git a/common/luaobject.h b/common/luaobject.h index 62b1374d..26ed2c92 100644 --- a/common/luaobject.h +++ b/common/luaobject.h @@ -173,6 +173,13 @@ int luaA_object_emit_signal_simple(lua_State *); lua_setmetatable(L, -2); \ lua_setfenv(L, -2); \ lua_pushvalue(L, -1); \ + /** @todo This is wrong we shouldn't copy the existing signals from */ \ + /* the class, but I'm too lazy for doing this correctly right now. */ \ + foreach(sig, (lua_class).signals) \ + { \ + signal_t s = { .id = sig->id }; \ + signal_array_insert(&p->signals, s); \ + } \ luaA_class_emit_signal(L, &(lua_class), "new", 1); \ return p; \ } diff --git a/common/signal.h b/common/signal.h index 1a17ef61..dbff6b69 100644 --- a/common/signal.h +++ b/common/signal.h @@ -55,7 +55,24 @@ signal_array_getbyid(signal_array_t *arr, unsigned long id) return signal_array_lookup(arr, &sig); } -/** Add a signal inside a signal array. +/** Add a signal to a signal array. + * Signals have to be added before they can be added or emitted. + * \param arr The signal array. + * \param name The signal name. + */ +static inline void +signal_add(signal_array_t *arr, const char *name) +{ + unsigned long tok = a_strhash((const unsigned char *) name); + signal_t *sigfound = signal_array_getbyid(arr, tok); + if(!sigfound) + { + signal_t sig = { .id = tok }; + signal_array_insert(arr, sig); + } +} + +/** Connect a signal inside a signal array. * You are in charge of reference counting. * \param arr The signal array. * \param name The signal name. @@ -69,14 +86,10 @@ signal_connect(signal_array_t *arr, const char *name, const void *ref) if(sigfound) cptr_array_append(&sigfound->sigfuncs, ref); else - { - signal_t sig = { .id = tok }; - cptr_array_append(&sig.sigfuncs, ref); - signal_array_insert(arr, sig); - } + warn("Trying to connect to unknown signal '%s'", name); } -/** Remove a signal inside a signal array. +/** Disconnect a signal inside a signal array. * You are in charge of reference counting. * \param arr The signal array. * \param name The signal name. @@ -88,12 +101,15 @@ signal_disconnect(signal_array_t *arr, const char *name, const void *ref) signal_t *sigfound = signal_array_getbyid(arr, a_strhash((const unsigned char *) name)); if(sigfound) + { foreach(func, sigfound->sigfuncs) if(ref == *func) { cptr_array_remove(&sigfound->sigfuncs, func); break; } + } else + warn("Trying to disconnect from unknown signal '%s'", name); } #endif diff --git a/dbus.c b/dbus.c index 7e550073..fd36e8dd 100644 --- a/dbus.c +++ b/dbus.c @@ -763,7 +763,10 @@ luaA_dbus_connect_signal(lua_State *L) if(sig) luaA_warn(L, "cannot add signal %s on D-Bus, already existing", name); else + { + signal_add(&dbus_signals, name); signal_connect(&dbus_signals, name, luaA_object_ref(L, 2)); + } return 0; } diff --git a/lib/awful/client.lua.in b/lib/awful/client.lua.in index 98968501..d12453e1 100644 --- a/lib/awful/client.lua.in +++ b/lib/awful/client.lua.in @@ -834,6 +834,9 @@ function property.set(c, prop, value) end -- Register standards signals +capi.client.add_signal("property::floating_geometry") +capi.client.add_signal("property::floating") + capi.client.connect_signal("focus", focus.history.add) capi.client.connect_signal("unmanage", focus.history.delete) diff --git a/lib/awful/layout/init.lua.in b/lib/awful/layout/init.lua.in index 3e4a891c..4e0e7fdb 100644 --- a/lib/awful/layout/init.lua.in +++ b/lib/awful/layout/init.lua.in @@ -124,6 +124,8 @@ local function arrange_on_tagged(c, tag) end for s = 1, capi.screen.count() do + capi.screen[s]:add_signal("arrange") + tag.attached_connect_signal(s, "property::mwfact", arrange_prop) tag.attached_connect_signal(s, "property::nmaster", arrange_prop) tag.attached_connect_signal(s, "property::ncol", arrange_prop) diff --git a/lib/awful/screen.lua.in b/lib/awful/screen.lua.in index 0ca10fd3..c7fdc777 100644 --- a/lib/awful/screen.lua.in +++ b/lib/awful/screen.lua.in @@ -50,4 +50,8 @@ function padding(screen, padding) return data.padding[screen] end +for s = 1, capi.screen.count() do + capi.screen[s]:add_signal("padding") +end + -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/lib/awful/tag.lua.in b/lib/awful/tag.lua.in index 91ab0f4f..10f6d87c 100644 --- a/lib/awful/tag.lua.in +++ b/lib/awful/tag.lua.in @@ -507,7 +507,15 @@ end) capi.client.connect_signal("manage", withcurrent) +capi.tag.add_signal("property::hide") +capi.tag.add_signal("property::layout") +capi.tag.add_signal("property::mwfact") +capi.tag.add_signal("property::ncol") +capi.tag.add_signal("property::nmaster") +capi.tag.add_signal("property::windowfact") + for s = 1, capi.screen.count() do + capi.screen[s]:add_signal("tag::history::update") capi.screen[s]:connect_signal("tag::history::update", history.update) end diff --git a/luaa.c b/luaa.c index 770888d9..33823d34 100644 --- a/luaa.c +++ b/luaa.c @@ -816,6 +816,10 @@ luaA_init(xdgHandle* xdg) lua_concat(L, 3); /* concatenate with package.path */ lua_setfield(L, 1, "path"); /* package.path = "concatenated string" */ lua_pop(L, 1); /* pop "package" */ + + signal_add(&global_signals, "exit"); + signal_add(&global_signals, "debug::index::miss"); + signal_add(&global_signals, "debug::newindex::miss"); } static bool diff --git a/objects/button.c b/objects/button.c index db638390..a7ec83bd 100644 --- a/objects/button.c +++ b/objects/button.c @@ -125,6 +125,11 @@ button_class_setup(lua_State *L) (lua_class_propfunc_t) luaA_button_set_modifiers, (lua_class_propfunc_t) luaA_button_get_modifiers, (lua_class_propfunc_t) luaA_button_set_modifiers); + + signal_add(&button_class.signals, "property::modifiers"); + signal_add(&button_class.signals, "property::button"); + signal_add(&button_class.signals, "press"); + signal_add(&button_class.signals, "release"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/client.c b/objects/client.c index 60463de0..03b07237 100644 --- a/objects/client.c +++ b/objects/client.c @@ -1875,6 +1875,51 @@ client_class_setup(lua_State *L) NULL, (lua_class_propfunc_t) luaA_client_get_focusable, NULL); + + signal_add(&client_class.signals, "focus"); + signal_add(&client_class.signals, "unfocus"); + signal_add(&client_class.signals, "manage"); + signal_add(&client_class.signals, "unmanage"); + signal_add(&client_class.signals, "list"); + signal_add(&client_class.signals, "tagged"); + signal_add(&client_class.signals, "untagged"); + signal_add(&client_class.signals, "property::screen"); + signal_add(&client_class.signals, "property::struts"); + signal_add(&client_class.signals, "property::window"); + signal_add(&client_class.signals, "property::x"); + signal_add(&client_class.signals, "property::y"); + signal_add(&client_class.signals, "property::width"); + signal_add(&client_class.signals, "property::height"); + signal_add(&client_class.signals, "property::geometry"); + signal_add(&client_class.signals, "property::size_hints_honor"); + signal_add(&client_class.signals, "property::group_window"); + signal_add(&client_class.signals, "property::machine"); + signal_add(&client_class.signals, "property::role"); + signal_add(&client_class.signals, "property::alt_name"); + signal_add(&client_class.signals, "property::name"); + signal_add(&client_class.signals, "property::alt_icon_name"); + signal_add(&client_class.signals, "property::icon_name"); + signal_add(&client_class.signals, "property::pid"); + signal_add(&client_class.signals, "property::class"); + signal_add(&client_class.signals, "property::instance"); + signal_add(&client_class.signals, "property::keys"); + signal_add(&client_class.signals, "property::fullscreen"); + signal_add(&client_class.signals, "property::maximized_horizontal"); + signal_add(&client_class.signals, "property::maximized_vertical"); + signal_add(&client_class.signals, "property::modal"); + signal_add(&client_class.signals, "property::sticky"); + signal_add(&client_class.signals, "property::above"); + signal_add(&client_class.signals, "property::below"); + signal_add(&client_class.signals, "property::minimized"); + signal_add(&client_class.signals, "property::urgent"); + signal_add(&client_class.signals, "property::hidden"); + signal_add(&client_class.signals, "property::icon"); + signal_add(&client_class.signals, "property::skip_taskbar"); + signal_add(&client_class.signals, "request::fullscreen"); + signal_add(&client_class.signals, "request::maximized_horizontal"); + signal_add(&client_class.signals, "request::maximized_vertical"); + signal_add(&client_class.signals, "mouse::enter"); + signal_add(&client_class.signals, "mouse::leave"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/key.c b/objects/key.c index a8e111d2..aacedacf 100644 --- a/objects/key.c +++ b/objects/key.c @@ -234,6 +234,11 @@ key_class_setup(lua_State *L) (lua_class_propfunc_t) luaA_key_set_modifiers, (lua_class_propfunc_t) luaA_key_get_modifiers, (lua_class_propfunc_t) luaA_key_set_modifiers); + + signal_add(&key_class.signals, "property::modifiers"); + signal_add(&key_class.signals, "property::key"); + signal_add(&key_class.signals, "press"); + signal_add(&key_class.signals, "release"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/tag.c b/objects/tag.c index cf7e1aeb..3a478fe4 100644 --- a/objects/tag.c +++ b/objects/tag.c @@ -421,6 +421,12 @@ tag_class_setup(lua_State *L) (lua_class_propfunc_t) luaA_tag_set_selected, (lua_class_propfunc_t) luaA_tag_get_selected, (lua_class_propfunc_t) luaA_tag_set_selected); + + signal_add(&tag_class.signals, "property::name"); + signal_add(&tag_class.signals, "property::screen"); + signal_add(&tag_class.signals, "property::selected"); + signal_add(&tag_class.signals, "tagged"); + signal_add(&tag_class.signals, "untagged"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/timer.c b/objects/timer.c index 947b2025..a6218790 100644 --- a/objects/timer.c +++ b/objects/timer.c @@ -133,6 +133,9 @@ timer_class_setup(lua_State *L) NULL, (lua_class_propfunc_t) luaA_timer_get_started, NULL); + + signal_add(&timer_class.signals, "property::timeout"); + signal_add(&timer_class.signals, "timeout"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/wibox.c b/objects/wibox.c index d6a92c0b..a1f7da2f 100644 --- a/objects/wibox.c +++ b/objects/wibox.c @@ -1282,6 +1282,20 @@ wibox_class_setup(lua_State *L) (lua_class_propfunc_t) luaA_wibox_set_shape_clip, (lua_class_propfunc_t) luaA_wibox_get_shape_clip, (lua_class_propfunc_t) luaA_wibox_set_shape_clip); + + signal_add(&wibox_class.signals, "property::border_width"); + signal_add(&wibox_class.signals, "property::fg"); + signal_add(&wibox_class.signals, "property::bg"); + signal_add(&wibox_class.signals, "property::widgets"); + signal_add(&wibox_class.signals, "property::x"); + signal_add(&wibox_class.signals, "property::y"); + signal_add(&wibox_class.signals, "property::width"); + signal_add(&wibox_class.signals, "property::height"); + signal_add(&wibox_class.signals, "property::ontop"); + signal_add(&wibox_class.signals, "property::visible"); + signal_add(&wibox_class.signals, "property::screen"); + signal_add(&wibox_class.signals, "mouse::enter"); + signal_add(&wibox_class.signals, "mouse::leave"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/widget.c b/objects/widget.c index 39f5dd93..32b4b643 100644 --- a/objects/widget.c +++ b/objects/widget.c @@ -584,6 +584,12 @@ widget_class_setup(lua_State *L) (lua_class_propfunc_t) luaA_widget_set_type, (lua_class_propfunc_t) luaA_widget_get_type, NULL); + + signal_add(&widget_class.signals, "property::type"); + signal_add(&widget_class.signals, "property::buttons"); + signal_add(&widget_class.signals, "property::visible"); + signal_add(&widget_class.signals, "mouse::enter"); + signal_add(&widget_class.signals, "mouse::leave"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/window.c b/objects/window.c index e24c1856..38e5a2f2 100644 --- a/objects/window.c +++ b/objects/window.c @@ -226,6 +226,12 @@ window_class_setup(lua_State *L) (lua_class_propfunc_t) luaA_window_set_border_width, (lua_class_propfunc_t) luaA_window_get_border_width, (lua_class_propfunc_t) luaA_window_set_border_width); + + signal_add(&window_class.signals, "property::border_color"); + signal_add(&window_class.signals, "property::border_width"); + signal_add(&window_class.signals, "property::buttons"); + signal_add(&window_class.signals, "property::struts"); + signal_add(&window_class.signals, "property::opacity"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/screen.c b/screen.c index 38e0cf0e..1dba889f 100644 --- a/screen.c +++ b/screen.c @@ -72,6 +72,15 @@ screen_default_visual(xcb_screen_t *s) return NULL; } +static void +screen_add(screen_t new_screen) +{ + signal_add(&new_screen.signals, "tag::attach"); + signal_add(&new_screen.signals, "tag::detach"); + signal_add(&new_screen.signals, "property::workarea"); + screen_array_append(&globalconf.screens, new_screen); +} + static bool screen_scan_randr(void) { @@ -138,7 +147,7 @@ screen_scan_randr(void) p_delete(&output_info_r); } - screen_array_append(&globalconf.screens, new_screen); + screen_add(new_screen); p_delete(&crtc_info_r); } @@ -201,7 +210,7 @@ screen_scan_xinerama(void) screen_t s; p_clear(&s, 1); s.geometry = screen_xsitoarea(xsi[screen]); - screen_array_append(&globalconf.screens, s); + screen_add(s); } } @@ -223,7 +232,7 @@ static void screen_scan_x11(void) s.geometry.y = 0; s.geometry.width = xcb_screen->width_in_pixels; s.geometry.height = xcb_screen->height_in_pixels; - screen_array_append(&globalconf.screens, s); + screen_add(s); } /** Get screens informations and fill global configuration. @@ -530,6 +539,22 @@ luaA_screen_index(lua_State *L) } /** Add a signal to a screen. + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lvalue A screen. + * \lparam A signal name. + */ +static int +luaA_screen_add_signal(lua_State *L) +{ + screen_t *s = lua_touserdata(L, 1); + const char *name = luaL_checkstring(L, 2); + signal_add(&s->signals, name); + return 0; +} + +/** Connect a screen's signal. * \param L The Lua VM state. * \return The number of elements pushed on stack. * \luastack @@ -619,6 +644,7 @@ const struct luaL_reg awesome_screen_methods[] = const struct luaL_reg awesome_screen_meta[] = { + { "add_signal", luaA_screen_add_signal }, { "connect_signal", luaA_screen_connect_signal }, { "disconnect_signal", luaA_screen_disconnect_signal }, { "emit_signal", luaA_screen_emit_signal }, diff --git a/spawn.c b/spawn.c index cb90fce5..a058c8f0 100644 --- a/spawn.c +++ b/spawn.c @@ -85,6 +85,8 @@ spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents) } lua_pop(globalconf.L, 1); } + else + warn("spawn::timeout signal is missing"); } sn_startup_sequence_unref(w->data); p_delete(&w); @@ -191,6 +193,8 @@ spawn_monitor_event(SnMonitorEvent *event, void *data) } lua_pop(globalconf.L, 1); } + else + warn("%s signal is missing", event_type_str); } /** Tell the spawn module that an app has been started. @@ -240,6 +244,12 @@ spawn_init(void) globalconf.default_screen, spawn_monitor_event, NULL, NULL); + + signal_add(&global_signals, "spawn::timeout"); + signal_add(&global_signals, "spawn::completed"); + signal_add(&global_signals, "spawn::change"); + signal_add(&global_signals, "spawn::initiated"); + signal_add(&global_signals, "spawn::canceled"); } static void