From 2cf4ea5cd41754b602ca831a433d5f61bdb74a00 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 17 Apr 2016 13:35:23 +0200 Subject: [PATCH 1/8] xutil.h: Add defines for valid coordinates and sizes Signed-off-by: Uli Schlachter --- common/xutil.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/xutil.h b/common/xutil.h index 0864feaa0..5ee3b08de 100644 --- a/common/xutil.h +++ b/common/xutil.h @@ -28,6 +28,11 @@ #include "common/atoms.h" #include "common/util.h" +#define MAX_X11_COORDINATE INT16_MAX +#define MIN_X11_COORDINATE INT16_MIN +#define MAX_X11_SIZE UINT16_MAX +#define MIN_X11_SIZE 1 + static inline char * xutil_get_text_property_from_reply(xcb_get_property_reply_t *reply) { From 163c15979e1737cab5b391cd0fbfb81de2d6b459 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 17 Apr 2016 13:37:15 +0200 Subject: [PATCH 2/8] Add range-checking Lua stack -> C value converters Signed-off-by: Uli Schlachter --- luaa.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/luaa.h b/luaa.h index 42404eeb1..c27b5d219 100644 --- a/luaa.h +++ b/luaa.h @@ -75,6 +75,18 @@ luaA_typerror(lua_State *L, int narg, const char *tname) return luaL_argerror(L, narg, msg); } +static inline int +luaA_rangerror(lua_State *L, int narg, double min, double max) +{ + const char *msg = lua_pushfstring(L, "value in [%f, %f] expected, got %f", + min, max, (double) lua_tonumber(L, narg)); +#if LUA_VERSION_NUM >= 502 + luaL_traceback(L, L, NULL, 2); + lua_concat(L, 2); +#endif + return luaL_argerror(L, narg, msg); +} + static inline void luaA_getuservalue(lua_State *L, int idx) { @@ -166,6 +178,33 @@ luaA_getopt_integer(lua_State *L, int idx, const char *name, lua_Integer def) return def; } +static inline int +luaA_checkinteger_range(lua_State *L, int n, int min, int max) +{ + int result = luaA_checkinteger(L, n); + if (result < min || result > max) + luaA_rangerror(L, n, min, max); + return result; +} + +static inline lua_Integer +luaA_optinteger_range(lua_State *L, int narg, lua_Integer def, int min, int max) +{ + if (lua_isnoneornil(L, narg)) + return def; + return luaA_checkinteger_range(L, narg, min, max); +} + +static inline int +luaA_getopt_integer_range(lua_State *L, int idx, const char *name, lua_Integer def, int min, int max) +{ + lua_getfield(L, idx, name); + if (lua_isnil(L, -1) || lua_isnumber(L, -1)) + def = luaA_optinteger_range(L, -1, def, min, max); + lua_pop(L, 1); + return def; +} + /** Push a area type to a table on stack. * \param L The Lua VM state. * \param geometry The area geometry to push. From 39c031241f5e04e6c1a32a67508f79b47ee6b4e8 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 18 Apr 2016 00:55:22 -0400 Subject: [PATCH 3/8] Add number range checking. Add the "number" equivalent functions for the integers one introduced by the last commit. --- luaa.h | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/luaa.h b/luaa.h index c27b5d219..c26b4d6d6 100644 --- a/luaa.h +++ b/luaa.h @@ -153,10 +153,37 @@ luaA_getopt_number(lua_State *L, int idx, const char *name, lua_Number def) return def; } +static inline lua_Number +luaA_checknumber_range(lua_State *L, int n, lua_Number min, lua_Number max) +{ + lua_Number result = lua_tonumber(L, n); + if (result < min || result > max) + luaA_rangerror(L, n, min, max); + return result; +} + +static inline lua_Number +luaA_optnumber_range(lua_State *L, int narg, lua_Number def, lua_Number min, lua_Number max) +{ + if (lua_isnoneornil(L, narg)) + return def; + return luaA_checknumber_range(L, narg, min, max); +} + +static inline lua_Number +luaA_getopt_number_range(lua_State *L, int idx, const char *name, lua_Number def, lua_Number min, lua_Number max) +{ + lua_getfield(L, idx, name); + if (lua_isnil(L, -1) || lua_isnumber(L, -1)) + def = luaA_optnumber_range(L, -1, def, min, max); + lua_pop(L, 1); + return def; +} + static inline int luaA_checkinteger(lua_State *L, int n) { - double d = lua_tonumber(L, n); + lua_Number d = lua_tonumber(L, n); if (d != (int)d) luaA_typerror(L, n, "integer"); return d; From d46e11f5e13c2c20c16d18f35dcea6035440060c Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 17 Apr 2016 13:44:05 +0200 Subject: [PATCH 4/8] Add range-checking to lots of arguments in the C code This change catches things like c:geometry { width = -42 }. Helps-a-bit-with: https://github.com/awesomeWM/awesome/pull/820 (fixes X errors) Signed-off-by: Uli Schlachter --- luaa.c | 2 +- mouse.c | 7 ++++--- objects/client.c | 14 +++++++------- objects/drawin.c | 23 +++++++++++------------ objects/window.c | 5 +++-- root.c | 5 +++-- strut.c | 8 ++++---- systray.c | 9 +++++---- 8 files changed, 38 insertions(+), 35 deletions(-) diff --git a/luaa.c b/luaa.c index e32544ed0..35c93879c 100644 --- a/luaa.c +++ b/luaa.c @@ -181,7 +181,7 @@ luaA_load_image(lua_State *L) static int luaA_set_preferred_icon_size(lua_State *L) { - globalconf.preferred_icon_size = luaL_checknumber(L, 1); + globalconf.preferred_icon_size = luaA_checkinteger_range(L, 1, 0, UINT32_MAX); return 0; } diff --git a/mouse.c b/mouse.c index 75301b56e..78557dfd0 100644 --- a/mouse.c +++ b/mouse.c @@ -31,6 +31,7 @@ #include "mouse.h" #include "common/util.h" +#include "common/xutil.h" #include "globalconf.h" #include "objects/client.h" #include "objects/drawin.h" @@ -111,7 +112,7 @@ mouse_query_pointer_root(int16_t *x, int16_t *y, xcb_window_t *child, uint16_t * * \param y Y-coordinate inside window. */ static inline void -mouse_warp_pointer(xcb_window_t window, int x, int y) +mouse_warp_pointer(xcb_window_t window, int16_t x, int16_t y) { xcb_warp_pointer(globalconf.connection, XCB_NONE, window, 0, 0, 0, 0, x, y); @@ -223,8 +224,8 @@ luaA_mouse_coords(lua_State *L) if(!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL, &mask)) return 0; - x = luaA_getopt_number(L, 1, "x", mouse_x); - y = luaA_getopt_number(L, 1, "y", mouse_y); + x = luaA_getopt_integer_range(L, 1, "x", mouse_x, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + y = luaA_getopt_integer_range(L, 1, "y", mouse_y, MIN_X11_COORDINATE, MAX_X11_COORDINATE); if(ignore_enter_notify) client_ignore_enterleave_events(); diff --git a/objects/client.c b/objects/client.c index d530376ed..225b40480 100644 --- a/objects/client.c +++ b/objects/client.c @@ -2538,7 +2538,7 @@ luaA_client_titlebar_ ## name(lua_State *L) \ if (lua_isnil(L, 2)) \ titlebar_resize(L, 1, c, index, 0); \ else \ - titlebar_resize(L, 1, c, index, luaL_checknumber(L, 2)); \ + titlebar_resize(L, 1, c, index, luaA_checkinteger_range(L, 2, 0, MAX_X11_SIZE)); \ } \ \ luaA_object_push_item(L, 1, titlebar_get_drawable(L, c, 1, index)); \ @@ -2566,8 +2566,8 @@ luaA_client_geometry(lua_State *L) area_t geometry; luaA_checktable(L, 2); - geometry.x = luaA_getopt_number(L, 2, "x", c->geometry.x); - geometry.y = luaA_getopt_number(L, 2, "y", c->geometry.y); + geometry.x = luaA_getopt_integer_range(L, 2, "x", c->geometry.x, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + geometry.y = luaA_getopt_integer_range(L, 2, "y", c->geometry.y, MIN_X11_COORDINATE, MAX_X11_COORDINATE); if(client_isfixed(c)) { geometry.width = c->geometry.width; @@ -2575,8 +2575,8 @@ luaA_client_geometry(lua_State *L) } else { - geometry.width = luaA_getopt_number(L, 2, "width", c->geometry.width); - geometry.height = luaA_getopt_number(L, 2, "height", c->geometry.height); + geometry.width = luaA_getopt_integer_range(L, 2, "width", c->geometry.width, MIN_X11_SIZE, MAX_X11_SIZE); + geometry.height = luaA_getopt_integer_range(L, 2, "height", c->geometry.height, MIN_X11_SIZE, MAX_X11_SIZE); } client_resize(c, geometry, c->size_hints_honor); @@ -2600,8 +2600,8 @@ luaA_client_apply_size_hints(lua_State *L) area_t geometry = c->geometry; if(!client_isfixed(c)) { - geometry.width = luaL_checknumber(L, 2); - geometry.height = luaL_checknumber(L, 3); + geometry.width = luaA_checkinteger_range(L, 2, MIN_X11_SIZE, MAX_X11_SIZE); + geometry.height = luaA_checkinteger_range(L, 3, MIN_X11_SIZE, MAX_X11_SIZE); } if (c->size_hints_honor) diff --git a/objects/drawin.c b/objects/drawin.c index b550e0504..8656e9b22 100644 --- a/objects/drawin.c +++ b/objects/drawin.c @@ -34,6 +34,7 @@ #include "drawin.h" #include "common/atoms.h" #include "common/xcursor.h" +#include "common/xutil.h" #include "event.h" #include "ewmh.h" #include "objects/client.h" @@ -406,10 +407,10 @@ luaA_drawin_geometry(lua_State *L) area_t wingeom; luaA_checktable(L, 2); - wingeom.x = luaA_getopt_number(L, 2, "x", drawin->geometry.x); - wingeom.y = luaA_getopt_number(L, 2, "y", drawin->geometry.y); - wingeom.width = luaA_getopt_number(L, 2, "width", drawin->geometry.width); - wingeom.height = luaA_getopt_number(L, 2, "height", drawin->geometry.height); + wingeom.x = luaA_getopt_integer_range(L, 2, "x", drawin->geometry.x, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + wingeom.y = luaA_getopt_integer_range(L, 2, "y", drawin->geometry.y, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + wingeom.width = luaA_getopt_integer_range(L, 2, "width", drawin->geometry.width, MIN_X11_SIZE, MAX_X11_SIZE); + wingeom.height = luaA_getopt_integer_range(L, 2, "height", drawin->geometry.height, MIN_X11_SIZE, MAX_X11_SIZE); if(wingeom.width > 0 && wingeom.height > 0) drawin_moveresize(L, 1, wingeom); @@ -426,7 +427,8 @@ LUA_OBJECT_EXPORT_PROPERTY(drawin, drawin_t, visible, lua_pushboolean) static int luaA_drawin_set_x(lua_State *L, drawin_t *drawin) { - drawin_moveresize(L, -3, (area_t) { .x = luaA_checkinteger(L, -1), + int x = luaA_checkinteger_range(L, -1, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + drawin_moveresize(L, -3, (area_t) { .x = x, .y = drawin->geometry.y, .width = drawin->geometry.width, .height = drawin->geometry.height }); @@ -443,8 +445,9 @@ luaA_drawin_get_x(lua_State *L, drawin_t *drawin) static int luaA_drawin_set_y(lua_State *L, drawin_t *drawin) { + int y = luaA_checkinteger_range(L, -1, MIN_X11_COORDINATE, MAX_X11_COORDINATE); drawin_moveresize(L, -3, (area_t) { .x = drawin->geometry.x, - .y = luaA_checkinteger(L, -1), + .y = y, .width = drawin->geometry.width, .height = drawin->geometry.height }); return 0; @@ -460,9 +463,7 @@ luaA_drawin_get_y(lua_State *L, drawin_t *drawin) static int luaA_drawin_set_width(lua_State *L, drawin_t *drawin) { - int width = luaA_checkinteger(L, -1); - if(width <= 0) - luaL_error(L, "invalid width"); + int width = luaA_checkinteger_range(L, -1, MIN_X11_SIZE, MAX_X11_SIZE); drawin_moveresize(L, -3, (area_t) { .x = drawin->geometry.x, .y = drawin->geometry.y, .width = width, @@ -480,9 +481,7 @@ luaA_drawin_get_width(lua_State *L, drawin_t *drawin) static int luaA_drawin_set_height(lua_State *L, drawin_t *drawin) { - int height = luaA_checkinteger(L, -1); - if(height <= 0) - luaL_error(L, "invalid height"); + int height = luaA_checkinteger_range(L, -1, MIN_X11_SIZE, MAX_X11_SIZE); drawin_moveresize(L, -3, (area_t) { .x = drawin->geometry.x, .y = drawin->geometry.y, .width = drawin->geometry.width, diff --git a/objects/window.c b/objects/window.c index 5f229225b..9ec1595bf 100644 --- a/objects/window.c +++ b/objects/window.c @@ -29,6 +29,7 @@ #include "objects/window.h" #include "common/atoms.h" +#include "common/xutil.h" #include "ewmh.h" #include "property.h" #include "xwindow.h" @@ -352,7 +353,7 @@ window_set_xproperty(lua_State *L, xcb_window_t window, int prop_idx, int value_ } else if(prop->type == PROP_NUMBER || prop->type == PROP_BOOLEAN) { if (prop->type == PROP_NUMBER) - number = luaL_checkinteger(L, value_idx); + number = luaA_checkinteger_range(L, value_idx, 0, UINT32_MAX); else number = luaA_checkboolean(L, value_idx); data = &number; @@ -475,7 +476,7 @@ window_translate_type(window_type_t type) static int luaA_window_set_border_width(lua_State *L, window_t *c) { - window_set_border_width(L, -3, luaL_checknumber(L, -1)); + window_set_border_width(L, -3, luaA_checkinteger_range(L, -1, 0, MAX_X11_SIZE)); return 0; } diff --git a/root.c b/root.c index f1236e86e..aa31cf1ed 100644 --- a/root.c +++ b/root.c @@ -30,6 +30,7 @@ #include "common/atoms.h" #include "common/xcursor.h" +#include "common/xutil.h" #include "objects/button.h" #include "xwindow.h" @@ -265,8 +266,8 @@ luaA_root_fake_input(lua_State *L) { type = XCB_MOTION_NOTIFY; detail = luaA_checkboolean(L, 2); /* relative to the current position or not */ - x = luaL_checkinteger(L, 3); - y = luaL_checkinteger(L, 4); + x = luaA_checkinteger_range(L, 3, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + y = luaA_checkinteger_range(L, 4, MIN_X11_COORDINATE, MAX_X11_COORDINATE); } else return 0; diff --git a/strut.c b/strut.c index 6300f4355..b90c75182 100644 --- a/strut.c +++ b/strut.c @@ -51,10 +51,10 @@ void luaA_tostrut(lua_State *L, int idx, strut_t *strut) { luaA_checktable(L, idx); - strut->left = luaA_getopt_integer(L, idx, "left", strut->left); - strut->right = luaA_getopt_integer(L, idx, "right", strut->right); - strut->top = luaA_getopt_integer(L, idx, "top", strut->top); - strut->bottom = luaA_getopt_integer(L, idx, "bottom", strut->bottom); + strut->left = luaA_getopt_integer_range(L, idx, "left", strut->left, 0, UINT16_MAX); + strut->right = luaA_getopt_integer_range(L, idx, "right", strut->right, 0, UINT16_MAX); + strut->top = luaA_getopt_integer_range(L, idx, "top", strut->top, 0, UINT16_MAX); + strut->bottom = luaA_getopt_integer_range(L, idx, "bottom", strut->bottom, 0, UINT16_MAX); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/systray.c b/systray.c index fea74449b..105a5a044 100644 --- a/systray.c +++ b/systray.c @@ -21,6 +21,7 @@ #include "systray.h" #include "common/atoms.h" +#include "common/xutil.h" #include "objects/drawin.h" #include "xwindow.h" #include "globalconf.h" @@ -324,13 +325,13 @@ luaA_systray(lua_State *L) { size_t bg_len; drawin_t *w = luaA_checkudata(L, 1, &drawin_class); - int x = luaL_checkinteger(L, 2); - int y = luaL_checkinteger(L, 3); - int base_size = luaL_checkinteger(L, 4); + int x = luaA_checkinteger_range(L, 2, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + int y = luaA_checkinteger_range(L, 3, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + int base_size = luaA_checkinteger_range(L, 4, MIN_X11_SIZE, MAX_X11_SIZE); bool horiz = lua_toboolean(L, 5); const char *bg = luaL_checklstring(L, 6, &bg_len); bool revers = lua_toboolean(L, 7); - int spacing = luaL_checkinteger(L, 8); + int spacing = luaA_checkinteger_range(L, 8, 0, MAX_X11_COORDINATE); color_t bg_color; bool force_redraw = false; From 9991f9ccc8786744430c2c0c7bb913f4f4699215 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 18 Apr 2016 01:15:15 -0400 Subject: [PATCH 5/8] geometry: Use the relevant rounding functions instead of integers In the case where one want to put the cursor at the middle of the workarea, it is logic to do: x=screen.workarea.x+screen.workasrea.width/2 However, this can cause floating points. This commit move the burden back to the C-API so the Lua placement code doesn't have to add a large number of rounding methods. Given 1 type of rounding cover a vast majority of use cases for each types of coordinates, the C-API can take care of it in peace. For the other corner cases, it is still possible for the Lua code to do the rounding there, but no longer necessary. The convenstions are: 'x' and 'y': use round (move to the closest point) 'width' and 'height': use ceil (to avoid involontary truncating) --- objects/client.c | 16 +++++++++------- objects/drawin.c | 18 ++++++++++-------- objects/window.c | 2 +- objects/window.h | 1 + root.c | 6 ++++-- strut.c | 9 +++++---- systray.c | 8 ++++---- 7 files changed, 34 insertions(+), 26 deletions(-) diff --git a/objects/client.c b/objects/client.c index 225b40480..8ec2118d7 100644 --- a/objects/client.c +++ b/objects/client.c @@ -98,6 +98,8 @@ #include "systray.h" #include "xwindow.h" +#include "math.h" + #include #include #include @@ -2538,7 +2540,7 @@ luaA_client_titlebar_ ## name(lua_State *L) \ if (lua_isnil(L, 2)) \ titlebar_resize(L, 1, c, index, 0); \ else \ - titlebar_resize(L, 1, c, index, luaA_checkinteger_range(L, 2, 0, MAX_X11_SIZE)); \ + titlebar_resize(L, 1, c, index, ceil(luaA_checknumber_range(L, 2, 0, MAX_X11_SIZE))); \ } \ \ luaA_object_push_item(L, 1, titlebar_get_drawable(L, c, 1, index)); \ @@ -2566,8 +2568,8 @@ luaA_client_geometry(lua_State *L) area_t geometry; luaA_checktable(L, 2); - geometry.x = luaA_getopt_integer_range(L, 2, "x", c->geometry.x, MIN_X11_COORDINATE, MAX_X11_COORDINATE); - geometry.y = luaA_getopt_integer_range(L, 2, "y", c->geometry.y, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + geometry.x = round(luaA_getopt_number_range(L, 2, "x", c->geometry.x, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); + geometry.y = round(luaA_getopt_number_range(L, 2, "y", c->geometry.y, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); if(client_isfixed(c)) { geometry.width = c->geometry.width; @@ -2575,8 +2577,8 @@ luaA_client_geometry(lua_State *L) } else { - geometry.width = luaA_getopt_integer_range(L, 2, "width", c->geometry.width, MIN_X11_SIZE, MAX_X11_SIZE); - geometry.height = luaA_getopt_integer_range(L, 2, "height", c->geometry.height, MIN_X11_SIZE, MAX_X11_SIZE); + geometry.width = ceil(luaA_getopt_number_range(L, 2, "width", c->geometry.width, MIN_X11_SIZE, MAX_X11_SIZE)); + geometry.height = ceil(luaA_getopt_number_range(L, 2, "height", c->geometry.height, MIN_X11_SIZE, MAX_X11_SIZE)); } client_resize(c, geometry, c->size_hints_honor); @@ -2600,8 +2602,8 @@ luaA_client_apply_size_hints(lua_State *L) area_t geometry = c->geometry; if(!client_isfixed(c)) { - geometry.width = luaA_checkinteger_range(L, 2, MIN_X11_SIZE, MAX_X11_SIZE); - geometry.height = luaA_checkinteger_range(L, 3, MIN_X11_SIZE, MAX_X11_SIZE); + geometry.width = ceil(luaA_checknumber_range(L, 2, MIN_X11_SIZE, MAX_X11_SIZE)); + geometry.height = ceil(luaA_checknumber_range(L, 3, MIN_X11_SIZE, MAX_X11_SIZE)); } if (c->size_hints_honor) diff --git a/objects/drawin.c b/objects/drawin.c index 8656e9b22..7e4bd4155 100644 --- a/objects/drawin.c +++ b/objects/drawin.c @@ -42,6 +42,8 @@ #include "systray.h" #include "xwindow.h" +#include "math.h" + #include #include @@ -407,10 +409,10 @@ luaA_drawin_geometry(lua_State *L) area_t wingeom; luaA_checktable(L, 2); - wingeom.x = luaA_getopt_integer_range(L, 2, "x", drawin->geometry.x, MIN_X11_COORDINATE, MAX_X11_COORDINATE); - wingeom.y = luaA_getopt_integer_range(L, 2, "y", drawin->geometry.y, MIN_X11_COORDINATE, MAX_X11_COORDINATE); - wingeom.width = luaA_getopt_integer_range(L, 2, "width", drawin->geometry.width, MIN_X11_SIZE, MAX_X11_SIZE); - wingeom.height = luaA_getopt_integer_range(L, 2, "height", drawin->geometry.height, MIN_X11_SIZE, MAX_X11_SIZE); + wingeom.x = round(luaA_getopt_number_range(L, 2, "x", drawin->geometry.x, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); + wingeom.y = round(luaA_getopt_number_range(L, 2, "y", drawin->geometry.y, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); + wingeom.width = ceil(luaA_getopt_number_range(L, 2, "width", drawin->geometry.width, MIN_X11_SIZE, MAX_X11_SIZE)); + wingeom.height = ceil(luaA_getopt_number_range(L, 2, "height", drawin->geometry.height, MIN_X11_SIZE, MAX_X11_SIZE)); if(wingeom.width > 0 && wingeom.height > 0) drawin_moveresize(L, 1, wingeom); @@ -427,7 +429,7 @@ LUA_OBJECT_EXPORT_PROPERTY(drawin, drawin_t, visible, lua_pushboolean) static int luaA_drawin_set_x(lua_State *L, drawin_t *drawin) { - int x = luaA_checkinteger_range(L, -1, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + int x = round(luaA_checknumber_range(L, -1, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); drawin_moveresize(L, -3, (area_t) { .x = x, .y = drawin->geometry.y, .width = drawin->geometry.width, @@ -445,7 +447,7 @@ luaA_drawin_get_x(lua_State *L, drawin_t *drawin) static int luaA_drawin_set_y(lua_State *L, drawin_t *drawin) { - int y = luaA_checkinteger_range(L, -1, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + int y = round(luaA_checknumber_range(L, -1, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); drawin_moveresize(L, -3, (area_t) { .x = drawin->geometry.x, .y = y, .width = drawin->geometry.width, @@ -463,7 +465,7 @@ luaA_drawin_get_y(lua_State *L, drawin_t *drawin) static int luaA_drawin_set_width(lua_State *L, drawin_t *drawin) { - int width = luaA_checkinteger_range(L, -1, MIN_X11_SIZE, MAX_X11_SIZE); + int width = ceil(luaA_checknumber_range(L, -1, MIN_X11_SIZE, MAX_X11_SIZE)); drawin_moveresize(L, -3, (area_t) { .x = drawin->geometry.x, .y = drawin->geometry.y, .width = width, @@ -481,7 +483,7 @@ luaA_drawin_get_width(lua_State *L, drawin_t *drawin) static int luaA_drawin_set_height(lua_State *L, drawin_t *drawin) { - int height = luaA_checkinteger_range(L, -1, MIN_X11_SIZE, MAX_X11_SIZE); + int height = ceil(luaA_checknumber_range(L, -1, MIN_X11_SIZE, MAX_X11_SIZE)); drawin_moveresize(L, -3, (area_t) { .x = drawin->geometry.x, .y = drawin->geometry.y, .width = drawin->geometry.width, diff --git a/objects/window.c b/objects/window.c index 9ec1595bf..15b582c86 100644 --- a/objects/window.c +++ b/objects/window.c @@ -476,7 +476,7 @@ window_translate_type(window_type_t type) static int luaA_window_set_border_width(lua_State *L, window_t *c) { - window_set_border_width(L, -3, luaA_checkinteger_range(L, -1, 0, MAX_X11_SIZE)); + window_set_border_width(L, -3, round(luaA_checknumber_range(L, -1, 0, MAX_X11_SIZE))); return 0; } diff --git a/objects/window.h b/objects/window.h index 3afcbb352..5386fafea 100644 --- a/objects/window.h +++ b/objects/window.h @@ -26,6 +26,7 @@ #include "common/luaclass.h" #include "objects/button.h" #include "strut.h" +#include "math.h" /** Windows type */ typedef enum diff --git a/root.c b/root.c index aa31cf1ed..99ebdb1ca 100644 --- a/root.c +++ b/root.c @@ -34,6 +34,8 @@ #include "objects/button.h" #include "xwindow.h" +#include "math.h" + #include #include #include @@ -266,8 +268,8 @@ luaA_root_fake_input(lua_State *L) { type = XCB_MOTION_NOTIFY; detail = luaA_checkboolean(L, 2); /* relative to the current position or not */ - x = luaA_checkinteger_range(L, 3, MIN_X11_COORDINATE, MAX_X11_COORDINATE); - y = luaA_checkinteger_range(L, 4, MIN_X11_COORDINATE, MAX_X11_COORDINATE); + x = round(luaA_checknumber_range(L, 3, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); + y = round(luaA_checknumber_range(L, 4, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); } else return 0; diff --git a/strut.c b/strut.c index b90c75182..8d46de344 100644 --- a/strut.c +++ b/strut.c @@ -21,6 +21,7 @@ #include "strut.h" #include "luaa.h" +#include "math.h" /** Push a strut type to a table on stack. * \param L The Lua VM state. @@ -51,10 +52,10 @@ void luaA_tostrut(lua_State *L, int idx, strut_t *strut) { luaA_checktable(L, idx); - strut->left = luaA_getopt_integer_range(L, idx, "left", strut->left, 0, UINT16_MAX); - strut->right = luaA_getopt_integer_range(L, idx, "right", strut->right, 0, UINT16_MAX); - strut->top = luaA_getopt_integer_range(L, idx, "top", strut->top, 0, UINT16_MAX); - strut->bottom = luaA_getopt_integer_range(L, idx, "bottom", strut->bottom, 0, UINT16_MAX); + strut->left = ceil(luaA_getopt_number_range(L, idx, "left", strut->left, 0, UINT16_MAX)); + strut->right = ceil(luaA_getopt_number_range(L, idx, "right", strut->right, 0, UINT16_MAX)); + strut->top = ceil(luaA_getopt_number_range(L, idx, "top", strut->top, 0, UINT16_MAX)); + strut->bottom = ceil(luaA_getopt_number_range(L, idx, "bottom", strut->bottom, 0, UINT16_MAX)); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/systray.c b/systray.c index 105a5a044..cad77b5ab 100644 --- a/systray.c +++ b/systray.c @@ -325,13 +325,13 @@ luaA_systray(lua_State *L) { size_t bg_len; drawin_t *w = luaA_checkudata(L, 1, &drawin_class); - int x = luaA_checkinteger_range(L, 2, MIN_X11_COORDINATE, MAX_X11_COORDINATE); - int y = luaA_checkinteger_range(L, 3, MIN_X11_COORDINATE, MAX_X11_COORDINATE); - int base_size = luaA_checkinteger_range(L, 4, MIN_X11_SIZE, MAX_X11_SIZE); + int x = round(luaA_checknumber_range(L, 2, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); + int y = round(luaA_checknumber_range(L, 3, MIN_X11_COORDINATE, MAX_X11_COORDINATE)); + int base_size = ceil(luaA_checknumber_range(L, 4, MIN_X11_SIZE, MAX_X11_SIZE)); bool horiz = lua_toboolean(L, 5); const char *bg = luaL_checklstring(L, 6, &bg_len); bool revers = lua_toboolean(L, 7); - int spacing = luaA_checkinteger_range(L, 8, 0, MAX_X11_COORDINATE); + int spacing = ceil(luaA_checknumber_range(L, 8, 0, MAX_X11_COORDINATE)); color_t bg_color; bool force_redraw = false; From b938a99e1e032d7515c02e1936e67b75db325183 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 18 Apr 2016 01:24:12 -0400 Subject: [PATCH 6/8] layout: Avoid creating negative geometries when adding gaps --- lib/awful/layout/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/awful/layout/init.lua b/lib/awful/layout/init.lua index b1da60e6b..3d32ef086 100644 --- a/lib/awful/layout/init.lua +++ b/lib/awful/layout/init.lua @@ -172,8 +172,8 @@ function layout.arrange(screen) p.geometries = setmetatable({}, {__mode = "k"}) layout.get(screen).arrange(p) for c, g in pairs(p.geometries) do - g.width = g.width - c.border_width * 2 - useless_gap * 2 - g.height = g.height - c.border_width * 2 - useless_gap * 2 + g.width = math.max(1, g.width - c.border_width * 2 - useless_gap * 2) + g.height = math.max(1, g.height - c.border_width * 2 - useless_gap * 2) g.x = g.x + useless_gap g.y = g.y + useless_gap c:geometry(g) From 7654abcedc4f42a6dabb399d5a5915e0dc69c715 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 18 Apr 2016 01:27:50 -0400 Subject: [PATCH 7/8] layout.tile: Avoid negative geometries --- lib/awful/layout/suit/tile.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/awful/layout/suit/tile.lua b/lib/awful/layout/suit/tile.lua index 802fdce97..fce17e01c 100644 --- a/lib/awful/layout/suit/tile.lua +++ b/lib/awful/layout/suit/tile.lua @@ -171,7 +171,7 @@ local function tile_group(gs, cls, wa, orientation, fact, group) end total_fact = total_fact + fact[i] end - size = math.min(size, available) + size = math.max(1, math.min(size, available)) local coord = wa[y] local used_size = 0 @@ -181,7 +181,7 @@ local function tile_group(gs, cls, wa, orientation, fact, group) local hints = {} local i = c - group.first +1 geom[width] = size - geom[height] = math.floor(unused * fact[i] / total_fact) + geom[height] = math.max(1, math.floor(unused * fact[i] / total_fact)) geom[x] = group.coord geom[y] = coord gs[cls[c]] = geom From bb47aa5861bf0ca9ce9407bd68a0360106e48d42 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sat, 9 Apr 2016 02:57:56 -0400 Subject: [PATCH 8/8] tests: Test all client layouts --- tests/test-awful-layout.lua | 122 ++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tests/test-awful-layout.lua diff --git a/tests/test-awful-layout.lua b/tests/test-awful-layout.lua new file mode 100644 index 000000000..bc8ced7d9 --- /dev/null +++ b/tests/test-awful-layout.lua @@ -0,0 +1,122 @@ +-- This test hit the client layout code paths to see if there is errors. +-- it doesn't check if the layout are correct. + +local awful = require("awful") + +local first_layout = nil + +local t = nil + +local has_spawned = false + +local steps = { + +-- Add enough clients +function(count) + if count <= 1 and not has_spawned then + for _=1, 5 do awful.spawn("xterm") end + has_spawned = true + elseif #client.get() >= 5 then + + first_layout = client.focus:tags()[1].layout + + t = client.focus:tags()[1] + + return true + end +end, + +} + +local function next_layout() + awful.layout.inc(1) + + assert(client.focus:tags()[1].layout ~= first_layout) + + return true +end + +-- Test most properties for each layouts +local common_steps = { + function() + assert(#t:clients() == 5) + + t.master_count = 2 + + return true + end, + function() + t.master_count = 0 + + return true + end, + function() + t.master_count = 6 --more than #client.get(1) + + return true + end, + function() + t.master_count = 1 + + return true + end, + function() + t.column_count = 2 + + return true + end, + function() + t.column_count = 6 --more than #client.get(1) + + return true + end, + function() + t.column_count = 1 + + return true + end, + function() + t.master_fill_policy = t.master_fill_policy == "mwfact" and + "expand" or "mwfact" + + return true + end, + function() + t.master_width_factor = 0.75 + + return true + end, + function() + t.master_width_factor = 0 + + return true + end, + function() + t.master_width_factor = 1 + + return true + end, + function() + t.master_width_factor = 0.5 + + return true + end, + function() + t.gap = t.gap == 0 and 5 or 0 + + return true + end, +} + +local first = false +for _ in ipairs(awful.layout.layouts) do + if not first then + first = true + else + awful.util.table.merge(steps, {next_layout}) + end + + awful.util.table.merge(steps, common_steps) +end + +require("_runner").run_steps(steps)