Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Refactor task widget #147

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 150 additions & 90 deletions widget/task_preview.lua
Original file line number Diff line number Diff line change
@@ -1,30 +1,63 @@
--
-- Provides:
-- bling::task_preview::visibility
-- s (screen)
-- v (boolean)
-- c (client)
--
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 helpers = require(tostring(...):match(".*bling") .. ".helpers")
local gears = require("gears")
local beautiful = require("beautiful")
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local dpi = beautiful.xresources.apply_dpi
local cairo = require("lgi").cairo
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
Expand All @@ -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
Expand All @@ -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 {
{
{
{
Expand Down Expand Up @@ -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
Expand All @@ -119,81 +152,108 @@ 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 {}

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",
function task_preview:hide()
self._private.widget.visible = false
self._private.widget.widget = nil
collectgarbage("collect")
end

function task_preview:toggle(c, args)
if self._private.widget.visible == true then
self:hide()
else
self:show(c, args)
end
end

local function new(args)
args = args or {}

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,
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::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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to keep this for a few months so we can notify the user that this signal is deprecated.

-- 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

function task_preview.mt:__call(...)
return new(...)
end

return { enable = enable, draw_widget = draw_widget }
return setmetatable(task_preview, task_preview.mt)