Merge pull request #1198 from psychon/wibox-shape

Wibox: Add gears.shape support
This commit is contained in:
Emmanuel Lepage Vallée 2017-01-26 05:30:42 -05:00 committed by GitHub
commit 5a914b3496
2 changed files with 94 additions and 0 deletions

View File

@ -17,6 +17,7 @@ local object = require("gears.object")
local grect = require("gears.geometry").rectangle local grect = require("gears.geometry").rectangle
local beautiful = require("beautiful") local beautiful = require("beautiful")
local base = require("wibox.widget.base") local base = require("wibox.widget.base")
local cairo = require("lgi").cairo
--- This provides widget box windows. Every wibox can also be used as if it were --- This provides widget box windows. Every wibox can also be used as if it were
-- a drawin. All drawin functions and properties are also available on wiboxes! -- a drawin. All drawin functions and properties are also available on wiboxes!
@ -61,6 +62,63 @@ function wibox:find_widgets(x, y)
return self._drawable:find_widgets(x, y) return self._drawable:find_widgets(x, y)
end end
function wibox:_apply_shape()
local shape = self._shape
if not shape then
self.shape_bounding = nil
self.shape_clip = nil
return
end
local geo = self:geometry()
local bw = self.border_width
-- First handle the bounding shape (things including the border)
local img = cairo.ImageSurface(cairo.Format.A1, geo.width + 2*bw, geo.height + 2*bw)
local cr = cairo.Context(img)
-- We just draw the shape in its full size
shape(cr, geo.width + 2*bw, geo.height + 2*bw)
cr:set_operator(cairo.Operator.SOURCE)
cr:fill()
self.shape_bounding = img._native
img:finish()
-- Now handle the clip shape (things excluding the border)
img = cairo.ImageSurface(cairo.Format.A1, geo.width, geo.height)
cr = cairo.Context(img)
-- We give the shape the same arguments as for the bounding shape and draw
-- it in its full size (the translate is to compensate for the smaller
-- surface)
cr:translate(-bw, -bw)
shape(cr, geo.width + 2*bw, geo.height + 2*bw)
cr:set_operator(cairo.Operator.SOURCE)
cr:fill_preserve()
-- Now we remove an area of width 'bw' again around the shape (We use 2*bw
-- since half of that is on the outside and only half on the inside)
cr:set_source_rgba(0, 0, 0, 0)
cr:set_line_width(2*bw)
cr:stroke()
self.shape_clip = img._native
img:finish()
end
--- Set the wibox shape.
-- @property shape
-- @tparam gears.shape A gears.shape compatible function.
-- @see gears.shape
function wibox:set_shape(shape)
self._shape = shape
self:_apply_shape()
end
function wibox:get_shape()
return self._shape
end
function wibox:get_screen() function wibox:get_screen()
if self.screen_assigned and self.screen_assigned.valid then if self.screen_assigned and self.screen_assigned.valid then
return self.screen_assigned return self.screen_assigned
@ -196,6 +254,9 @@ local function new(args)
-- Make sure the wibox is drawn at least once -- Make sure the wibox is drawn at least once
ret.draw() ret.draw()
ret:connect_signal("property::geometry", ret._apply_shape)
ret:connect_signal("property::border_width", ret._apply_shape)
-- If a value is not found, look in the drawin -- If a value is not found, look in the drawin
setmetatable(ret, { setmetatable(ret, {
__index = function(self, k) __index = function(self, k)
@ -229,6 +290,8 @@ local function new(args)
ret:set_screen ( args.screen ) ret:set_screen ( args.screen )
end end
ret.shape = args.shape
return ret return ret
end end

View File

@ -0,0 +1,31 @@
-- A quick-and-dirty test of wibox shapes ("Does it error out?")
local runner = require("_runner")
local wibox = require("wibox")
local shape = require("gears.shape")
local was_drawn
local widget = wibox.widget.base.make_widget()
function widget.draw()
was_drawn = true
end
local wb = wibox {
shape = shape.powerline,
widget = widget,
border_width = 42,
}
wb:geometry(screen[1].geometry)
wb.visible = true
runner.run_steps({
function()
assert(wb.shape == shape.powerline)
assert(wb.shape_bounding) -- This is a memory leak! Don't copy!
if was_drawn then
return true
end
end
})
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80