diff --git a/lib/wibox/init.lua b/lib/wibox/init.lua index f90284ac..aa027bcb 100644 --- a/lib/wibox/init.lua +++ b/lib/wibox/init.lua @@ -63,6 +63,37 @@ function wibox:find_widgets(x, y) return self._drawable:find_widgets(x, y) end +--- Create a widget that reflects the current state of this wibox. +-- @treturn widget A new widget. +function wibox:to_widget() + local bw = self.border_width or beautiful.border_width or 0 + return wibox.widget { + { + self:get_widget(), + margins = bw, + widget = wibox.container.margin + }, + bg = self.bg or beautiful.bg_normal or "#ffffff", + fg = self.fg or beautiful.fg_normal or "#000000", + shape_border_color = self.border_color or beautiful.border_color or "#000000", + shape_border_width = bw*2, + shape_clip = true, + shape = self._shape, + forced_width = self:geometry().width + 2*bw, + forced_height = self:geometry().height + 2*bw, + widget = wibox.container.background + } +end + +--- Save a screenshot of the wibox to `path`. +-- @tparam string path The path. +-- @tparam[opt=nil] table context A widget context. +function wibox:save_to_svg(path, context) + wibox.widget.draw_to_svg_file( + self:to_widget(), path, self:geometry().width, self:geometry().height, context + ) +end + function wibox:_apply_shape() local shape = self._shape diff --git a/tests/examples/awful/template.lua b/tests/examples/awful/template.lua index 9e45fa48..52ffc0fc 100644 --- a/tests/examples/awful/template.lua +++ b/tests/examples/awful/template.lua @@ -2,12 +2,11 @@ local file_path, image_path = ... require("_common_template")(...) local cairo = require("lgi").cairo -local pango = require("lgi").Pango -local pangocairo = require("lgi").PangoCairo -local color = require( "gears.color" ) -local shape = require( "gears.shape" ) -local beautiful = require( "beautiful" ) +local color = require( "gears.color" ) +local shape = require( "gears.shape" ) +local beautiful = require( "beautiful" ) +local wibox = require( "wibox" ) -- Run the test local args = loadfile(file_path)() or {} @@ -17,19 +16,6 @@ local img = cairo.SvgSurface.create(image_path..".svg", screen._get_extents() ) local cr = cairo.Context(img) -local pango_crx = pangocairo.font_map_get_default():create_context() -local pl = pango.Layout.new(pango_crx) - --- Draw some text inside of the geometry -local function draw_label(geo, text) - cr:save() - cr:set_source(color(beautiful.fg_normal)) - cr:translate(geo.x, geo.y) - pl.text = text - cr:show_layout(pl) - cr:restore() -end - -- Draw a mouse cursor at [x,y] local function draw_mouse(x, y) cr:move_to(x, y) @@ -66,22 +52,125 @@ end cr:set_line_width(beautiful.border_width) cr:set_source(color(beautiful.border_color)) + + +local rect = {x1 = 0 ,y1 = 0 , x2 = 0 , y2 = 0} + +-- Get the region with wiboxes +for _, obj in ipairs {drawin, client} do + for _, d in ipairs(obj.get()) do + local w = d.get_wibox and d:get_wibox() or d + if w and w.geometry then + local geo = w:geometry() + rect.x1 = math.min(rect.x1, geo.x ) + rect.y1 = math.min(rect.y1, geo.y ) + rect.x2 = math.max(rect.x2, geo.x + geo.width + 2*(w.border_width or 0)) + rect.y2 = math.max(rect.y2, geo.y + geo.height + 2*(w.border_width or 0)) + end + end +end + +local total_area = wibox.layout { + forced_width = rect.x2, + forced_height = rect.y2, + layout = wibox.layout.manual, +} + +local function wrap_titlebar(tb, width, height) + return wibox.widget { + tb.drawable.widget, + bg = tb.args.bg_normal, + fg = tb.args.fg_normal, + forced_width = width, + forced_height = height, + widget = wibox.container.background + } +end + +local function client_widget(c, col, label) + local geo = c:geometry() + local bw = c.border_width or beautiful.border_width or 0 + + local l = wibox.layout.align.vertical() + l.fill_space = true + + local tbs = c.titlebars or {} + + local map = { + top = "set_first", + left = "set_first", + bottom = "set_third", + right = "set_third", + } + + for _, position in ipairs{"top", "bottom"} do + local tb = tbs[position] + if tb then + l[map[position]](l, wrap_titlebar(tb, c:geometry().width, tb.args.height or 16)) + end + end + + for _, position in ipairs{"left", "right"} do + local tb = tbs[position] + if tb then + l[map[position]](l, wrap_titlebar(tb, tb.args.width or 16, c:geometry().height)) + end + end + + local l2 = wibox.layout.align.horizontal() + l2.fill_space = true + l:set_second(l2) + l.forced_width = c.width + l.forced_height = c.height + + return wibox.widget { + { + { + l, + margins = bw + 1, -- +1 because the the SVG AA + layout = wibox.container.margin + }, + { + text = label or "", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + layout = wibox.layout.stack + }, + shape_border_width = bw*2, + shape_border_color = beautiful.border_color, + shape_clip = true, + fg = beautiful.fg_normal or "#000000", + bg = col, + forced_width = geo.width + 2*bw, + forced_height = geo.height + 2*bw, + shape = function(cr2, w, h) + return shape.rounded_rect(cr2, w, h, args.radius or 5) + end, + + widget = wibox.container.background, + } +end + +-- Add all wiboxes +for _, d in ipairs(drawin.get()) do + local w = d.get_wibox and d:get_wibox() or nil + if w then + local geo = w:geometry() + total_area:add_at(w:to_widget(), {x = geo.x, y = geo.y}) + end +end + -- Loop each clients geometry history and paint it for _, c in ipairs(client.get()) do local pgeo = nil for _, geo in ipairs(c._old_geo) do if not geo._hide then - cr:save() - cr:translate(geo.x, geo.y) - shape.rounded_rect(cr, geo.width, geo.height, args.radius or 5) - cr:stroke_preserve() - cr:set_source(color(c.color or geo._color or beautiful.bg_normal)) - cr:fill() - cr:restore() - - if geo._label then - draw_label(geo, geo._label) - end + total_area:add_at( + client_widget(c, c.color or geo._color or beautiful.bg_normal, geo._label), + {x=geo.x, y=geo.y} + ) end -- Draw lines between the old and new corners @@ -115,6 +204,11 @@ for _, c in ipairs(client.get()) do end end +-- Draw the wiboxes/clients on top of the screen +wibox.widget.draw_to_cairo_context( + total_area, cr, screen._get_extents() +) + cr:set_source_rgba(1,0,0,1) cr:set_dash({1,1},1)