initial commit
This commit is contained in:
commit
e5554861f5
|
@ -0,0 +1,465 @@
|
|||
-- upstream url:
|
||||
-- https://github.com/BlingCorp/bling
|
||||
-- forked from:
|
||||
-- https://github.com/BlingCorp/bling/blob/487cdb69a5b38b48a8a6045218cbdea313325b8a/widget/tag_preview.lua
|
||||
|
||||
local cairo = require("lgi").cairo
|
||||
|
||||
local wibox = require("wibox")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local awful = require("awful")
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
|
||||
|
||||
local function ellipsize(unicode_string, max_length)
|
||||
if not unicode_string then return nil end
|
||||
local result = ''
|
||||
local counter = 1
|
||||
for uchar in string.gmatch(unicode_string, '([%z\1-\127\194-\244][\128-\191]*)') do
|
||||
counter = counter + 1
|
||||
if counter > max_length then
|
||||
result = result .. '…'
|
||||
break
|
||||
else
|
||||
result = result .. uchar
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
local function rounded_rect(radius)
|
||||
return function(cr, width, height)
|
||||
gears.shape.rounded_rect(cr, width, height, radius)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function create_box(
|
||||
client_geo, client_icon, client_name, screen_geo, img, buttons,
|
||||
client_bg, client_fg, client_opacity, client_border_color, client_border_width, client_radius,
|
||||
settings
|
||||
)
|
||||
local img_box
|
||||
if img then
|
||||
img_box = wibox.widget {
|
||||
image = gears.surface.load(img),
|
||||
resize = true,
|
||||
opacity = client_opacity,
|
||||
forced_height = math.floor(client_geo.height * settings.scale),
|
||||
forced_width = math.floor(client_geo.width * settings.scale),
|
||||
widget = wibox.widget.imagebox
|
||||
}
|
||||
elseif client_icon then
|
||||
img_box = wibox.widget {
|
||||
image = gears.surface.load(client_icon),
|
||||
resize = true,
|
||||
forced_height = settings.icon_size,
|
||||
forced_width = settings.icon_size,
|
||||
widget = wibox.widget.imagebox,
|
||||
valign = "center",
|
||||
}
|
||||
end
|
||||
|
||||
local client_box = wibox.widget {
|
||||
{
|
||||
nil,
|
||||
{
|
||||
nil,
|
||||
{
|
||||
{
|
||||
img_box,
|
||||
wibox.widget.textbox(
|
||||
gears.string.xml_escape(
|
||||
ellipsize(client_name, 80)
|
||||
)
|
||||
),
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
spacing = settings.margin * 2,
|
||||
fill_space = false,
|
||||
},
|
||||
margins = settings.margin * 3,
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
nil,
|
||||
expand = "outside",
|
||||
layout = wibox.layout.align.horizontal
|
||||
},
|
||||
nil,
|
||||
expand = "outside",
|
||||
widget = wibox.layout.align.vertical
|
||||
},
|
||||
forced_height = math.floor(client_geo.height * settings.scale),
|
||||
forced_width = math.floor(client_geo.width * settings.scale),
|
||||
bg = client_bg,
|
||||
fg = client_fg,
|
||||
border_color = client_border_color,
|
||||
border_width = client_border_width,
|
||||
shape = rounded_rect(client_radius),
|
||||
widget = wibox.container.background
|
||||
}
|
||||
|
||||
client_box.point = {
|
||||
x = math.floor((client_geo.x - screen_geo.x) * settings.scale),
|
||||
y = math.floor((client_geo.y - screen_geo.y) * settings.scale)
|
||||
}
|
||||
client_box:buttons(buttons)
|
||||
return client_box
|
||||
end
|
||||
|
||||
|
||||
local function get_settings(opts)
|
||||
local settings = {
|
||||
tag_preview_image = false,
|
||||
--tag_preview_image = true,
|
||||
--work_area = false,
|
||||
work_area = true,
|
||||
padding = false,
|
||||
|
||||
scale = 0.1963,
|
||||
--scale = 0.2,
|
||||
icon_size = 32 or dpi(24),
|
||||
default_client_icon = beautiful.tag_preview_default_client_icon or beautiful.awesome_icon,
|
||||
|
||||
--widget_x = dpi(20),
|
||||
--widget_y = dpi(20),
|
||||
widget_x = dpi(0),
|
||||
--widget_y = beautiful.panel_height or dpi(0),
|
||||
widget_y = dpi(0),
|
||||
margin = beautiful.tag_preview_widget_margin or dpi(1),
|
||||
screen_radius = (
|
||||
beautiful.tag_preview_widget_border_radius or
|
||||
(beautiful.client_border_radius or dpi(0))*2.7
|
||||
),
|
||||
widget_bg = beautiful.tag_preview_widget_bg or "#00000013", -- ???
|
||||
widget_border_color = beautiful.tag_preview_widget_border_color or "#ffffff22",
|
||||
widget_border_width = beautiful.tag_preview_widget_border_width or dpi(0),
|
||||
|
||||
screen_bg = beautiful.tag_preview_screen_bg or beautiful.bg_normal or "#60600023",
|
||||
|
||||
client_radius = beautiful.tag_preview_client_border_radius or
|
||||
beautiful.client_border_radius or 0,
|
||||
client_border_width = beautiful.tag_preview_client_border_width or
|
||||
dpi(2),
|
||||
client_opacity = beautiful.tag_preview_client_opacity or 0.5,
|
||||
client_bg = beautiful.tag_preview_client_bg or
|
||||
beautiful.titlebar_bg_normal or "#60006088",
|
||||
client_fg = beautiful.tag_preview_client_fg or
|
||||
beautiful.titlebar_fg_normal or "#ffffff88",
|
||||
client_border_color = beautiful.tag_preview_client_border_color or
|
||||
beautiful.border_normal or "#ffffff88",
|
||||
client_bg_focus = beautiful.tag_preview_client_bg_focus or
|
||||
beautiful.titlebar_bg_focus or "#60006088",
|
||||
client_fg_focus = beautiful.tag_preview_client_fg_focus or
|
||||
beautiful.titlebar_fg_focus or "#ffffff88",
|
||||
client_border_color_focus = beautiful.tag_preview_client_border_color_focus or
|
||||
beautiful.border_focus or "#ffffff88",
|
||||
|
||||
tag_opacity = beautiful.tag_preview_tag_opacity or 0.8,
|
||||
tag_bg = beautiful.tag_preview_tag_bg or
|
||||
beautiful.taglist_bg_occupied or "#00606088",
|
||||
tag_bg_focus = beautiful.tag_preview_tag_bg_focus or
|
||||
beautiful.taglist_bg_focus or "#00606088",
|
||||
tag_fg = beautiful.tag_preview_tag_fg or
|
||||
beautiful.taglist_fg_occupied or "#00606088",
|
||||
tag_fg_focus = beautiful.tag_preview_tag_fg_focus or
|
||||
beautiful.taglist_fg_focus or "#00606088",
|
||||
|
||||
}
|
||||
|
||||
settings.tag_radius = settings.client_radius
|
||||
settings.tag_border_width = settings.client_border_width
|
||||
settings.tag_border_color = beautiful.panel_widget_border_color or settings.client_border_color
|
||||
|
||||
if opts then
|
||||
for key, value in pairs(opts) do
|
||||
if opts[key] then
|
||||
settings[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return settings
|
||||
end
|
||||
|
||||
|
||||
local function create_class(from_table)
|
||||
local result = {
|
||||
mt = {},
|
||||
prototype = from_table,
|
||||
}
|
||||
result.mt.__index = function (_, key)
|
||||
return result.prototype[key]
|
||||
end
|
||||
result.new = function(...)
|
||||
local instance = {}
|
||||
setmetatable(instance, result.mt)
|
||||
instance:init(...)
|
||||
return instance
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
local tag_previewz = create_class{
|
||||
|
||||
init = function(self, opts)
|
||||
self.tag_preview_box = wibox({
|
||||
visible = false,
|
||||
ontop = true,
|
||||
--input_passthrough = true,
|
||||
bg = "#00000000"
|
||||
})
|
||||
self.settings = get_settings(opts)
|
||||
end,
|
||||
|
||||
|
||||
update = function(self, s)
|
||||
local widget_honor_padding = false
|
||||
local widget_honor_work_area = false
|
||||
|
||||
local screen_geo = s:get_bounding_geometry{
|
||||
honor_padding = self.settings.padding,
|
||||
honor_workarea = self.settings.work_area
|
||||
}
|
||||
local full_screen_geo = (
|
||||
self.settings.padding == widget_honor_padding and
|
||||
self.settings.work_area == widget_honor_work_area
|
||||
) and screen_geo or s:get_bounding_geometry{
|
||||
honor_padding = widget_honor_padding,
|
||||
honor_workarea = widget_honor_work_area
|
||||
}
|
||||
|
||||
self.tag_preview_box.x = full_screen_geo.x + self.settings.widget_x
|
||||
self.tag_preview_box.y = full_screen_geo.y + self.settings.widget_y
|
||||
self.tag_preview_box.width = self.settings.widget_width or full_screen_geo.width
|
||||
self.tag_preview_box.height = self.settings.widget_height or full_screen_geo.height
|
||||
|
||||
self:draw_widget(
|
||||
s, screen_geo, self.settings
|
||||
)
|
||||
end,
|
||||
|
||||
|
||||
toggle = function(self, s, args)
|
||||
s = s or awful.screen.focused()
|
||||
args = args or {}
|
||||
if args.update and args.visible ~= false then
|
||||
self:update(s)
|
||||
end
|
||||
local target_state = not self.tag_preview_box.visible
|
||||
if args.visible ~= nil then target_state = args.visible end
|
||||
self.tag_preview_box.visible = target_state
|
||||
end,
|
||||
|
||||
|
||||
draw_widget = function(self, s, screen_geo, settings)
|
||||
local tag_preview_box = self.tag_preview_box
|
||||
local client_lists = {}
|
||||
for _, t in ipairs(s.tags) do
|
||||
local client_list = wibox.layout.manual()
|
||||
table.insert(client_lists, client_list)
|
||||
client_list.forced_height = screen_geo.height
|
||||
client_list.forced_width = screen_geo.width
|
||||
for _, c in ipairs(t:clients()) do
|
||||
if not c.hidden and not c.minimized then
|
||||
client_list:add(
|
||||
self:create_client_box(c, t, s, screen_geo, settings)
|
||||
)
|
||||
end
|
||||
end
|
||||
client_list:add(
|
||||
self:create_tag_box(t, s, screen_geo, settings)
|
||||
)
|
||||
end
|
||||
|
||||
local used_width = 0
|
||||
local previews_v = wibox.layout.fixed.vertical()
|
||||
previews_v.fill_space = false
|
||||
previews_v.spacing = settings.margin * 2
|
||||
local previews_h = wibox.layout.fixed.horizontal()
|
||||
previews_h.fill_space = false
|
||||
previews_h.spacing = settings.margin * 2
|
||||
previews_v:add(previews_h)
|
||||
for _, client_list in ipairs(client_lists) do
|
||||
if screen_geo.width < (settings.scale * screen_geo.width + used_width) then
|
||||
previews_h = wibox.layout.fixed.horizontal()
|
||||
previews_h.fill_space = false
|
||||
previews_h.spacing = settings.margin * 2
|
||||
previews_v:add(previews_h)
|
||||
used_width = 0
|
||||
end
|
||||
used_width = used_width + screen_geo.width * settings.scale
|
||||
previews_h:add(wibox.widget{
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
client_list,
|
||||
bg = settings.screen_bg,
|
||||
widget = wibox.container.background
|
||||
},
|
||||
layout = wibox.container.constraint,
|
||||
height = screen_geo.height * settings.scale,
|
||||
width = screen_geo.width * settings.scale,
|
||||
strategy = "exact",
|
||||
},
|
||||
layout = wibox.layout.align.horizontal
|
||||
},
|
||||
layout = wibox.layout.align.vertical
|
||||
},
|
||||
margins = settings.margin,
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
bg = settings.widget_bg,
|
||||
border_width = settings.widget_border_width,
|
||||
border_color = settings.widget_border_color,
|
||||
shape = rounded_rect(settings.screen_radius),
|
||||
widget = wibox.container.background
|
||||
})
|
||||
end
|
||||
tag_preview_box:set_widget(previews_v)
|
||||
end,
|
||||
|
||||
|
||||
create_tag_box = function(self, t, s, screen_geo, settings)
|
||||
local tag_buttons = awful.util.table.join({
|
||||
awful.button({}, 1, function()
|
||||
if not self.tag_preview_box.visible then return end
|
||||
self:toggle(s, { visible = false })
|
||||
t:view_only()
|
||||
end)
|
||||
})
|
||||
local tag_geo = {
|
||||
x = 0 + screen_geo.x, y = 0 + screen_geo.y, height = 250, width = 400,
|
||||
--x = 0 + screen_geo.x, y = 0 + screen_geo.y, height = 200, width = 350,
|
||||
}
|
||||
local this_tag_bg = settings.tag_bg
|
||||
local this_tag_fg = settings.tag_fg
|
||||
for _, each_selected_tag in ipairs(s.selected_tags) do
|
||||
if t == each_selected_tag then
|
||||
this_tag_bg = settings.tag_bg_focus
|
||||
this_tag_fg = settings.tag_fg_focus
|
||||
break
|
||||
end
|
||||
end
|
||||
local tag_box = create_box(
|
||||
tag_geo, nil, t.name, screen_geo, nil, tag_buttons,
|
||||
this_tag_bg, this_tag_fg, settings.tag_opacity, settings.tag_border_color,
|
||||
settings.tag_border_width, settings.tag_radius,
|
||||
settings
|
||||
)
|
||||
return tag_box
|
||||
end,
|
||||
|
||||
|
||||
create_client_box = function(self, c, t, s, screen_geo, settings)
|
||||
local client_name = c.name
|
||||
local client_icon = c.icon or settings.default_client_icon
|
||||
local client_geo = {
|
||||
height = c.height,
|
||||
width = c.width,
|
||||
x = c.x,
|
||||
y = c.y
|
||||
}
|
||||
|
||||
local buttons = awful.util.table.join({
|
||||
awful.button({}, 1, function()
|
||||
if not self.tag_preview_box.visible then return end
|
||||
self:toggle(s, { visible = false })
|
||||
t:view_only()
|
||||
client.focus = c
|
||||
c:raise()
|
||||
end)
|
||||
})
|
||||
|
||||
local img
|
||||
if settings.tag_preview_image then
|
||||
if c.prev_content or t.selected then
|
||||
local content
|
||||
if t.selected then
|
||||
content = gears.surface(c.content)
|
||||
else
|
||||
content = gears.surface(c.prev_content)
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
local client_radius = settings.client_radius
|
||||
local client_border_width = settings.client_border_width
|
||||
local client_border_color = settings.client_border_color
|
||||
local client_bg = settings.client_bg
|
||||
local client_fg = settings.client_fg
|
||||
local geo = client_geo
|
||||
if c.fullscreen then
|
||||
client_border_width = 0
|
||||
client_radius = 0
|
||||
geo = screen_geo
|
||||
end
|
||||
if c == client.focus then
|
||||
client_bg = settings.client_bg_focus
|
||||
client_fg = settings.client_fg_focus
|
||||
client_border_color = settings.client_border_color_focus
|
||||
end
|
||||
|
||||
local client_box = create_box(
|
||||
geo, client_icon, client_name, screen_geo, img, buttons,
|
||||
client_bg, client_fg, settings.client_opacity, client_border_color,
|
||||
client_border_width, client_radius,
|
||||
settings
|
||||
)
|
||||
return client_box
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
|
||||
local module = {
|
||||
saving_client_content_enabled = false,
|
||||
}
|
||||
|
||||
function module.new(opts)
|
||||
local instance = tag_previewz.new(opts)
|
||||
if instance.settings.tag_preview_image then
|
||||
module.enable_saving_client_content()
|
||||
end
|
||||
return instance
|
||||
end
|
||||
|
||||
function module.enable_saving_client_content()
|
||||
if not module.saving_client_content_enabled then
|
||||
module.saving_client_content_enabled = true
|
||||
tag.connect_signal("property::selected", function(t)
|
||||
for _, c in ipairs(t:clients()) do
|
||||
c.prev_content = gears.surface.duplicate_surface(c.content)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function module.enable_signals(opts)
|
||||
local instance = module.new(opts)
|
||||
if instance.settings.tag_preview_image then
|
||||
module.enable_saving_client_content()
|
||||
end
|
||||
awesome.connect_signal("tag_previewz::update", function(s)
|
||||
instance:update(s)
|
||||
end)
|
||||
awesome.connect_signal("tag_previewz::visibility::toggle", function(s, args)
|
||||
instance:toggle(s, args)
|
||||
end)
|
||||
end
|
||||
|
||||
return module
|
Loading…
Reference in New Issue