I did something, Idk.

This commit is contained in:
Gokul Swaminathan 2023-04-03 16:55:16 -07:00
parent 49e7c07657
commit 0a40308f90
2 changed files with 195 additions and 189 deletions

View File

@ -1,87 +1,127 @@
-- local cairo = require("lgi").cairo
-- Provides:
-- bling::tag_preview::update -- first line is the signal
-- t (tag) -- indented lines are function parameters
-- bling::tag_preview::visibility
-- s (screen)
-- v (boolean)
--
local awful = require("awful") local awful = require("awful")
local wibox = require("wibox") local wibox = require("wibox")
local helpers = require(tostring(...):match(".*bling") .. ".helpers") local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local gears = require("gears") 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 beautiful = require("beautiful") local beautiful = require("beautiful")
local dpi = beautiful.xresources.apply_dpi local dpi = beautiful.xresources.apply_dpi
local cairo = require("lgi").cairo local collectgarbage = collectgarbage
local ipairs = ipairs
local pcall = pcall
local capi = {client = client, tag = tag}
local function draw_widget( local tag_preview = {mt = {}}
t,
tag_preview_image,
scale,
screen_radius,
client_radius,
client_opacity,
client_bg,
client_border_color,
client_border_width,
widget_bg,
widget_border_color,
widget_border_width,
geo,
margin,
background_image
)
local client_list = wibox.layout.manual()
client_list.forced_height = geo.height
client_list.forced_width = geo.width
local tag_screen = t.screen
for i, c in ipairs(t:clients()) do
if not c.hidden and not c.minimized then
local function _get_widget_geometry(_hierarchy, widget)
local img_box = wibox.widget ({ local width, height = _hierarchy:get_size()
resize = true, if _hierarchy:get_widget() == widget then
forced_height = 100 * scale, -- Get the extents of this widget in the device space
forced_width = 100 * scale, local x, y, w, h = gmatrix.transform_rectangle(
widget = wibox.widget.imagebox, _hierarchy:get_matrix_to_device(), 0, 0, width,
}) height)
return {x = x, y = y, width = w, height = h, hierarchy = _hierarchy}
-- If fails to set image, fallback to a awesome icon
if not pcall(function() img_box.image = gears.surface.load(c.icon) end) then
img_box.image = beautiful.theme_assets.awesome_icon (24, "#222222", "#fafafa")
end end
if tag_preview_image then 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 tag_preview:update(t)
local args = self
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
local geo = t.screen:get_bounding_geometry({
honor_padding = args.padding,
honor_workarea = args.work_area
})
self._private.widget.maximum_width =
args.scale * geo.width + args.margin * 2
self._private.widget.maximum_height =
args.scale * geo.height + args.margin * 2
local client_list = wibox.layout.manual()
client_list.forced_height = geo.height
client_list.forced_width = geo.widget
for _, c in ipairs(t:clients()) do
if not c.hidden and not c.minimized then
local img_box = wibox.widget {
resize = true,
forced_height = 100 * args.scale,
forced_width = 100 * args.scale,
widget = wibox.widget.imagebox
}
-- If fails to set image, fallback to a awesome icon
if args.client_icon then
if not pcall(function()
img_box.image = gsurface.load(c.icon)
end) then
img_box.image = beautiful.theme_assets.awesome_icon(24,
"#222222",
"#fafafa")
end
end
if args.tag_preview_image then
if c.prev_content or t.selected then if c.prev_content or t.selected then
local content local content = nil
if t.selected then if t.selected then
content = gears.surface(c.content) content = gsurface(c.content)
else else
content = gears.surface(c.prev_content) content = gsurface(c.prev_content)
end end
local cr = cairo.Context(content) local cr = cairo.Context(content)
local x, y, w, h = cr:clip_extents() local x, y, w, h = cr:clip_extents()
local img = cairo.ImageSurface.create( local img = cairo.ImageSurface.create(cairo.Format.ARGB32,
cairo.Format.ARGB32, w - x, h - y)
w - x,
h - y
)
cr = cairo.Context(img) cr = cairo.Context(img)
cr:set_source_surface(content, 0, 0) cr:set_source_surface(content, 0, 0)
cr.operator = cairo.Operator.SOURCE cr.operator = cairo.Operator.SOURCE
cr:paint() cr:paint()
img_box = wibox.widget({ img_box = wibox.widget({
image = gears.surface.load(img), image = gsurface.load(img),
resize = true, resize = true,
opacity = client_opacity, opacity = args.client_opacity,
forced_height = math.floor(c.height * scale), forced_height = c.height * args.scale,
forced_width = math.floor(c.width * scale), forced_width = c.width * args.scale,
widget = wibox.widget.imagebox, widget = wibox.widget.imagebox
}) })
end end
end end
local c_bg = args.client_bg
if c == capi.client.focus then
c_bg = beautiful.xcolor4
end
local client_box = wibox.widget({ local client_box = wibox.widget({
{ {
nil, nil,
@ -90,101 +130,105 @@ local function draw_widget(
img_box, img_box,
nil, nil,
expand = "outside", expand = "outside",
layout = wibox.layout.align.horizontal, layout = wibox.layout.align.horizontal
}, },
nil, nil,
expand = "outside", expand = "outside",
widget = wibox.layout.align.vertical, widget = wibox.layout.align.vertical
}, },
forced_height = math.floor(c.height * scale), forced_height = math.floor(c.height * args.scale),
forced_width = math.floor(c.width * scale), forced_width = math.floor(c.width * args.scale),
bg = client_bg, bg = c_bg,
shape_border_color = client_border_color, shape_border_color = args.client_border_color,
shape_border_width = client_border_width, shape_border_width = args.client_border_width,
shape = helpers.shape.rrect(client_radius), shape = helpers.shape.rrect(args.client_border_radius),
widget = wibox.container.background, widget = wibox.container.background
}) })
client_box.point = { client_box.point = {
x = math.floor((c.x - geo.x) * scale), x = math.floor((c.x - geo.x) * args.scale),
y = math.floor((c.y - geo.y) * scale), y = math.floor((c.y - geo.y) * args.scale)
} }
client_list:add(client_box) client_list:add(client_box)
end end
end end
return wibox.widget { local w = wibox.widget {
{
background_image,
{
{ {
args.background_image,
{ {
{ {
client_list, client_list,
forced_height = geo.height, forced_height = geo.height,
forced_width = geo.width, forced_width = geo.width,
widget = wibox.container.place, valign = "center",
halign = "center",
widget = wibox.container.place
}, },
layout = wibox.layout.align.horizontal, margins = args.tag_margin,
}, widget = wibox.container.margin
layout = wibox.layout.align.vertical,
},
margins = margin,
widget = wibox.container.margin,
}, },
layout = wibox.layout.stack layout = wibox.layout.stack
}, },
bg = widget_bg, bg = args.tag_bg,
shape_border_width = widget_border_width, shape_border_color = args.tag_border_color,
shape_border_color = widget_border_color, shape_border_width = args.tag_border_width,
shape = helpers.shape.rrect(screen_radius), shape = helpers.shape.rrect(args.tag_border_radius),
widget = wibox.container.background, widget = wibox.container.background
} }
self._private.widget.widget = w
end end
local enable = function(opts) local function new(args)
local opts = opts or {} args = args or {}
local tag_preview_image = opts.show_client_content or false args.type = args.type or "dropdown_menu"
local widget_x = opts.x or dpi(20) args.coords = args.coords or nil
local widget_y = opts.y or dpi(20) args.placement = args.placement or nil
local scale = opts.scale or 0.2 args.wibox = args.wibox
local work_area = opts.honor_workarea or false args.widget = args.widget
local padding = opts.honor_padding or false args.offset = args.offset or {}
local placement_fn = opts.placement_fn or nil args.padding = args.padding
local background_image = opts.background_widget or nil args.work_area = args.work_area
args.scale = args.scale or 0.2
args.margin = args.margin or dpi(0)
args.client_icon = args.client_icon
args.client_opacity = args.client_opacity or 0
args.client_bg = args.client_bg or "#000000"
args.client_border_color = args.client_border_color or "#ffffff"
args.client_border_width = args.client_border_width or dpi(1)
args.client_border_radius = args.client_border_radius or dpi(0)
args.tag_margin = args.tag_margin or dpi(0)
args.tag_bg = args.tag_bg or "#000000"
args.tag_border_color = args.tag_border_color or "#ffffff"
args.tag_border_width = args.tag_border_width or dpi(0)
args.tag_border_radius = args.tag_border_radius or dpi(0)
args.background_image = args.background_image or nil
args.tag_preview_image = args.tag_preview_image
local margin = beautiful.tag_preview_widget_margin or dpi(0) local ret = gobject {}
local screen_radius = beautiful.tag_preview_widget_border_radius or dpi(0) ret._private = {}
local client_radius = beautiful.tag_preview_client_border_radius or dpi(0)
local client_opacity = beautiful.tag_preview_client_opacity or 0.5
local client_bg = beautiful.tag_preview_client_bg or "#000000"
local client_border_color = beautiful.tag_preview_client_border_color
or "#ffffff"
local client_border_width = beautiful.tag_preview_client_border_width
or dpi(3)
local widget_bg = beautiful.tag_preview_widget_bg or "#000000"
local widget_border_color = beautiful.tag_preview_widget_border_color
or "#ffffff"
local widget_border_width = beautiful.tag_preview_widget_border_width
or dpi(3)
local tag_preview_box = awful.popup({ gtable.crush(ret, tag_preview)
type = "dropdown_menu", gtable.crush(ret, args)
ret._private.widget = awful.popup({
type = ret.type,
visible = false, visible = false,
ontop = true, ontop = true,
placement = placement_fn, placement = ret.placement,
widget = wibox.container.background, input_passthrough = ret.input_passthrough,
input_passthrough = true,
bg = "#00000000", 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 -- 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 -- which can cause the c.content to not show the correct image
gears.timer gtimer {
{
timeout = 0.1, timeout = 0.1,
call_now = false, call_now = false,
autostart = true, autostart = true,
@ -192,55 +236,37 @@ local enable = function(opts)
callback = function() callback = function()
if t.selected == true then if t.selected == true then
for _, c in ipairs(t:clients()) do 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
end end
} }
end) end)
awesome.connect_signal("bling::tag_preview::update", function(t) return ret
local geo = t.screen:get_bounding_geometry({
honor_padding = padding,
honor_workarea = work_area,
})
tag_preview_box.maximum_width = scale * geo.width + margin * 2
tag_preview_box.maximum_height = scale * geo.height + margin * 2
tag_preview_box.widget = draw_widget(
t,
tag_preview_image,
scale,
screen_radius,
client_radius,
client_opacity,
client_bg,
client_border_color,
client_border_width,
widget_bg,
widget_border_color,
widget_border_width,
geo,
margin,
background_image
)
end)
awesome.connect_signal("bling::tag_preview::visibility", function(s, v)
if not placement_fn then
tag_preview_box.x = s.geometry.x + widget_x
tag_preview_box.y = s.geometry.y + widget_y
end
if v == false then
tag_preview_box.widget = nil
collectgarbage("collect")
end
tag_preview_box.visible = v
end)
end end
return {enable = enable, draw_widget = draw_widget} function tag_preview:get_widget() return self._private.widget.widget end
function tag_preview:show(t)
self:update(t)
self._private.widget.visible = true
end
function tag_preview:hide()
self._private.widget.visible = false
self._private.widget.widget = nil
collectgarbage("collect")
end
function tag_preview:toggle(t)
if self._private.widget.visible == true then
self:hide()
else
self:show(t)
end
end
function tag_preview.mt:__call(...) return new(...) end
return setmetatable(tag_preview, tag_preview.mt)

View File

@ -58,25 +58,10 @@ function task_preview:show(c, args)
self._private.widget.y = args.coords.y self._private.widget.y = args.coords.y
end end
if not pcall(function() return type(c.content) end) then return end local shoot = awful.screenshot {client = c}
shoot:refresh()
local content = nil local ib = shoot.content_widget
if c.active then ib.resize = true
content = gsurface(c.content)
elseif c.prev_content then
content = gsurface(c.prev_content)
end
local img = nil
if content ~= nil then
local cr = cairo.Context(content)
local x, y, w, h = cr:clip_extents()
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()
end
local widget = wibox.widget { local widget = wibox.widget {
(self.widget_template or { (self.widget_template or {
@ -104,12 +89,7 @@ function task_preview:show(c, args)
}, },
{ {
{ {
{ id = "image_container_role",
id = "image_role",
resize = true,
clip_shape = self.image_shape,
widget = wibox.widget.imagebox
},
valign = "center", valign = "center",
halign = "center", halign = "center",
widget = wibox.container.place widget = wibox.container.place
@ -136,8 +116,8 @@ function task_preview:show(c, args)
-- TODO: have something like a create callback here? -- TODO: have something like a create callback here?
for _, w in ipairs(widget:get_children_by_id("image_role")) do for _, w in ipairs(widget:get_children_by_id("image_container_role")) do
w.image = img -- TODO: copy it with gsurface.xxx or something w.widget = ib -- TODO: copy it with gsurface.xxx or something
end end
for _, w in ipairs(widget:get_children_by_id("name_role")) do for _, w in ipairs(widget:get_children_by_id("name_role")) do