diff --git a/globalconf.h b/globalconf.h index 608ee851..414b6fcb 100644 --- a/globalconf.h +++ b/globalconf.h @@ -59,7 +59,7 @@ typedef struct xproperty xproperty_t; ARRAY_TYPE(button_t *, button) ARRAY_TYPE(tag_t *, tag) -ARRAY_TYPE(screen_t, screen) +ARRAY_TYPE(screen_t *, screen) ARRAY_TYPE(client_t *, client) ARRAY_TYPE(drawin_t *, drawin) ARRAY_TYPE(xproperty_t, xproperty) diff --git a/lib/awful/layout/init.lua.in b/lib/awful/layout/init.lua.in index eb5af12f..2d6588a3 100755 --- a/lib/awful/layout/init.lua.in +++ b/lib/awful/layout/init.lua.in @@ -152,9 +152,8 @@ local function arrange_tag(t) layout.arrange(tag.getscreen(t)) end +capi.screen.add_signal("arrange") for s = 1, capi.screen.count() do - capi.screen[s]:add_signal("arrange") - tag.attached_connect_signal(s, "property::mwfact", arrange_tag) tag.attached_connect_signal(s, "property::nmaster", arrange_tag) tag.attached_connect_signal(s, "property::ncol", arrange_tag) diff --git a/lib/awful/screen.lua.in b/lib/awful/screen.lua.in index 025e0682..531056a9 100644 --- a/lib/awful/screen.lua.in +++ b/lib/awful/screen.lua.in @@ -104,9 +104,7 @@ function screen.padding(_screen, padding) return data.padding[_screen] end -for s = 1, capi.screen.count() do - capi.screen[s]:add_signal("padding") -end +capi.screen.add_signal("padding") return screen diff --git a/lib/awful/tag.lua.in b/lib/awful/tag.lua.in index 6217d558..3a20ea8b 100644 --- a/lib/awful/tag.lua.in +++ b/lib/awful/tag.lua.in @@ -603,8 +603,8 @@ capi.tag.add_signal("property::windowfact") capi.tag.add_signal("property::screen") capi.tag.add_signal("property::index") +capi.screen.add_signal("tag::history::update") for s = 1, capi.screen.count() do - capi.screen[s]:add_signal("tag::history::update") capi.screen[s]:connect_signal("tag::history::update", tag.history.update) end diff --git a/luaa.c b/luaa.c index a19fbf0d..0424550f 100644 --- a/luaa.c +++ b/luaa.c @@ -57,8 +57,6 @@ extern const struct luaL_Reg awesome_mousegrabber_lib[]; extern const struct luaL_Reg awesome_root_lib[]; extern const struct luaL_Reg awesome_mouse_methods[]; extern const struct luaL_Reg awesome_mouse_meta[]; -extern const struct luaL_Reg awesome_screen_methods[]; -extern const struct luaL_Reg awesome_screen_meta[]; /** Path to config file */ static char *conffile; @@ -402,12 +400,12 @@ luaA_init(xdgHandle* xdg) luaA_registerlib(L, "mousegrabber", awesome_mousegrabber_lib); lua_pop(L, 1); /* luaA_registerlib() leaves the table on stack */ - /* Export screen */ - luaA_openlib(L, "screen", awesome_screen_methods, awesome_screen_meta); - /* Export mouse */ luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta); + /* Export screen */ + screen_class_setup(L); + /* Export button */ button_class_setup(L); diff --git a/mouse.c b/mouse.c index 5bb7bfa1..1045f90e 100644 --- a/mouse.c +++ b/mouse.c @@ -114,14 +114,14 @@ luaA_mouse_index(lua_State *L) * having lots of lua errors in this case. */ if (globalconf.focus.client) - lua_pushnumber(L, screen_array_indexof(&globalconf.screens, globalconf.focus.client->screen) + 1); + lua_pushnumber(L, screen_get_index(globalconf.focus.client->screen)); else lua_pushnumber(L, 1); return 1; } screen = screen_getbycoord(mouse_x, mouse_y); - lua_pushnumber(L, screen_array_indexof(&globalconf.screens, screen) + 1); + lua_pushnumber(L, screen_get_index(screen)); return 1; } @@ -142,8 +142,8 @@ luaA_mouse_newindex(lua_State *L) screen = luaL_checknumber(L, 3) - 1; luaA_checkscreen(screen); - x = globalconf.screens.tab[screen].geometry.x; - y = globalconf.screens.tab[screen].geometry.y; + x = globalconf.screens.tab[screen]->geometry.x; + y = globalconf.screens.tab[screen]->geometry.y; mouse_warp_pointer(globalconf.screen->root, x, y); return 0; diff --git a/objects/client.c b/objects/client.c index 8f639fb8..bee6ef8e 100644 --- a/objects/client.c +++ b/objects/client.c @@ -847,6 +847,14 @@ client_resize(client_t *c, area_t geometry, bool honor_hints) return false; } +static void +client_emit_property_workarea_on_screen(lua_State *L, client_t *c) +{ + luaA_object_push(L, c->screen); + luaA_object_emit_signal(L, -1, "property::workarea", 0); + lua_pop(L, 1); +} + /** Set a client minimized, or not. * \param L The Lua VM state. * \param cidx The client index. @@ -866,7 +874,7 @@ client_set_minimized(lua_State *L, int cidx, bool s) else xwindow_set_state(c->window, XCB_ICCCM_WM_STATE_NORMAL); if(strut_has_value(&c->strut)) - screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0); + client_emit_property_workarea_on_screen(L, c); luaA_object_emit_signal(L, cidx, "property::minimized", 0); } } @@ -886,7 +894,7 @@ client_set_hidden(lua_State *L, int cidx, bool s) c->hidden = s; banning_need_update(); if(strut_has_value(&c->strut)) - screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0); + client_emit_property_workarea_on_screen(L, c); luaA_object_emit_signal(L, cidx, "property::hidden", 0); } } @@ -1142,7 +1150,7 @@ client_unmanage(client_t *c, bool window_valid) luaA_class_emit_signal(globalconf.L, &client_class, "list", 0); if(strut_has_value(&c->strut)) - screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0); + client_emit_property_workarea_on_screen(globalconf.L, c); /* Get rid of all titlebars */ for (client_titlebar_t bar = CLIENT_TITLEBAR_TOP; bar < CLIENT_TITLEBAR_COUNT; bar++) { @@ -1253,7 +1261,7 @@ luaA_client_get(lua_State *L) { luaA_checkscreen(screen); foreach(c, globalconf.clients) - if((*c)->screen == &globalconf.screens.tab[screen]) + if((*c)->screen == globalconf.screens.tab[screen]) { luaA_object_push(L, *c); lua_rawseti(L, -2, i++); @@ -1676,7 +1684,7 @@ luaA_client_set_screen(lua_State *L, client_t *c) { int screen = luaL_checknumber(L, -1) - 1; luaA_checkscreen(screen); - screen_client_moveto(c, &globalconf.screens.tab[screen], true); + screen_client_moveto(c, globalconf.screens.tab[screen], true); return 0; } @@ -1858,7 +1866,7 @@ luaA_client_get_screen(lua_State *L, client_t *c) { if(!c->screen) return 0; - lua_pushnumber(L, 1 + screen_array_indexof(&globalconf.screens, c->screen)); + lua_pushnumber(L, screen_get_index(c->screen)); return 1; } diff --git a/objects/drawin.c b/objects/drawin.c index 22fc3966..dde10c48 100644 --- a/objects/drawin.c +++ b/objects/drawin.c @@ -265,9 +265,9 @@ drawin_set_visible(lua_State *L, int udx, bool v) luaA_object_emit_signal(L, udx, "property::visible", 0); if(strut_has_value(&drawin->strut)) { - screen_t *screen = - screen_getbycoord(drawin->geometry.x, drawin->geometry.y); - screen_emit_signal(globalconf.L, screen, "property::workarea", 0); + luaA_object_push(L, screen_getbycoord(drawin->geometry.x, drawin->geometry.y)); + luaA_object_emit_signal(L, -1, "property::workarea", 0); + lua_pop(L, 1); } } } diff --git a/objects/screen.c b/objects/screen.c index 029a92ad..d002c354 100644 --- a/objects/screen.c +++ b/objects/screen.c @@ -41,7 +41,23 @@ struct screen_output_t uint32_t mm_width, mm_height; }; -ARRAY_FUNCS(screen_output_t, screen_output, DO_NOTHING) +static void +screen_output_wipe(screen_output_t *output) +{ + p_delete(&output); +} + +ARRAY_FUNCS(screen_output_t, screen_output, screen_output_wipe) + +static lua_class_t screen_class; +LUA_OBJECT_FUNCS(screen_class, screen_t, screen) + +/** Collect a screen. */ +static void +screen_wipe(screen_t *s) +{ + screen_output_array_wipe(&s->outputs); +} static inline area_t screen_xsitoarea(xcb_xinerama_screen_info_t si) @@ -57,31 +73,26 @@ screen_xsitoarea(xcb_xinerama_screen_info_t si) } static void -screen_add(screen_t new_screen) +screen_add(lua_State *L, int sidx) { + screen_t *new_screen = luaA_checkudata(L, sidx, &screen_class); + foreach(screen_to_test, globalconf.screens) - if(new_screen.geometry.x == screen_to_test->geometry.x - && new_screen.geometry.y == screen_to_test->geometry.y) + if(new_screen->geometry.x == (*screen_to_test)->geometry.x + && new_screen->geometry.y == (*screen_to_test)->geometry.y) { /* we already have a screen for this area, just check if * it's not bigger and drop it */ - screen_to_test->geometry.width = - MAX(new_screen.geometry.width, screen_to_test->geometry.width); - screen_to_test->geometry.height = - MAX(new_screen.geometry.height, screen_to_test->geometry.height); + (*screen_to_test)->geometry.width = + MAX(new_screen->geometry.width, (*screen_to_test)->geometry.width); + (*screen_to_test)->geometry.height = + MAX(new_screen->geometry.height, (*screen_to_test)->geometry.height); + lua_remove(L, sidx); return; } - signal_add(&new_screen.signals, "property::workarea"); + luaA_object_ref(L, sidx); screen_array_append(&globalconf.screens, new_screen); - - /* Allocate the lua userdata object representing this screen */ - screen_t *s = &globalconf.screens.tab[globalconf.screens.len-1]; - screen_t **ps = lua_newuserdata(globalconf.L, sizeof(*ps)); - *ps = s; - luaL_getmetatable(globalconf.L, "screen"); - lua_setmetatable(globalconf.L, -2); - s->userdata = luaA_object_ref(globalconf.L, -1); } static bool @@ -131,12 +142,11 @@ screen_scan_randr(void) continue; /* Prepare the new screen */ - screen_t new_screen; - p_clear(&new_screen, 1); - new_screen.geometry.x = crtc_info_r->x; - new_screen.geometry.y = crtc_info_r->y; - new_screen.geometry.width= crtc_info_r->width; - new_screen.geometry.height= crtc_info_r->height; + screen_t *new_screen = screen_new(globalconf.L); + new_screen->geometry.x = crtc_info_r->x; + new_screen->geometry.y = crtc_info_r->y; + new_screen->geometry.width= crtc_info_r->width; + new_screen->geometry.height= crtc_info_r->height; xcb_randr_output_t *randr_outputs = xcb_randr_get_crtc_info_outputs(crtc_info_r); @@ -150,7 +160,7 @@ screen_scan_randr(void) char *name = memcpy(p_new(char *, len + 1), xcb_randr_get_output_info_name(output_info_r), len); name[len] = '\0'; - screen_output_array_append(&new_screen.outputs, + screen_output_array_append(&new_screen->outputs, (screen_output_t) { .name = name, .mm_width = output_info_r->mm_width, .mm_height = output_info_r->mm_height }); @@ -158,7 +168,7 @@ screen_scan_randr(void) p_delete(&output_info_r); } - screen_add(new_screen); + screen_add(globalconf.L, -1); p_delete(&crtc_info_r); } @@ -202,10 +212,9 @@ screen_scan_xinerama(void) /* now check if screens overlaps (same x,y): if so, we take only the biggest one */ for(int screen = 0; screen < xinerama_screen_number; screen++) { - screen_t s; - p_clear(&s, 1); - s.geometry = screen_xsitoarea(xsi[screen]); - screen_add(s); + screen_t *s = screen_new(globalconf.L); + s->geometry = screen_xsitoarea(xsi[screen]); + screen_add(globalconf.L, -1); } p_delete(&xsq); @@ -220,13 +229,12 @@ static void screen_scan_x11(void) { /* One screen only / Zaphod mode */ xcb_screen_t *xcb_screen = globalconf.screen; - screen_t s; - p_clear(&s, 1); - s.geometry.x = 0; - s.geometry.y = 0; - s.geometry.width = xcb_screen->width_in_pixels; - s.geometry.height = xcb_screen->height_in_pixels; - screen_add(s); + screen_t *s = screen_new(globalconf.L); + s->geometry.x = 0; + s->geometry.y = 0; + s->geometry.width = xcb_screen->width_in_pixels; + s->geometry.height = xcb_screen->height_in_pixels; + screen_add(globalconf.L, -1); } /** Get screens informations and fill global configuration. @@ -248,12 +256,12 @@ screen_t * screen_getbycoord(int x, int y) { foreach(s, globalconf.screens) - if((x < 0 || (x >= s->geometry.x && x < s->geometry.x + s->geometry.width)) - && (y < 0 || (y >= s->geometry.y && y < s->geometry.y + s->geometry.height))) - return s; + if((x < 0 || (x >= (*s)->geometry.x && x < (*s)->geometry.x + (*s)->geometry.width)) + && (y < 0 || (y >= (*s)->geometry.y && y < (*s)->geometry.y + (*s)->geometry.height))) + return *s; /* No screen found, let's be creative. */ - return &globalconf.screens.tab[0]; + return globalconf.screens.tab[0]; } /** Get screens info. @@ -261,7 +269,7 @@ screen_getbycoord(int x, int y) * \param strut Honor windows strut. * \return The screen area. */ -area_t +static area_t screen_area_get(screen_t *screen, bool strut) { if(!strut) @@ -399,16 +407,19 @@ screen_client_moveto(client_t *c, screen_t *new_screen, bool doresize) client_focus(c); } -/** Push a screen onto the stack. - * \param L The Lua VM state. - * \param s The screen to push. - * \return The number of elements pushed on stack. - */ -static int -luaA_pushscreen(lua_State *L, screen_t *s) +/** Get a screen's index. */ +int +screen_get_index(screen_t *s) { - luaA_object_push(L, s->userdata); - return 1; + int res = 0; + foreach(screen, globalconf.screens) + { + res++; + if (*screen == s) + return res; + } + + return 0; } /** Screen module. @@ -424,172 +435,48 @@ luaA_screen_module_index(lua_State *L) if((name = lua_tostring(L, 2))) foreach(screen, globalconf.screens) - foreach(output, screen->outputs) + foreach(output, (*screen)->outputs) if(A_STREQ(output->name, name)) - return luaA_pushscreen(L, screen); + return luaA_object_push(L, screen); int screen = luaL_checknumber(L, 2) - 1; luaA_checkscreen(screen); - return luaA_pushscreen(L, &globalconf.screens.tab[screen]); + return luaA_object_push(L, globalconf.screens.tab[screen]); } -/** A screen. - * \param L The Lua VM state. - * \return The number of elements pushed on stack. - * \luastack - * \lfield coords The screen coordinates. Immutable. - * \lfield workarea The screen workarea. - */ +LUA_OBJECT_EXPORT_PROPERTY(screen, screen_t, geometry, luaA_pusharea) + static int -luaA_screen_index(lua_State *L) +luaA_screen_get_index(lua_State *L, screen_t *s) { - const char *buf; - screen_t **ps; - screen_t *s; - - /* Get metatable of the screen. */ - lua_getmetatable(L, 1); - /* Get the field */ - lua_pushvalue(L, 2); - lua_rawget(L, -2); - /* Do we have a field like that? */ - if(!lua_isnil(L, -1)) - { - /* Yes, so return it! */ - lua_remove(L, -2); - return 1; - } - /* No, so remove everything. */ - lua_pop(L, 2); - - buf = luaL_checkstring(L, 2); - ps = luaL_checkudata(L, 1, "screen"); - s = *ps; - - if(A_STREQ(buf, "index")) - { - lua_pushinteger(L, screen_array_indexof(&globalconf.screens, s) + 1); - return 1; - } - - if(A_STREQ(buf, "geometry")) - { - luaA_pusharea(L, s->geometry); - return 1; - } - - if(A_STREQ(buf, "workarea")) - { - luaA_pusharea(L, screen_area_get(s, true)); - return 1; - } - - if(A_STREQ(buf, "outputs")) - { - lua_createtable(L, 0, s->outputs.len); - foreach(output, s->outputs) - { - lua_createtable(L, 2, 0); - - lua_pushinteger(L, output->mm_width); - lua_setfield(L, -2, "mm_width"); - lua_pushinteger(L, output->mm_height); - lua_setfield(L, -2, "mm_height"); - - lua_setfield(L, -2, output->name); - } - /* The table of tables we created. */ - return 1; - } - - return luaA_default_index(L); + lua_pushinteger(L, screen_get_index(s)); + return 1; } -/** 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) +luaA_screen_get_outputs(lua_State *L, screen_t *s) { - screen_t **ps = luaL_checkudata(L, 1, "screen"); - screen_t *s = *ps; - const char *name = luaL_checkstring(L, 2); - signal_add(&s->signals, name); - return 0; + lua_createtable(L, 0, s->outputs.len); + foreach(output, s->outputs) + { + lua_createtable(L, 2, 0); + + lua_pushinteger(L, output->mm_width); + lua_setfield(L, -2, "mm_width"); + lua_pushinteger(L, output->mm_height); + lua_setfield(L, -2, "mm_height"); + + lua_setfield(L, -2, output->name); + } + /* The table of tables we created. */ + return 1; } -/** Connect a screen's signal. - * \param L The Lua VM state. - * \return The number of elements pushed on stack. - * \luastack - * \lvalue A screen. - * \lparam A signal name. - * \lparam A function to call when the signal is emitted. - */ static int -luaA_screen_connect_signal(lua_State *L) +luaA_screen_get_workarea(lua_State *L, screen_t *s) { - screen_t **ps = luaL_checkudata(L, 1, "screen"); - screen_t *s = *ps; - const char *name = luaL_checkstring(L, 2); - luaA_checkfunction(L, 3); - signal_connect(&s->signals, name, luaA_object_ref(L, 3)); - return 0; -} - -/** Remove 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. - * \lparam A function to remove - */ -static int -luaA_screen_disconnect_signal(lua_State *L) -{ - screen_t **ps = luaL_checkudata(L, 1, "screen"); - screen_t *s = *ps; - const char *name = luaL_checkstring(L, 2); - luaA_checkfunction(L, 3); - const void *ref = lua_topointer(L, 3); - signal_disconnect(&s->signals, name, ref); - luaA_object_unref(L, (void *) ref); - return 0; -} - -/** Emit a signal to a screen. - * \param L The Lua VM state. - * \param screen The screen. - * \param name The signal name. - * \param nargs The number of arguments to the signal function. - */ -void -screen_emit_signal(lua_State *L, screen_t *screen, const char *name, int nargs) -{ - luaA_pushscreen(L, screen); - lua_insert(L, - nargs - 1); - signal_object_emit(L, &screen->signals, name, nargs + 1); -} - -/** Emit 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. - * \lparam Various arguments, optional. - */ -static int -luaA_screen_emit_signal(lua_State *L) -{ - screen_t **ps = luaL_checkudata(L, 1, "screen"); - screen_emit_signal(L, *ps, luaL_checkstring(L, 2), lua_gettop(L) - 2); - return 0; + luaA_pusharea(L, screen_area_get(s, true)); + return 1; } /** Get the screen count. @@ -606,23 +493,48 @@ luaA_screen_count(lua_State *L) return 1; } -const struct luaL_Reg awesome_screen_methods[] = +void +screen_class_setup(lua_State *L) { - { "count", luaA_screen_count }, - { "__index", luaA_screen_module_index }, - { "__newindex", luaA_default_newindex }, - { NULL, NULL } -}; + static const struct luaL_Reg screen_methods[] = + { + LUA_CLASS_METHODS(screen) + { "count", luaA_screen_count }, + { "__index", luaA_screen_module_index }, + { "__newindex", luaA_default_newindex }, + { NULL, NULL } + }; -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 }, - { "__index", luaA_screen_index }, - { "__newindex", luaA_default_newindex }, - { NULL, NULL } -}; + static const struct luaL_Reg screen_meta[] = + { + LUA_OBJECT_META(screen) + LUA_CLASS_META + { NULL, NULL }, + }; + + luaA_class_setup(L, &screen_class, "screen", NULL, + (lua_class_allocator_t) screen_new, + (lua_class_collector_t) screen_wipe, + NULL, + luaA_class_index_miss_property, luaA_class_newindex_miss_property, + screen_methods, screen_meta); + luaA_class_add_property(&screen_class, "geometry", + NULL, + (lua_class_propfunc_t) luaA_screen_get_geometry, + NULL); + luaA_class_add_property(&screen_class, "index", + NULL, + (lua_class_propfunc_t) luaA_screen_get_index, + NULL); + luaA_class_add_property(&screen_class, "outputs", + NULL, + (lua_class_propfunc_t) luaA_screen_get_outputs, + NULL); + luaA_class_add_property(&screen_class, "workarea", + NULL, + (lua_class_propfunc_t) luaA_screen_get_workarea, + NULL); + signal_add(&screen_class.signals, "property::workarea"); +} // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/objects/screen.h b/objects/screen.h index c812baaa..a8db3370 100644 --- a/objects/screen.h +++ b/objects/screen.h @@ -30,21 +30,18 @@ ARRAY_TYPE(screen_output_t, screen_output) struct a_screen { + LUA_OBJECT_HEADER /** Screen geometry */ area_t geometry; - /** The signals emitted by screen objects */ - signal_array_t signals; /** The screen outputs informations */ screen_output_array_t outputs; - /** The lua userdata representing this screen */ - void *userdata; }; -ARRAY_FUNCS(screen_t, screen, DO_NOTHING) +ARRAY_FUNCS(screen_t *, screen, DO_NOTHING) -void screen_emit_signal(lua_State *, screen_t *, const char *, int); +void screen_class_setup(lua_State *L); void screen_scan(void); screen_t *screen_getbycoord(int, int); -area_t screen_area_get(screen_t *, bool); +int screen_get_index(screen_t *); area_t display_area_get(void); void screen_client_moveto(client_t *, screen_t *, bool); diff --git a/objects/window.c b/objects/window.c index 8184dbd7..a843e89b 100644 --- a/objects/window.c +++ b/objects/window.c @@ -80,7 +80,11 @@ luaA_window_struts(lua_State *L) /* FIXME: Only emit if the workarea actually changed * (= window is visible, only on the right screen)? */ foreach(s, globalconf.screens) - screen_emit_signal(L, s, "property::workarea", 0); + { + luaA_object_push(L, *s); + luaA_object_emit_signal(L, -1, "property::workarea", 0); + lua_pop(L, 1); + } } return luaA_pushstrut(L, window->strut);