collision/max.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;