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