collision/focus.lua

177 lines
6.5 KiB
Lua
Raw Normal View History

2013-07-17 06:53:30 +02:00
local capi = { client = client , mouse = mouse ,
screen = screen , keygrabber = keygrabber,}
2013-06-03 23:22:41 +02:00
local setmetatable = setmetatable
2013-07-17 06:53:30 +02:00
local ipairs = ipairs
local util = require( "awful.util" )
local client = require( "awful.client" )
local alayout = require( "awful.layout" )
2013-07-17 06:53:30 +02:00
local wibox = require( "wibox" )
local cairo = require( "lgi" ).cairo
2013-06-03 23:22:41 +02:00
local beautiful = require( "beautiful" )
2013-07-17 06:53:30 +02:00
local color = require( "gears.color" )
2013-06-03 23:22:41 +02:00
local module = {}
local wiboxes,delta = nil,100
2013-06-03 23:22:41 +02:00
---------------- Visual -----------------------
2013-06-03 23:22:41 +02:00
local function gen(item_height)
local img = cairo.ImageSurface(cairo.Format.ARGB32, item_height,item_height)
local cr = cairo.Context(img)
local rad = 10
cr:set_source_rgba(0,0,0,0)
cr:paint()
cr:set_source_rgba(1,1,1,1)
cr:arc(rad,rad,rad,0,2*math.pi)
cr:arc(item_height-rad,rad,rad,0,2*math.pi)
cr:arc(rad,item_height-rad,rad,0,2*math.pi)
cr:arc(item_height-rad,item_height-rad,rad,0,2*math.pi)
cr:fill()
cr:rectangle(0,rad, item_height, item_height-2*rad)
cr:rectangle(rad,0, item_height-2*rad, item_height)
cr:fill()
return img._native
end
2013-07-17 06:53:30 +02:00
local function constructor(width)
local img = cairo.ImageSurface(cairo.Format.ARGB32, width, width)
2013-06-03 23:22:41 +02:00
local cr = cairo.Context(img)
cr:move_to(0,0)
cr:set_source(color(beautiful.fg_normal))
cr:paint()
cr:set_source(color(beautiful.bg_normal))
cr:set_antialias(1)
cr:rectangle(0, (width/2), 10, (width/2))
cr:rectangle(width-10, (width/2), 10, (width/2))
for i=0,(width/2) do
cr:rectangle(i, 0, 1, (width/2)-i)
cr:rectangle(width-i, 0, 1, (width/2)-i)
end
cr:fill()
2013-07-17 06:53:30 +02:00
return cairo.Pattern.create_for_surface(img)
end
2013-06-03 23:22:41 +02:00
2013-07-17 06:53:30 +02:00
local function init()
local bounding,arrow = gen(75),constructor(55)
wiboxes = {}
for k,v in ipairs({"up","right","down","left","center"}) do
wiboxes[v] = wibox({})
wiboxes[v].height = 75
wiboxes[v].width = 75
wiboxes[v].ontop = true
if v ~= "center" then
local ib,m = wibox.widget.imagebox(),wibox.layout.margin()
local img = cairo.ImageSurface(cairo.Format.ARGB32, 55, 55)
local cr = cairo.Context(img)
cr:translate(55/2,55/2)
cr:rotate((k-1)*(2*math.pi)/4)
cr:translate(-(55/2),-(55/2))
cr:set_source(arrow)
cr:paint()
ib:set_image(img)
m:set_margins(10)
m:set_widget(ib)
wiboxes[v]:set_widget(m)
wiboxes[v].shape_bounding = bounding
end
2013-06-03 23:22:41 +02:00
end
2013-07-17 06:53:30 +02:00
wiboxes["center"]:set_bg(beautiful.bg_urgent)
local img = cairo.ImageSurface(cairo.Format.ARGB32, 75,75)
2013-06-03 23:22:41 +02:00
local cr = cairo.Context(img)
2013-07-17 06:53:30 +02:00
cr:set_source_rgba(0,0,0,0)
2013-06-03 23:22:41 +02:00
cr:paint()
2013-07-17 06:53:30 +02:00
cr:set_source_rgba(1,1,1,1)
cr:arc( 75/2,75/2,75/2,0,2*math.pi )
2013-06-03 23:22:41 +02:00
cr:fill()
2013-07-17 06:53:30 +02:00
wiboxes["center"].shape_bounding = img._native
2013-06-03 23:22:41 +02:00
end
local function display_wiboxes(cltbl,geomtbl,float,swap,c)
if not wiboxes then
init()
end
for k,v in ipairs({"left","right","up","down","center"}) do
local next_clients = (not (float and swap)) and cltbl[util.get_rectangle_in_direction(v , geomtbl, capi.client.focus:geometry())] or c
if next_clients or k==5 then
local same, center = capi.client.focus == next_clients,k==5
local geo = center and capi.client.focus:geometry() or next_clients:geometry()
wiboxes[v].visible = true
wiboxes[v].x = (swap and float and (not center)) and (geo.x + (k>2 and (geo.width/2) or 0) + (k==2 and geo.width or 0) - 75/2) or (geo.x + geo.width/2 - 75/2)
wiboxes[v].y = (swap and float and (not center)) and (geo.y + (k<=2 and geo.height/2 or 0) + (k==4 and geo.height or 0) - 75/2) or (geo.y + geo.height/2 - 75/2)
else
wiboxes[v].visible = false
2013-06-03 23:22:41 +02:00
end
end
end
2013-06-03 23:22:41 +02:00
---------------- Position -----------------------
local function float_move(dir,c)
return ({left={x=c:geometry().x-delta},right={x=c:geometry().x+delta},up={y=c:geometry().y-delta},down={y=c:geometry().y+delta}})[dir]
end
2013-06-03 23:22:41 +02:00
local function float_move_max(dir,c)
2014-05-10 05:09:17 +02:00
return ({left={x=capi.screen[c.screen].workarea.x},right={x=capi.screen[c.screen].workarea.width+capi.screen[c.screen].workarea.x-c:geometry().width}
,up={y=capi.screen[c.screen].workarea.y},down={y=capi.screen[c.screen].workarea.y+capi.screen[c.screen].workarea.height-c:geometry().height}})[dir]
end
2013-06-03 23:22:41 +02:00
local function floating_clients()
local ret = {}
for v in util.table.iterate(client.visible(),function(c) return client.floating.get(c) end) do
ret[#ret+1] = v
2013-06-03 23:22:41 +02:00
end
return ret
2013-06-03 23:22:41 +02:00
end
local function bydirection(dir, c, swap,max)
if c then
local float = client.floating.get(c) or alayout.get(c.screen) == alayout.suit.floating
-- Move the client if floating, swaping wont work anyway
if swap and float then
c:geometry((max and float_move_max or float_move)(dir,c))
display_wiboxes(nil,nil,float,swap,c)
else
-- Get all clients rectangle
2014-05-10 05:09:17 +02:00
local cltbl,geomtbl = max and floating_clients() or client.tiled(),{}
2013-06-03 23:22:41 +02:00
for i,cl in ipairs(cltbl) do
geomtbl[i] = cl:geometry()
end
local target = util.get_rectangle_in_direction(dir, geomtbl, c:geometry())
-- If we found a client to focus, then do it.
2013-06-03 23:22:41 +02:00
if target then
if swap ~= true then
capi.client.focus = cltbl[target]
capi.client.focus:raise()
else
c:swap(cltbl[target])
end
display_wiboxes(cltbl,geomtbl,float,swap,c)
2013-06-03 23:22:41 +02:00
end
end
end
end
2013-06-04 05:00:09 +02:00
function module.global_bydirection(dir, c,swap,max)
bydirection(dir, c or capi.client.focus, swap,max)
end
function module._global_bydirection_key(mod,key,event,direction,is_swap,is_max)
bydirection(direction,capi.client.focus,is_swap,is_max)
return true
end
function module.display(mod,key,event,direction,is_swap,is_max)
local c = capi.client.focus
local cltbl,geomtbl = max and floating_clients() or client.tiled(),{}
for i,cl in ipairs(cltbl) do
geomtbl[i] = cl:geometry()
end
display_wiboxes(cltbl,geomtbl,client.floating.get(c) or alayout.get(c.screen) == alayout.suit.floating,is_swap,c)
end
function module._quit()
for k,v in ipairs({"left","right","up","down","center"}) do
wiboxes[v].visible = false
end
2013-06-04 05:00:09 +02:00
end
2013-06-03 23:22:41 +02:00
return setmetatable(module, { __call = function(_, ...) return new(...) end })