awesome/lib/awful/icccm.lua.in

124 lines
4.4 KiB
Lua

---------------------------------------------------------------------------
-- @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:textwidth=80