Move size-hints handling to lua

The C core now completely ignores size hints and let's lua handle them.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2011-03-11 17:13:20 +01:00
parent 4e31c72497
commit eff4474c6d
6 changed files with 129 additions and 113 deletions

View File

@ -287,7 +287,7 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev)
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
} }
if(!client_resize(c, geometry, false)) if(!client_resize(c, geometry))
/* ICCCM 4.1.5 / 4.2.3, if nothing was changed, send an event saying so */ /* ICCCM 4.1.5 / 4.2.3, if nothing was changed, send an event saying so */
xwindow_configure(c->window, geometry, c->border_width); xwindow_configure(c->window, geometry, c->border_width);
} }

123
lib/awful/icccm.lua.in Normal file
View File

@ -0,0 +1,123 @@
---------------------------------------------------------------------------
-- @author Uli Schlachter
-- @copyright 2011 Uli Schlachter
-- @release @AWESOME_VERSION@
---------------------------------------------------------------------------
local client = client
local math = math
--- Implements ICCCM handling.
module("awful.icccm")
-- Make sure we don't get into an endless loop
local size_hints_lock = false
function apply_size_hints(c)
if size_hints_lock then return end
if not c.size_hints_honor then return end
-- Fullscreen clients don't get size hints applied!
if c.fullscreen then return end
size_hints_lock = true
local geom = c:geometry()
local hints = c.size_hints
local basew, baseh
local real_basew, real_baseh = 0, 0
if hints.base_width then
basew, baseh = hints.base_width, hints.base_height
real_basew, real_baseh = basew, baseh
elseif hints.min_width then
-- Base size is substituted with min size if not specified
basew, baseh = hints.min_width, hints.min_height
else
basew, baseh = 0, 0
end
-- Handle the size aspect ratio
if hints.min_aspect_den then
-- Apply the size aspect
if hints.min_aspect_den > 0 and hints.max_aspect_den > 0 and
geom.height > real_baseh and geom.width > real_basew then
-- ICCCM mandates:
-- If a base size is provided along with the aspect ratio fields, the
-- base size should be subtracted from the window size prior to checking
-- that the aspect ratio falls in range. If a base size is not provided,
-- nothing should be subtracted from the window size. (The minimum size
-- is not to be used in place of the base size for this purpose.)
local dx = geom.width - real_basew
local dy = geom.height - real_baseh
local ratio = dx / dy
local min = hints.min_aspect_num / hints.min_aspect_den
local max = hints.max_aspect_num / hints.max_aspect_den
if max > 0 and min > 0 and ratio > 0 then
if ratio < min then
-- dx is lower than allowed, make dy lower to compensate this
-- (+ 0.5 to force proper rounding).
dy = dx / min + 0.5
geom.width = dx + real_basew
geom.height = dy + real_baseh
elseif ratio > max then
-- dx is too high, lower it (+0.5 for proper rounding)
dx = dy * max + 0.5
geom.width = dx + real_basew
geom.height = dy + real_baseh;
end
-- Make sure these are integers
geom.width = math.floor(geom.width)
geom.height = math.floor(geom.height)
end
end
end
-- Handle the minimum size
local minw, minh
if hints.min_width then
minw, minh = hints.min_width, hints.min_height
elseif hints.base_width then
-- min size is substituted with base size if not specified
minw, minh = hints.base_width, hints.base_height
else
minw, minh = 0, 0
end
if minw ~= nil and minw > 0 and geom.width < minw then
geom.width = minw
end
if minh ~= nil and minh > 0 and geom.height < minh then
geom.height = minh
end
-- Handle the maximum size
if hints.max_width ~= nil and hints.max_width > 0 and hints.max_width < geom.width then
geom.width = hints.max_width
end
if hints.max_height ~= nil and hints.max_height > 0 and hints.max_height < geom.height then
geom.height = hints.max_height
end
-- Handle the size increment
if hints.width_inc and hints.width_inc > 0 then
function apply_inc(size, inc, base)
local i = size - base
if i < 0 then i = 0 end
-- Round size down to a multiple of inc, ignoring the base size
return size - math.fmod(i, inc)
end
geom.width = apply_inc(geom.width, hints.width_inc, basew)
geom.height = apply_inc(geom.height, hints.height_inc, baseh)
end
c:geometry(geom)
size_hints_lock = false
end
client.connect_signal("property::width", apply_size_hints)
client.connect_signal("property::height", apply_size_hints)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -22,6 +22,7 @@ require("awful.wibox")
require("awful.startup_notification") require("awful.startup_notification")
require("awful.tooltip") require("awful.tooltip")
require("awful.ewmh") require("awful.ewmh")
require("awful.icccm")
--- AWesome Functions very UsefuL --- AWesome Functions very UsefuL
module("awful") module("awful")

View File

@ -533,110 +533,6 @@ HANDLE_GEOM(height)
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
} }
/** Compute client geometry with respect to its geometry hints.
* \param c The client.
* \param geometry The geometry that the client might receive.
* \return The geometry the client must take respecting its hints.
*/
area_t
client_geometry_hints(client_t *c, area_t geometry)
{
int32_t basew, baseh, minw, minh;
int32_t real_basew = 0, real_baseh = 0;
/* base size is substituted with min size if not specified */
if(c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)
{
basew = c->size_hints.base_width;
baseh = c->size_hints.base_height;
real_basew = basew;
real_baseh = baseh;
}
else if(c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)
{
basew = c->size_hints.min_width;
baseh = c->size_hints.min_height;
}
else
basew = baseh = 0;
/* min size is substituted with base size if not specified */
if(c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)
{
minw = c->size_hints.min_width;
minh = c->size_hints.min_height;
}
else if(c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)
{
minw = c->size_hints.base_width;
minh = c->size_hints.base_height;
}
else
minw = minh = 0;
if(c->size_hints.flags & XCB_SIZE_HINT_P_ASPECT
&& c->size_hints.min_aspect_den > 0
&& c->size_hints.max_aspect_den > 0
&& geometry.height - real_baseh > 0
&& geometry.width - real_basew > 0)
{
/* ICCCM mandates:
* If a base size is provided along with the aspect ratio fields, the
* base size should be subtracted from the window size prior to checking
* that the aspect ratio falls in range. If a base size is not provided,
* nothing should be subtracted from the window size. (The minimum size
* is not to be used in place of the base size for this purpose.) */
double dx = (double) (geometry.width - real_basew);
double dy = (double) (geometry.height - real_baseh);
double min = (double) c->size_hints.min_aspect_num / (double) c->size_hints.min_aspect_den;
double max = (double) c->size_hints.max_aspect_num / (double) c->size_hints.max_aspect_den;
double ratio = dx / dy;
if(max > 0 && min > 0 && ratio > 0)
{
if(ratio < min)
{
/* dx is lower than allowed, make dy lower to compensate this
* (+ 0.5 to force proper rounding). */
dy = dx / min + 0.5;
geometry.width = (int) dx + real_basew;
geometry.height = (int) dy + real_baseh;
}
else if(ratio > max)
{
/* dx is too high, lower it (+0.5 for proper rounding) */
dx = dy * max + 0.5;
geometry.width = (int) dx + real_basew;
geometry.height = (int) dy + real_baseh;
}
}
}
if(minw)
geometry.width = MAX(geometry.width, minw);
if(minh)
geometry.height = MAX(geometry.height, minh);
if(c->size_hints.flags & XCB_SIZE_HINT_P_MAX_SIZE)
{
if(c->size_hints.max_width)
geometry.width = MIN(geometry.width, c->size_hints.max_width);
if(c->size_hints.max_height)
geometry.height = MIN(geometry.height, c->size_hints.max_height);
}
if(c->size_hints.flags & (XCB_SIZE_HINT_P_RESIZE_INC | XCB_SIZE_HINT_BASE_SIZE)
&& c->size_hints.width_inc && c->size_hints.height_inc)
{
uint16_t t1 = geometry.width, t2 = geometry.height;
unsigned_subtract(t1, basew);
unsigned_subtract(t2, baseh);
geometry.width -= t1 % c->size_hints.width_inc;
geometry.height -= t2 % c->size_hints.height_inc;
}
return geometry;
}
/** Resize client window. /** Resize client window.
* The sizes given as parameters are with borders! * The sizes given as parameters are with borders!
* \param c Client to resize. * \param c Client to resize.
@ -645,7 +541,7 @@ client_geometry_hints(client_t *c, area_t geometry)
* \return true if an actual resize occurred. * \return true if an actual resize occurred.
*/ */
bool bool
client_resize(client_t *c, area_t geometry, bool hints) client_resize(client_t *c, area_t geometry)
{ {
area_t area; area_t area;
@ -661,9 +557,6 @@ client_resize(client_t *c, area_t geometry, bool hints)
if(geometry.y + geometry.height < 0) if(geometry.y + geometry.height < 0)
geometry.y = 0; geometry.y = 0;
if(hints && !c->fullscreen)
geometry = client_geometry_hints(c, geometry);
if(geometry.width == 0 || geometry.height == 0) if(geometry.width == 0 || geometry.height == 0)
return false; return false;
@ -1284,7 +1177,7 @@ luaA_client_geometry(lua_State *L)
geometry.height = luaA_getopt_number(L, 2, "height", c->geometry.height); geometry.height = luaA_getopt_number(L, 2, "height", c->geometry.height);
} }
client_resize(c, geometry, c->size_hints_honor); client_resize(c, geometry);
} }
return luaA_pusharea(L, c->geometry); return luaA_pusharea(L, c->geometry);

View File

@ -116,8 +116,7 @@ void client_ban(client_t *);
void client_ban_unfocus(client_t *); void client_ban_unfocus(client_t *);
void client_unban(client_t *); void client_unban(client_t *);
void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, bool); void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, bool);
area_t client_geometry_hints(client_t *, area_t); bool client_resize(client_t *, area_t);
bool client_resize(client_t *, area_t, bool);
void client_unmanage(client_t *, bool); void client_unmanage(client_t *, bool);
void client_kill(client_t *); void client_kill(client_t *);
void client_set_sticky(lua_State *, int, bool); void client_set_sticky(lua_State *, int, bool);

View File

@ -378,7 +378,7 @@ screen_client_moveto(client_t *c, screen_t *new_screen, bool doresize)
new_geometry.y = to.y + to.height - new_geometry.height; new_geometry.y = to.y + to.height - new_geometry.height;
/* move / resize the client */ /* move / resize the client */
client_resize(c, new_geometry, false); client_resize(c, new_geometry);
luaA_object_push(globalconf.L, c); luaA_object_push(globalconf.L, c);
luaA_object_emit_signal(globalconf.L, -1, "property::screen", 0); luaA_object_emit_signal(globalconf.L, -1, "property::screen", 0);
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);