Merge remote-tracking branch 'oof/task-widget-v2' into tag_task_refractor

This commit is contained in:
Gokul Swaminathan 2022-11-21 21:09:06 -08:00
commit c8adfe6a90
1 changed files with 150 additions and 90 deletions

View File

@ -1,30 +1,63 @@
--
-- 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
local awful = require("awful")
local gobject = require("gears.object")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local gmatrix = require("gears.matrix")
local gsurface = require("gears.surface")
local wibox = require("wibox")
local beautiful = require("beautiful")
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local dpi = beautiful.xresources.apply_dpi
local collectgarbage = collectgarbage
local ipairs = ipairs
local pcall = pcall
local type = type
local capi = { tag = tag }
local task_preview = { mt = {} }
local function _get_widget_geometry(_hierarchy, widget)
local width, height = _hierarchy:get_size()
if _hierarchy:get_widget() == widget then
-- Get the extents of this widget in the device space
local x, y, w, h = gmatrix.transform_rectangle(
_hierarchy:get_matrix_to_device(),
0, 0, width, height)
return { x = x, y = y, width = w, height = h, hierarchy = _hierarchy }
end
for _, child in ipairs(_hierarchy:get_children()) do
local ret = _get_widget_geometry(child, widget)
if ret then return ret end
end
end
local function get_widget_geometry(wibox, widget)
return _get_widget_geometry(wibox._drawable._widget_hierarchy, widget)
end
function task_preview:show(c, args)
args = args or {}
args.coords = args.coords or self.coords
args.wibox = args.wibox
args.widget = args.widget
args.offset = args.offset or {}
if not args.coords and args.wibox and args.widget then
args.coords = get_widget_geometry(args.wibox, args.widget)
if args.offset.x ~= nil then
args.coords.x = args.coords.x + args.offset.x
end
if args.offset.y ~= nil then
args.coords.y = args.coords.y + args.offset.y
end
self._private.widget.x = args.coords.x
self._private.widget.y = args.coords.y
end
-- 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
@ -33,9 +66,9 @@ local function draw_widget(
local content = nil
if c.active then
content = gears.surface(c.content)
content = gsurface(c.content)
elseif c.prev_content then
content = gears.surface(c.prev_content)
content = gsurface(c.prev_content)
end
local img = nil
@ -49,8 +82,8 @@ local function draw_widget(
cr:paint()
end
local widget = wibox.widget({
(widget_template or {
local widget = wibox.widget{
(self.widget_template or {
{
{
{
@ -78,37 +111,37 @@ local function draw_widget(
{
id = "image_role",
resize = true,
clip_shape = helpers.shape.rrect(screen_radius),
clip_shape = self.image_shape,
widget = wibox.widget.imagebox,
},
valign = "center",
halign = "center",
widget = wibox.container.place,
},
top = margin * 0.25,
top = self.margin * 0.25,
widget = wibox.container.margin,
},
fill_space = true,
layout = wibox.layout.fixed.vertical,
},
margins = margin,
margins = self.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),
bg = self.bg,
shape_border_width = self.border_width,
shape_border_color = self.border_color,
shape = self.shape,
widget = wibox.container.background,
}),
width = widget_width,
height = widget_height,
width = self.forced_width,
height = self.forced_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
w.image = img -- TODO: copy it with gsurface.xxx or something
end
for _, w in ipairs(widget:get_children_by_id("name_role")) do
@ -119,41 +152,62 @@ local function draw_widget(
w.image = c.icon -- TODO: detect clienticon
end
return widget
self._private.widget.widget = widget
self._private.widget.visible = true
end
local enable = function(opts)
local opts = opts or {}
function task_preview:hide()
self._private.widget.visible = false
self._private.widget.widget = nil
collectgarbage("collect")
end
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
function task_preview:toggle(c, args)
if self._private.widget.visible == true then
self:hide()
else
self:show(c, args)
end
end
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 function new(args)
args = args or {}
local task_preview_box = awful.popup({
type = "dropdown_menu",
args.type = args.type or "dropdown_menu"
args.coords = args.coords or nil
args.placement = args.placement or nil
args.forced_width = args.forced_width or dpi(200)
args.forced_height = args.forced_height or dpi(200)
args.input_passthrough = args.input_passthrough or false
args.margin = args.margin or beautiful.task_preview_widget_margin or dpi(0)
args.shape = args.shape or beautiful.task_preview_widget_shape or nil
args.bg = args.bg or beautiful.task_preview_widget_bg or "#000000"
args.border_width = args.border_width or beautiful.task_preview_widget_border_width or nil
args.border_color = args.border_color or beautiful.task_preview_widget_border_color or "#ffffff"
args.image_shape = args.image_shape or beautiful.task_preview_image_shape or nil
local ret = gobject{}
ret._private = {}
gtable.crush(ret, task_preview)
gtable.crush(ret, args)
ret._private.widget = awful.popup
{
type = ret.type,
visible = false,
ontop = true,
placement = placement_fn,
widget = wibox.container.background, -- A dummy widget to make awful.popup not scream
input_passthrough = true,
placement = ret.placement,
input_passthrough = ret.input_passthrough,
bg = "#00000000",
})
widget = wibox.container.background, -- A dummy widget to make awful.popup not scream
}
tag.connect_signal("property::selected", function(t)
capi.tag.connect_signal("property::selected", function(t)
-- Awesome switches up tags on startup really fast it seems, probably depends on what rules you have set
-- which can cause the c.content to not show the correct image
gears.timer
{
gtimer {
timeout = 0.1,
call_now = false,
autostart = true,
@ -161,39 +215,45 @@ local enable = function(opts)
callback = function()
if t.selected == true then
for _, c in ipairs(t:clients()) do
c.prev_content = gears.surface.duplicate_surface(c.content)
c.prev_content = gsurface.duplicate_surface(c.content)
end
end
end
}
end)
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
return ret
if not placement_fn then
task_preview_box.x = s.geometry.x + widget_x
task_preview_box.y = s.geometry.y + widget_y
end
-- 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
task_preview_box.visible = v
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, draw_widget = draw_widget }
function task_preview.mt:__call(...)
return new(...)
end
return setmetatable(task_preview, task_preview.mt)