293 lines
8.3 KiB
Lua
293 lines
8.3 KiB
Lua
local capi = {screen=screen,client=client,mouse=mouse}
|
|
local wibox = require("wibox")
|
|
local awful = require("awful")
|
|
local cairo = require( "lgi" ).cairo
|
|
local color = require( "gears.color" )
|
|
local beautiful = require( "beautiful" )
|
|
local surface = require( "gears.surface" )
|
|
local layout = require( "collision.layout" )
|
|
local util = require( "collision.util" )
|
|
local shape = require( "gears.shape" )
|
|
local pango = require("lgi").Pango
|
|
local pangocairo = require("lgi").PangoCairo
|
|
local module = {}
|
|
|
|
local w = nil
|
|
local rad = 10
|
|
local border = 3
|
|
|
|
local function init()
|
|
w = wibox{}
|
|
w.ontop = true
|
|
w.visible = true
|
|
end
|
|
|
|
local margin = 15
|
|
|
|
local function create_arrow(cr,x,y,width, height,direction)
|
|
local r,g,b = util.get_rgb()
|
|
cr:set_source_rgba(r,g,b,0.15)
|
|
cr:set_antialias(1)
|
|
|
|
local s = shape.transform(shape.arrow)
|
|
: rotate_at(width/4, height/4, math.pi/2)
|
|
|
|
if direction == 1 then
|
|
s : rotate_at(width/4, height/4, math.pi)
|
|
end
|
|
|
|
s : translate(x, y)
|
|
|
|
s(cr, width/2, height/2, nil)
|
|
|
|
cr:fill()
|
|
end
|
|
|
|
local pango_l = nil
|
|
local function draw_shape(s,collection,current_idx,icon_f,y,text_height)
|
|
local geo = capi.screen[s].geometry
|
|
local wa =capi.screen[s].workarea
|
|
|
|
--Compute thumb dimensions
|
|
local margins = 2*20 + (#collection-1)*20
|
|
local width = (geo.width - margins) / #collection
|
|
local ratio = geo.height/geo.width
|
|
local height = width*ratio
|
|
local dx = 20
|
|
|
|
-- Do not let the thumb get too big
|
|
if height > 150 then
|
|
height = 150
|
|
width = 150 * (1.0/ratio)
|
|
dx = (wa.width-margins-(#collection*width))/2 + 20
|
|
end
|
|
|
|
-- Resize the wibox
|
|
w.x,w.y,w.width,w.height = math.floor(geo.x),math.floor(y or (wa.y+wa.height) - margin - height),math.floor(geo.width),math.floor(height)
|
|
|
|
local rshape = beautiful.collision_max_shape or shape.rounded_rect
|
|
local img = cairo.ImageSurface(cairo.Format.ARGB32, geo.width,geo.height)
|
|
local img3 = cairo.ImageSurface(cairo.Format.ARGB32, geo.width,geo.height)
|
|
local cr = cairo.Context(img)
|
|
local cr3 = cairo.Context(img3)
|
|
cr:set_source_rgba(0,0,0,0)
|
|
cr:paint()
|
|
|
|
-- Get the colors
|
|
local white,bg = color("#FFFFFF"),color(
|
|
beautiful.collision_max_bg or beautiful.menu_bg_normal or beautiful.bg_normal
|
|
)
|
|
|
|
local normal, focus = color(beautiful.collision_max_fg or beautiful.fg_normal), color(beautiful.bg_urgent)
|
|
|
|
-- Init the text properties
|
|
if not pango_l then
|
|
local pango_crx = pangocairo.font_map_get_default():create_context()
|
|
pango_l = pango.Layout.new(pango_crx)
|
|
pango_l:set_font_description(beautiful.get_font(font))
|
|
pango_l:set_alignment("CENTER")
|
|
pango_l:set_wrap("CHAR")
|
|
end
|
|
|
|
for k,v in ipairs(collection) do
|
|
-- Shape bounding
|
|
cr:set_source(white)
|
|
|
|
local s = shape.transform(rshape) : translate(dx, 0)
|
|
s(cr, width, height, 10)
|
|
cr:fill()
|
|
|
|
-- Borders and background
|
|
cr3:set_source(k==current_idx and focus or normal)
|
|
|
|
cr3:move_to(0,0)
|
|
s = shape.transform(rshape) : translate(dx+border, border)
|
|
s(cr3, width-2*border, height-2*border, rad)
|
|
|
|
cr3:set_line_width(2*border + 4) -- The 4 is required to cover the non-antialiased region
|
|
cr3:stroke_preserve()
|
|
cr3:set_source(bg)
|
|
cr3:fill()
|
|
|
|
-- Print the icon
|
|
local icon = icon_f(v,width-20,height-20-text_height)
|
|
if icon then
|
|
cr3:save()
|
|
cr3:translate(dx+10,10)
|
|
cr3:set_source_surface(icon)
|
|
cr3:paint_with_alpha(0.7)
|
|
cr3:restore()
|
|
end
|
|
|
|
-- Print a pretty line
|
|
local r,g,b = util.get_rgb(normal)
|
|
cr3:set_source_rgba(r,g,b,0.7)
|
|
cr3:set_line_width(1)
|
|
cr3:move_to(dx+margin,height - text_height-border)
|
|
cr3:line_to(dx+margin+width-2*margin,height - text_height-border)
|
|
cr3:stroke()
|
|
|
|
-- Pring the text
|
|
pango_l.text = v.name
|
|
pango_l.width = pango.units_from_double(width-16)
|
|
pango_l.height = pango.units_from_double(height-text_height-10)
|
|
cr3:move_to(dx+8,height-text_height-0)
|
|
cr3:show_layout(pango_l)
|
|
|
|
-- Draw an arrow
|
|
if current_idx and k == current_idx-1 then
|
|
create_arrow(cr3,dx,0,width,height,1)
|
|
else
|
|
create_arrow(cr3,dx,0,width,height,nil)
|
|
end
|
|
|
|
dx = dx + width + 20
|
|
end
|
|
|
|
w:set_bg(cairo.Pattern.create_for_surface(img3))
|
|
w.shape_bounding = img._native
|
|
w.visible = true
|
|
end
|
|
|
|
function module.hide()
|
|
w.visible = false
|
|
end
|
|
|
|
--Client related
|
|
local function client_icon(c,width,height)
|
|
-- Get the content
|
|
--TODO detect pure black frames
|
|
local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height)
|
|
local rshape = beautiful.collision_max_shape or shape.rounded_rect
|
|
local cr = cairo.Context(img)
|
|
|
|
local geom = c:geometry()
|
|
local scale = width/geom.width
|
|
if geom.height*scale > height then
|
|
scale = height/geom.height
|
|
end
|
|
local w,h = geom.width*scale,geom.height*scale
|
|
|
|
-- Create a mask
|
|
local s = shape.transform(rshape) : translate((width-w)/2, (height-h)/2)
|
|
s(cr, w, h, 10)
|
|
|
|
cr:clip()
|
|
|
|
cr:translate((width-w)/2,(height-h)/2)
|
|
|
|
-- Create a matrix to scale down the screenshot
|
|
cr:save()
|
|
cr:scale(scale,scale)
|
|
|
|
-- Paint the screenshot in the rounded rectangle
|
|
cr:set_source_surface(surface(c.content))
|
|
|
|
cr:paint()
|
|
cr:restore()
|
|
|
|
-- Add icon on top, "solve" the black window issue
|
|
local icon = surface(c.icon)
|
|
|
|
if not icon then
|
|
return img
|
|
end
|
|
|
|
-- local w,h = icon:get_width(),icon:get_height()
|
|
-- local aspect,aspect_h = width / w,(height) / h
|
|
-- if aspect > aspect_h then aspect = aspect_h end
|
|
-- cr:translate((width-w*aspect)/2,(height-h*aspect)/2)
|
|
-- cr:scale(aspect, aspect)
|
|
-- cr:set_source_surface(icon)
|
|
-- cr:paint_with_alpha(0.5)
|
|
|
|
return img
|
|
end
|
|
|
|
function module.display_clients(s,direction)
|
|
if not w then
|
|
init()
|
|
end
|
|
if direction then
|
|
awful.client.focus.byidx(direction == "right" and 1 or -1)
|
|
capi.client.focus:raise()
|
|
end
|
|
local clients = awful.client.tiled(s)
|
|
local fk = awful.util.table.hasitem(clients,capi.client.focus)
|
|
draw_shape(s,clients,fk,client_icon,nil,50)
|
|
end
|
|
|
|
function module.change_focus(mod,key,event,direction,is_swap,is_max)
|
|
awful.client.focus.byidx(direction == "right" and 1 or -1)
|
|
local c = capi.client.focus
|
|
local s = c.screen
|
|
c:raise()
|
|
local clients = awful.client.tiled(s)
|
|
local fk = awful.util.table.hasitem(clients,c)
|
|
draw_shape(s,clients,fk,client_icon,nil,50)
|
|
return true
|
|
end
|
|
|
|
--Tag related
|
|
local function tag_icon(t,width,height)
|
|
local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height)
|
|
local cr = cairo.Context(img)
|
|
|
|
local has_layout = layout.draw(t,cr,width,height)
|
|
|
|
-- Create a monochrome representation of the icon
|
|
local icon_orig = surface(t.icon)
|
|
if icon_orig then
|
|
local icon = cairo.ImageSurface(cairo.Format.ARGB32, icon_orig:get_width(), icon_orig:get_height())
|
|
local cr2 = cairo.Context(icon)
|
|
cr2:set_source_surface(icon_orig)
|
|
cr2:paint()
|
|
|
|
cr2:set_source(color(beautiful.fg_normal))
|
|
cr2:set_operator(cairo.Operator.IN)
|
|
cr2:paint()
|
|
|
|
local w,h = icon:get_width(),icon:get_height()
|
|
local aspect,aspect_h = width / w,(height) / h
|
|
if aspect > aspect_h then aspect = aspect_h end
|
|
cr:translate((width-w*aspect)/2,(height-h*aspect)/2)
|
|
cr:scale(aspect, aspect)
|
|
cr:set_source_surface(icon)
|
|
cr:paint_with_alpha(has_layout and 0.35 or 1)
|
|
end
|
|
return img
|
|
end
|
|
|
|
local function change_tag(s,direction,is_swap)
|
|
local s = capi.client.focus and capi.client.focus.screen or capi.mouse.screen
|
|
if not is_swap then
|
|
awful.tag[direction == "left" and "viewprev" or "viewnext"](s)
|
|
else
|
|
-- Move the tag
|
|
local t = capi.screen[s].selected_tag
|
|
local cur_idx,count = awful.tag.getidx(t),#capi.screen[s].tags
|
|
cur_idx = cur_idx + (direction == "left" and -1 or 1)
|
|
cur_idx = cur_idx == 0 and count or cur_idx > count and 1 or cur_idx
|
|
t.index = cur_idx
|
|
end
|
|
local tags = capi.screen[s].tags
|
|
local fk = awful.util.table.hasitem(tags,capi.screen[s].selected_tag)
|
|
draw_shape(s,tags,fk,tag_icon,capi.screen[s].workarea.y + 15,20)
|
|
end
|
|
|
|
function module.display_tags(s,direction,c,is_swap,is_max)
|
|
if not w then
|
|
init()
|
|
end
|
|
change_tag(s,direction,is_swap)
|
|
end
|
|
|
|
function module.change_tag(mod,key,event,direction,is_swap,is_max)
|
|
local s = capi.client.focus and capi.client.focus.screen or capi.mouse.screen
|
|
change_tag(s,direction,is_swap)
|
|
return true
|
|
end
|
|
|
|
return module
|
|
-- kate: space-indent on; indent-width 2; replace-tabs on;
|