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 @@
--
-- 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 cairo = require("lgi").cairo
local awful = require("awful")
local wibox = require("wibox")
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 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 tag_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 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 function 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
)
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
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 ({
local img_box = wibox.widget {
resize = true,
forced_height = 100 * scale,
forced_width = 100 * scale,
widget = wibox.widget.imagebox,
})
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 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
-- If fails to set image, fallback to a awesome icon
if tag_preview_image then
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
local content
local content = nil
if t.selected then
content = gears.surface(c.content)
content = gsurface(c.content)
else
content = gears.surface(c.prev_content)
content = gsurface(c.prev_content)
end
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
)
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()
img_box = wibox.widget({
image = gears.surface.load(img),
image = gsurface.load(img),
resize = true,
opacity = client_opacity,
forced_height = math.floor(c.height * scale),
forced_width = math.floor(c.width * scale),
widget = wibox.widget.imagebox,
opacity = args.client_opacity,
forced_height = c.height * args.scale,
forced_width = c.width * args.scale,
widget = wibox.widget.imagebox
})
end
end
local c_bg = args.client_bg
if c == capi.client.focus then
c_bg = beautiful.xcolor4
end
local client_box = wibox.widget({
{
nil,
@ -90,157 +130,143 @@ local function draw_widget(
img_box,
nil,
expand = "outside",
layout = wibox.layout.align.horizontal,
layout = wibox.layout.align.horizontal
},
nil,
expand = "outside",
widget = wibox.layout.align.vertical,
widget = wibox.layout.align.vertical
},
forced_height = math.floor(c.height * scale),
forced_width = math.floor(c.width * scale),
bg = client_bg,
shape_border_color = client_border_color,
shape_border_width = client_border_width,
shape = helpers.shape.rrect(client_radius),
widget = wibox.container.background,
forced_height = math.floor(c.height * args.scale),
forced_width = math.floor(c.width * args.scale),
bg = c_bg,
shape_border_color = args.client_border_color,
shape_border_width = args.client_border_width,
shape = helpers.shape.rrect(args.client_border_radius),
widget = wibox.container.background
})
client_box.point = {
x = math.floor((c.x - geo.x) * scale),
y = math.floor((c.y - geo.y) * scale),
x = math.floor((c.x - geo.x) * args.scale),
y = math.floor((c.y - geo.y) * args.scale)
}
client_list:add(client_box)
end
end
return wibox.widget {
local w = wibox.widget {
{
background_image,
args.background_image,
{
{
{
{
client_list,
forced_height = geo.height,
forced_width = geo.width,
widget = wibox.container.place,
},
layout = wibox.layout.align.horizontal,
},
layout = wibox.layout.align.vertical,
client_list,
forced_height = geo.height,
forced_width = geo.width,
valign = "center",
halign = "center",
widget = wibox.container.place
},
margins = margin,
widget = wibox.container.margin,
margins = args.tag_margin,
widget = wibox.container.margin
},
layout = wibox.layout.stack
},
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,
bg = args.tag_bg,
shape_border_color = args.tag_border_color,
shape_border_width = args.tag_border_width,
shape = helpers.shape.rrect(args.tag_border_radius),
widget = wibox.container.background
}
self._private.widget.widget = w
end
local enable = function(opts)
local opts = opts or {}
local function new(args)
args = args or {}
local tag_preview_image = opts.show_client_content or false
local widget_x = opts.x or dpi(20)
local widget_y = opts.y or dpi(20)
local scale = opts.scale or 0.2
local work_area = opts.honor_workarea or false
local padding = opts.honor_padding or false
local placement_fn = opts.placement_fn or nil
local background_image = opts.background_widget or nil
args.type = args.type or "dropdown_menu"
args.coords = args.coords or nil
args.placement = args.placement or nil
args.wibox = args.wibox
args.widget = args.widget
args.offset = args.offset or {}
args.padding = args.padding
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 screen_radius = beautiful.tag_preview_widget_border_radius or dpi(0)
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 ret = gobject {}
ret._private = {}
local tag_preview_box = awful.popup({
type = "dropdown_menu",
gtable.crush(ret, tag_preview)
gtable.crush(ret, args)
ret._private.widget = awful.popup({
type = ret.type,
visible = false,
ontop = true,
placement = placement_fn,
widget = wibox.container.background,
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,
call_now = false,
autostart = true,
single_shot = true,
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::tag_preview::update", function(t)
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)
return ret
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
end
if not pcall(function() return type(c.content) end) then return end
local content = nil
if c.active then
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 shoot = awful.screenshot {client = c}
shoot:refresh()
local ib = shoot.content_widget
ib.resize = true
local widget = wibox.widget {
(self.widget_template or {
@ -104,12 +89,7 @@ function task_preview:show(c, args)
},
{
{
{
id = "image_role",
resize = true,
clip_shape = self.image_shape,
widget = wibox.widget.imagebox
},
id = "image_container_role",
valign = "center",
halign = "center",
widget = wibox.container.place
@ -136,8 +116,8 @@ function task_preview:show(c, args)
-- 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 gsurface.xxx or something
for _, w in ipairs(widget:get_children_by_id("image_container_role")) do
w.widget = ib -- TODO: copy it with gsurface.xxx or something
end
for _, w in ipairs(widget:get_children_by_id("name_role")) do