bling/widget/task_preview.lua

171 lines
5.4 KiB
Lua

--
-- Provides:
-- bling::task_preview::visibility
-- s (screen)
-- v (boolean)
-- c (client)
--
local awful = require("awful")
local wibox = require("wibox")
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local gears = require("gears")
local beautiful = require("beautiful")
local dpi = beautiful.xresources.apply_dpi
local cairo = require("lgi").cairo
-- TODO: rename structure to something better?
local function draw_widget(
c,
widget_template,
screen_radius,
widget_bg,
widget_border_color,
widget_border_width,
margin,
widget_width,
widget_height
)
if not pcall(function()
return type(c.content)
end) then
return
end
local content = gears.surface(c.content)
local cr = cairo.Context(content)
local x, y, w, h = cr:clip_extents()
local img = cairo.ImageSurface.create(cairo.Format.ARGB32, w - x, h - y)
cr = cairo.Context(img)
cr:set_source_surface(content, 0, 0)
cr.operator = cairo.Operator.SOURCE
cr:paint()
local widget = wibox.widget({
(widget_template or {
{
{
{
{
id = "icon_role",
resize = true,
forced_height = dpi(20),
forced_width = dpi(20),
widget = wibox.widget.imagebox,
},
{
{
id = "name_role",
align = "center",
widget = wibox.widget.textbox,
},
left = dpi(4),
right = dpi(4),
widget = wibox.container.margin,
},
layout = wibox.layout.align.horizontal,
},
{
{
{
id = "image_role",
resize = true,
clip_shape = helpers.shape.rrect(screen_radius),
widget = wibox.widget.imagebox,
},
valign = "center",
halign = "center",
widget = wibox.container.place,
},
top = margin * 0.25,
widget = wibox.container.margin,
},
fill_space = true,
layout = wibox.layout.fixed.vertical,
},
margins = margin,
widget = wibox.container.margin,
},
bg = widget_bg,
shape_border_width = widget_border_width,
shape_border_color = widget_border_color,
shape = helpers.shape.rrect(screen_radius),
widget = wibox.container.background,
}),
width = widget_width,
height = widget_height,
widget = wibox.container.constraint,
})
-- TODO: have something like a create callback here?
for _, w in ipairs(widget:get_children_by_id("image_role")) do
w.image = img -- TODO: copy it with gears.surface.xxx or something
end
for _, w in ipairs(widget:get_children_by_id("name_role")) do
w.text = c.name
end
for _, w in ipairs(widget:get_children_by_id("icon_role")) do
w.image = c.icon -- TODO: detect clienticon
end
return widget
end
local enable = function(opts)
local opts = opts or {}
local widget_x = opts.x or dpi(20)
local widget_y = opts.y or dpi(20)
local widget_height = opts.height or dpi(200)
local widget_width = opts.width or dpi(200)
local placement_fn = opts.placement_fn or nil
local margin = beautiful.task_preview_widget_margin or dpi(0)
local screen_radius = beautiful.task_preview_widget_border_radius or dpi(0)
local widget_bg = beautiful.task_preview_widget_bg or "#000000"
local widget_border_color = beautiful.task_preview_widget_border_color
or "#ffffff"
local widget_border_width = beautiful.task_preview_widget_border_width
or dpi(3)
local task_preview_box = awful.popup({
type = "dropdown_menu",
visible = false,
ontop = true,
placement = placement_fn,
widget = wibox.container.background, -- A dummy widget to make awful.popup not scream
input_passthrough = true,
bg = "#00000000",
})
awesome.connect_signal("bling::task_preview::visibility", function(s, v, c)
if v then
-- Update task preview contents
task_preview_box.widget = draw_widget(
c,
opts.structure,
screen_radius,
widget_bg,
widget_border_color,
widget_border_width,
margin,
widget_width,
widget_height
)
else
task_preview_box.widget = nil
collectgarbage("collect")
end
if not placement_fn then
task_preview_box.x = s.geometry.x + widget_x
task_preview_box.y = s.geometry.y + widget_y
end
task_preview_box.visible = v
end)
end
return { enable = enable }