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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2010-08-25 23:00:36 +02:00
parent 948f960b7e
commit ab4c151ed8
21 changed files with 208 additions and 12 deletions

View File

@ -244,6 +244,17 @@ luaA_class_setup(lua_State *L, lua_class_t *class,
class->checker = checker; class->checker = checker;
class->parent = parent; 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); lua_class_array_append(&luaA_classes, class);
} }

View File

@ -106,6 +106,13 @@ luaA_checkudataornil(lua_State *L, int udx, lua_class_t *class)
#define LUA_CLASS_FUNCS(prefix, lua_class) \ #define LUA_CLASS_FUNCS(prefix, lua_class) \
static inline int \ 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_##prefix##_class_connect_signal(lua_State *L) \
{ \ { \
luaA_class_connect_signal_from_stack(L, &(lua_class), \ 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) \ #define LUA_CLASS_METHODS(class) \
{ "add_signal", luaA_##class##_class_add_signal }, \
{ "connect_signal", luaA_##class##_class_connect_signal }, \ { "connect_signal", luaA_##class##_class_connect_signal }, \
{ "disconnect_signal", luaA_##class##_class_disconnect_signal }, \ { "disconnect_signal", luaA_##class##_class_disconnect_signal }, \
{ "emit_signal", luaA_##class##_class_emit_signal }, { "emit_signal", luaA_##class##_class_emit_signal },

View File

@ -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); lua_remove(L, - nargs - nbfunc - 1 + i);
luaA_dofunction(L, nargs, 0); luaA_dofunction(L, nargs, 0);
} }
} } else
warn("Trying to emit unknown signal '%s'", name);
/* remove args */ /* remove args */
lua_pop(L, nargs); lua_pop(L, nargs);
} }
@ -266,7 +268,9 @@ luaA_object_emit_signal(lua_State *L, int oud,
lua_remove(L, - nargs - nbfunc - 2 + i); lua_remove(L, - nargs - nbfunc - 2 + i);
luaA_dofunction(L, nargs + 1, 0); luaA_dofunction(L, nargs + 1, 0);
} }
} } else
luaL_error(L, "Trying to emit unknown signal '%s'", name);
/* Then emit signal on the class */ /* Then emit signal on the class */
lua_pushvalue(L, oud); lua_pushvalue(L, oud);
lua_insert(L, - nargs - 1); lua_insert(L, - nargs - 1);

View File

@ -173,6 +173,13 @@ int luaA_object_emit_signal_simple(lua_State *);
lua_setmetatable(L, -2); \ lua_setmetatable(L, -2); \
lua_setfenv(L, -2); \ lua_setfenv(L, -2); \
lua_pushvalue(L, -1); \ 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); \ luaA_class_emit_signal(L, &(lua_class), "new", 1); \
return p; \ return p; \
} }

View File

@ -55,7 +55,24 @@ signal_array_getbyid(signal_array_t *arr, unsigned long id)
return signal_array_lookup(arr, &sig); 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. * You are in charge of reference counting.
* \param arr The signal array. * \param arr The signal array.
* \param name The signal name. * \param name The signal name.
@ -69,14 +86,10 @@ signal_connect(signal_array_t *arr, const char *name, const void *ref)
if(sigfound) if(sigfound)
cptr_array_append(&sigfound->sigfuncs, ref); cptr_array_append(&sigfound->sigfuncs, ref);
else else
{ warn("Trying to connect to unknown signal '%s'", name);
signal_t sig = { .id = tok };
cptr_array_append(&sig.sigfuncs, ref);
signal_array_insert(arr, sig);
}
} }
/** Remove a signal inside a signal array. /** Disconnect a signal inside a signal array.
* You are in charge of reference counting. * You are in charge of reference counting.
* \param arr The signal array. * \param arr The signal array.
* \param name The signal name. * \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, signal_t *sigfound = signal_array_getbyid(arr,
a_strhash((const unsigned char *) name)); a_strhash((const unsigned char *) name));
if(sigfound) if(sigfound)
{
foreach(func, sigfound->sigfuncs) foreach(func, sigfound->sigfuncs)
if(ref == *func) if(ref == *func)
{ {
cptr_array_remove(&sigfound->sigfuncs, func); cptr_array_remove(&sigfound->sigfuncs, func);
break; break;
} }
} else
warn("Trying to disconnect from unknown signal '%s'", name);
} }
#endif #endif

3
dbus.c
View File

@ -763,7 +763,10 @@ luaA_dbus_connect_signal(lua_State *L)
if(sig) if(sig)
luaA_warn(L, "cannot add signal %s on D-Bus, already existing", name); luaA_warn(L, "cannot add signal %s on D-Bus, already existing", name);
else else
{
signal_add(&dbus_signals, name);
signal_connect(&dbus_signals, name, luaA_object_ref(L, 2)); signal_connect(&dbus_signals, name, luaA_object_ref(L, 2));
}
return 0; return 0;
} }

View File

@ -834,6 +834,9 @@ function property.set(c, prop, value)
end end
-- Register standards signals -- 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("focus", focus.history.add)
capi.client.connect_signal("unmanage", focus.history.delete) capi.client.connect_signal("unmanage", focus.history.delete)

View File

@ -124,6 +124,8 @@ local function arrange_on_tagged(c, tag)
end end
for s = 1, capi.screen.count() do 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::mwfact", arrange_prop)
tag.attached_connect_signal(s, "property::nmaster", arrange_prop) tag.attached_connect_signal(s, "property::nmaster", arrange_prop)
tag.attached_connect_signal(s, "property::ncol", arrange_prop) tag.attached_connect_signal(s, "property::ncol", arrange_prop)

View File

@ -50,4 +50,8 @@ function padding(screen, padding)
return data.padding[screen] return data.padding[screen]
end 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 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -507,7 +507,15 @@ end)
capi.client.connect_signal("manage", withcurrent) 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 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) capi.screen[s]:connect_signal("tag::history::update", history.update)
end end

4
luaa.c
View File

@ -816,6 +816,10 @@ luaA_init(xdgHandle* xdg)
lua_concat(L, 3); /* concatenate with package.path */ lua_concat(L, 3); /* concatenate with package.path */
lua_setfield(L, 1, "path"); /* package.path = "concatenated string" */ lua_setfield(L, 1, "path"); /* package.path = "concatenated string" */
lua_pop(L, 1); /* pop "package" */ 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 static bool

View File

@ -125,6 +125,11 @@ button_class_setup(lua_State *L)
(lua_class_propfunc_t) luaA_button_set_modifiers, (lua_class_propfunc_t) luaA_button_set_modifiers,
(lua_class_propfunc_t) luaA_button_get_modifiers, (lua_class_propfunc_t) luaA_button_get_modifiers,
(lua_class_propfunc_t) luaA_button_set_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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -1875,6 +1875,51 @@ client_class_setup(lua_State *L)
NULL, NULL,
(lua_class_propfunc_t) luaA_client_get_focusable, (lua_class_propfunc_t) luaA_client_get_focusable,
NULL); 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -234,6 +234,11 @@ key_class_setup(lua_State *L)
(lua_class_propfunc_t) luaA_key_set_modifiers, (lua_class_propfunc_t) luaA_key_set_modifiers,
(lua_class_propfunc_t) luaA_key_get_modifiers, (lua_class_propfunc_t) luaA_key_get_modifiers,
(lua_class_propfunc_t) luaA_key_set_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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -421,6 +421,12 @@ tag_class_setup(lua_State *L)
(lua_class_propfunc_t) luaA_tag_set_selected, (lua_class_propfunc_t) luaA_tag_set_selected,
(lua_class_propfunc_t) luaA_tag_get_selected, (lua_class_propfunc_t) luaA_tag_get_selected,
(lua_class_propfunc_t) luaA_tag_set_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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -133,6 +133,9 @@ timer_class_setup(lua_State *L)
NULL, NULL,
(lua_class_propfunc_t) luaA_timer_get_started, (lua_class_propfunc_t) luaA_timer_get_started,
NULL); 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -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_set_shape_clip,
(lua_class_propfunc_t) luaA_wibox_get_shape_clip, (lua_class_propfunc_t) luaA_wibox_get_shape_clip,
(lua_class_propfunc_t) luaA_wibox_set_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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -584,6 +584,12 @@ widget_class_setup(lua_State *L)
(lua_class_propfunc_t) luaA_widget_set_type, (lua_class_propfunc_t) luaA_widget_set_type,
(lua_class_propfunc_t) luaA_widget_get_type, (lua_class_propfunc_t) luaA_widget_get_type,
NULL); 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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -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_set_border_width,
(lua_class_propfunc_t) luaA_window_get_border_width, (lua_class_propfunc_t) luaA_window_get_border_width,
(lua_class_propfunc_t) luaA_window_set_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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -72,6 +72,15 @@ screen_default_visual(xcb_screen_t *s)
return NULL; 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 static bool
screen_scan_randr(void) screen_scan_randr(void)
{ {
@ -138,7 +147,7 @@ screen_scan_randr(void)
p_delete(&output_info_r); p_delete(&output_info_r);
} }
screen_array_append(&globalconf.screens, new_screen); screen_add(new_screen);
p_delete(&crtc_info_r); p_delete(&crtc_info_r);
} }
@ -201,7 +210,7 @@ screen_scan_xinerama(void)
screen_t s; screen_t s;
p_clear(&s, 1); p_clear(&s, 1);
s.geometry = screen_xsitoarea(xsi[screen]); 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.y = 0;
s.geometry.width = xcb_screen->width_in_pixels; s.geometry.width = xcb_screen->width_in_pixels;
s.geometry.height = xcb_screen->height_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. /** Get screens informations and fill global configuration.
@ -530,6 +539,22 @@ luaA_screen_index(lua_State *L)
} }
/** Add a signal to a screen. /** 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. * \param L The Lua VM state.
* \return The number of elements pushed on stack. * \return The number of elements pushed on stack.
* \luastack * \luastack
@ -619,6 +644,7 @@ const struct luaL_reg awesome_screen_methods[] =
const struct luaL_reg awesome_screen_meta[] = const struct luaL_reg awesome_screen_meta[] =
{ {
{ "add_signal", luaA_screen_add_signal },
{ "connect_signal", luaA_screen_connect_signal }, { "connect_signal", luaA_screen_connect_signal },
{ "disconnect_signal", luaA_screen_disconnect_signal }, { "disconnect_signal", luaA_screen_disconnect_signal },
{ "emit_signal", luaA_screen_emit_signal }, { "emit_signal", luaA_screen_emit_signal },

10
spawn.c
View File

@ -85,6 +85,8 @@ spawn_monitor_timeout(struct ev_loop *loop, ev_timer *w, int revents)
} }
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
} }
else
warn("spawn::timeout signal is missing");
} }
sn_startup_sequence_unref(w->data); sn_startup_sequence_unref(w->data);
p_delete(&w); p_delete(&w);
@ -191,6 +193,8 @@ spawn_monitor_event(SnMonitorEvent *event, void *data)
} }
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
} }
else
warn("%s signal is missing", event_type_str);
} }
/** Tell the spawn module that an app has been started. /** Tell the spawn module that an app has been started.
@ -240,6 +244,12 @@ spawn_init(void)
globalconf.default_screen, globalconf.default_screen,
spawn_monitor_event, spawn_monitor_event,
NULL, NULL); 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 static void