From e998e3fe207e22050087ba93821294f80d3a52e2 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Mon, 14 Apr 2014 10:04:56 +0200 Subject: [PATCH] awful.client.shape: Import client shape handling (FS#1051) This new awful module reacts to shapes that a client sets on itself and sets the shape of awesome's frame window to match. This way, xeyes really gets transparent parts again. Signed-off-by: Uli Schlachter --- lib/awful/client.lua.in | 1 + lib/awful/client/shape.lua.in | 89 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 lib/awful/client/shape.lua.in diff --git a/lib/awful/client.lua.in b/lib/awful/client.lua.in index f72e9be1..11d5953f 100644 --- a/lib/awful/client.lua.in +++ b/lib/awful/client.lua.in @@ -43,6 +43,7 @@ client.swap = {} client.floating = {} client.dockable = {} client.property = {} +client.shape = require("awful.client.shape") --- -- Jump to the given client. Takes care of focussing the screen, the right tag, diff --git a/lib/awful/client/shape.lua.in b/lib/awful/client/shape.lua.in new file mode 100644 index 00000000..5fa8a954 --- /dev/null +++ b/lib/awful/client/shape.lua.in @@ -0,0 +1,89 @@ +--------------------------------------------------------------------------- +-- @author Uli Schlachter <psychon@znc.in> +-- @copyright 2014 Uli Schlachter +-- @release @AWESOME_VERSION@ +--------------------------------------------------------------------------- + +-- Grab environment we need +local surface = require("gears.surface") +local cairo = require("lgi").cairo +local capi = +{ + client = client, +} + +--- Handle client shapes. +-- awful.client.shape +local shape = {} +shape.update = {} + +--- Get one of a client's shapes and transform it to include window decorations +-- @param c The client whose shape should be retrieved +-- @param shape Either "bounding" or "clip" +function shape.get_transformed(c, shape) + local border = shape == "bounding" and c.border_width or 0 + local shape = surface(c["client_shape_" .. shape]) + if not shape then return end + + -- Get information about various sizes on the client + local geom = c:geometry() + local _, t = c:titlebar_top() + local _, b = c:titlebar_bottom() + local _, l = c:titlebar_left() + local _, r = c:titlebar_right() + + -- Figure out the size of the shape that we need + local img_width = geom.width + 2*border + local img_height = geom.height + 2*border + local result = cairo.ImageSurface(cairo.Format.A1, img_width, img_height) + local cr = cairo.Context(result) + + -- Fill everything (this paints the titlebars and border) + cr:paint() + + -- Draw the client's shape in the middle + cr:set_operator(cairo.Operator.SOURCE) + cr:set_source_surface(shape, border + l, border + t) + cr:rectangle(border + l, border + t, geom.width - l - r, geom.height - t - b) + cr:fill() + + return result +end + +--- Update a client's bounding shape from the shape the client set itself +-- @param c The client to act on +function shape.update.bounding(c) + local res = shape.get_transformed(c, "bounding") + c.shape_bounding = res and res._native + -- Free memory + if res then + res:finish() + end +end + +--- Update a client's clip shape from the shape the client set itself +-- @param c The client to act on +function shape.update.clip(c) + local res = shape.get_transformed(c, "clip") + c.shape_clip = res and res._native + -- Free memory + if res then + res:finish() + end +end + +--- Update all of a client's shapes from the shapes the client set itself +-- @param c The client to act on +function shape.update.all(c) + shape.update.bounding(c) + shape.update.clip(c) +end + +capi.client.connect_signal("property::shape_client_bounding", shape.update.bounding) +capi.client.connect_signal("property::shape_client_clip", shape.update.clip) +capi.client.connect_signal("property::width", shape.update.all) +capi.client.connect_signal("property::height", shape.update.all) + +return shape + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80