Move size hints handling back into C (FS#1117)
Having this in lua means that size hints are only applied after the client got resized. The bad side effect of this is some flickering if awesome is being slow. And apparently, it is slow for way too many people... Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
5365dfdb79
commit
23b30be106
2
event.c
2
event.c
|
@ -335,7 +335,7 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev)
|
|||
lua_pop(globalconf.L, 1);
|
||||
}
|
||||
|
||||
if(!client_resize(c, geometry))
|
||||
if(!client_resize(c, geometry, false))
|
||||
/* ICCCM 4.1.5 / 4.2.3, if nothing was changed, send an event saying so */
|
||||
client_send_configure(c);
|
||||
}
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2011 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local client = client
|
||||
local math = math
|
||||
|
||||
--- Implements ICCCM handling.
|
||||
-- awful.icccm
|
||||
|
||||
-- Make sure we don't get into an endless loop
|
||||
local size_hints_lock = false
|
||||
|
||||
local function get_titlebar_size(c)
|
||||
local res, _ = {}
|
||||
_, res.top = c:titlebar_top()
|
||||
_, res.right = c:titlebar_right()
|
||||
_, res.bottom = c:titlebar_bottom()
|
||||
_, res.left = c:titlebar_left()
|
||||
|
||||
res.x = res.left
|
||||
res.y = res.top
|
||||
res.width = res.left + res.right
|
||||
res.height = res.top + res.bottom
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
local 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 titlebar = get_titlebar_size(c)
|
||||
|
||||
-- Apply size hints to the client size without titlebars
|
||||
geom.width = geom.width - titlebar.width
|
||||
geom.height = geom.height - titlebar.height
|
||||
|
||||
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
|
||||
local 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({ width = geom.width + titlebar.width, height = geom.height + titlebar.height })
|
||||
|
||||
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:textwidth=80
|
|
@ -28,7 +28,6 @@ return
|
|||
startup_notification = require("awful.startup_notification");
|
||||
tooltip = require("awful.tooltip");
|
||||
ewmh = require("awful.ewmh");
|
||||
icccm = require("awful.icccm");
|
||||
titlebar = require("awful.titlebar");
|
||||
}
|
||||
|
||||
|
|
151
objects/client.c
151
objects/client.c
|
@ -585,29 +585,154 @@ HANDLE_GEOM(height)
|
|||
lua_pop(globalconf.L, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
client_remove_titlebar_geometry(client_t *c, area_t *geometry)
|
||||
{
|
||||
geometry->x += c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||
geometry->y += c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||
geometry->width -= c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||
geometry->width -= c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
|
||||
geometry->height -= c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||
geometry->height -= c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
||||
}
|
||||
|
||||
static void
|
||||
client_add_titlebar_geometry(client_t *c, area_t *geometry)
|
||||
{
|
||||
geometry->x -= c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||
geometry->y -= c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||
geometry->width += c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||
geometry->width += c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
|
||||
geometry->height += c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||
geometry->height += c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
||||
}
|
||||
|
||||
/** Send a synthetic configure event to a window.
|
||||
*/
|
||||
void
|
||||
client_send_configure(client_t *c)
|
||||
{
|
||||
area_t geometry = c->geometry;
|
||||
geometry.x += c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||
geometry.y += c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||
geometry.width -= c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||
geometry.width -= c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
|
||||
geometry.height -= c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||
geometry.height -= c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
||||
|
||||
client_remove_titlebar_geometry(c, &geometry);
|
||||
xwindow_configure(c->window, geometry, c->border_width);
|
||||
}
|
||||
|
||||
/** Apply size hints to the client's new geometry.
|
||||
*/
|
||||
static area_t
|
||||
client_apply_size_hints(client_t *c, area_t geometry)
|
||||
{
|
||||
int32_t minw = 0, minh = 0;
|
||||
int32_t basew = 0, baseh = 0, real_basew = 0, real_baseh = 0;
|
||||
|
||||
if (c->fullscreen)
|
||||
return geometry;
|
||||
|
||||
/* Size hints are applied to the window without any decoration */
|
||||
client_remove_titlebar_geometry(c, &geometry);
|
||||
|
||||
if(c->size_hints.flags & XCB_ICCCM_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_ICCCM_SIZE_HINT_P_MIN_SIZE)
|
||||
{
|
||||
/* base size is substituted with min size if not specified */
|
||||
basew = c->size_hints.min_width;
|
||||
baseh = c->size_hints.min_height;
|
||||
}
|
||||
|
||||
if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)
|
||||
{
|
||||
minw = c->size_hints.min_width;
|
||||
minh = c->size_hints.min_height;
|
||||
}
|
||||
else if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_SIZE)
|
||||
{
|
||||
/* min size is substituted with base size if not specified */
|
||||
minw = c->size_hints.base_width;
|
||||
minh = c->size_hints.base_height;
|
||||
}
|
||||
|
||||
/* Handle the size aspect ratio */
|
||||
if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_ASPECT
|
||||
&& c->size_hints.min_aspect_den > 0
|
||||
&& c->size_hints.max_aspect_den > 0
|
||||
&& geometry.height > real_baseh
|
||||
&& geometry.width > real_basew)
|
||||
{
|
||||
/* 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 = geometry.width - real_basew;
|
||||
double dy = geometry.height - real_baseh;
|
||||
double ratio = dx / dy;
|
||||
double min = c->size_hints.min_aspect_num / (double) c->size_hints.min_aspect_den;
|
||||
double max = c->size_hints.max_aspect_num / (double) c->size_hints.max_aspect_den;
|
||||
|
||||
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 = dx + real_basew;
|
||||
geometry.height = 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 = dx + real_basew;
|
||||
geometry.height = dy + real_baseh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the minimum size */
|
||||
geometry.width = MAX(geometry.width, minw);
|
||||
geometry.height = MAX(geometry.height, minh);
|
||||
|
||||
/* Handle the maximum size */
|
||||
if(c->size_hints.flags & XCB_ICCCM_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);
|
||||
}
|
||||
|
||||
/* Handle the size increment */
|
||||
if(c->size_hints.flags & (XCB_ICCCM_SIZE_HINT_P_RESIZE_INC | XCB_ICCCM_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;
|
||||
}
|
||||
|
||||
client_add_titlebar_geometry(c, &geometry);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
static void
|
||||
client_resize_do(client_t *c, area_t geometry, bool force_notice)
|
||||
client_resize_do(client_t *c, area_t geometry, bool force_notice, bool honor_hints)
|
||||
{
|
||||
bool send_notice = force_notice;
|
||||
bool hide_titlebars = c->fullscreen;
|
||||
screen_t *new_screen = screen_getbycoord(geometry.x, geometry.y);
|
||||
|
||||
if (honor_hints)
|
||||
geometry = client_apply_size_hints(c, geometry);
|
||||
|
||||
if(c->geometry.width == geometry.width
|
||||
&& c->geometry.height == geometry.height)
|
||||
send_notice = true;
|
||||
|
@ -710,11 +835,11 @@ client_resize_do(client_t *c, area_t geometry, bool force_notice)
|
|||
* The sizes given as parameters are with borders!
|
||||
* \param c Client to resize.
|
||||
* \param geometry New window geometry.
|
||||
* \param hints Use size hints.
|
||||
* \param honor_hints Use size hints.
|
||||
* \return true if an actual resize occurred.
|
||||
*/
|
||||
bool
|
||||
client_resize(client_t *c, area_t geometry)
|
||||
client_resize(client_t *c, area_t geometry, bool honor_hints)
|
||||
{
|
||||
area_t area;
|
||||
|
||||
|
@ -743,7 +868,7 @@ client_resize(client_t *c, area_t geometry)
|
|||
|| c->geometry.width != geometry.width
|
||||
|| c->geometry.height != geometry.height)
|
||||
{
|
||||
client_resize_do(c, geometry, false);
|
||||
client_resize_do(c, geometry, false, honor_hints);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -842,7 +967,7 @@ client_set_fullscreen(lua_State *L, int cidx, bool s)
|
|||
luaA_object_emit_signal(L, abs_cidx, "request::fullscreen", 1);
|
||||
luaA_object_emit_signal(L, abs_cidx, "property::fullscreen", 0);
|
||||
/* Force a client resize, so that titlebars get shown/hidden */
|
||||
client_resize_do(c, c->geometry, true);
|
||||
client_resize_do(c, c->geometry, true, false);
|
||||
stack_windows();
|
||||
}
|
||||
}
|
||||
|
@ -1445,7 +1570,7 @@ titlebar_resize(client_t *c, client_titlebar_t bar, int size)
|
|||
}
|
||||
|
||||
c->titlebar[bar].size = size;
|
||||
client_resize_do(c, geometry, true);
|
||||
client_resize_do(c, geometry, true, false);
|
||||
}
|
||||
|
||||
#define HANDLE_TITLEBAR(name, index) \
|
||||
|
@ -1501,7 +1626,7 @@ luaA_client_geometry(lua_State *L)
|
|||
geometry.height = luaA_getopt_number(L, 2, "height", c->geometry.height);
|
||||
}
|
||||
|
||||
client_resize(c, geometry);
|
||||
client_resize(c, geometry, true);
|
||||
}
|
||||
|
||||
return luaA_pusharea(L, c->geometry);
|
||||
|
|
|
@ -141,7 +141,7 @@ void client_ban(client_t *);
|
|||
void client_ban_unfocus(client_t *);
|
||||
void client_unban(client_t *);
|
||||
void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, bool);
|
||||
bool client_resize(client_t *, area_t);
|
||||
bool client_resize(client_t *, area_t, bool);
|
||||
void client_unmanage(client_t *, bool);
|
||||
void client_kill(client_t *);
|
||||
void client_set_sticky(lua_State *, int, bool);
|
||||
|
|
2
screen.c
2
screen.c
|
@ -376,7 +376,7 @@ screen_client_moveto(client_t *c, screen_t *new_screen, bool doresize)
|
|||
new_geometry.y = to.y + to.height - new_geometry.height;
|
||||
|
||||
/* move / resize the client */
|
||||
client_resize(c, new_geometry);
|
||||
client_resize(c, new_geometry, false);
|
||||
luaA_object_push(globalconf.L, c);
|
||||
luaA_object_emit_signal(globalconf.L, -1, "property::screen", 0);
|
||||
lua_pop(globalconf.L, 1);
|
||||
|
|
Loading…
Reference in New Issue