Track focus and cursor position when selecting screen

This commit is contained in:
Emmanuel Lepage Vallee 2015-02-19 05:17:42 +00:00
parent 5956636d7e
commit 0366cd142f
6 changed files with 204 additions and 55 deletions

View File

@ -99,4 +99,7 @@ collision.settings.swap_across_screen = true
# Other
The `collision.select_screen(idx)` function allow to select a screen and can be
assigned to shortcuts.
assigned to shortcuts.
The `collision.highlight_cursor(timeout)` method will highlight the current mouse
cursor position.

View File

@ -17,44 +17,11 @@ local module = {}
local wiboxes,delta = nil,100
---------------- Visual -----------------------
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
local function constructor(width)
local img = cairo.ImageSurface(cairo.Format.ARGB32, width, width)
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()
return cairo.Pattern.create_for_surface(img)
end
local function init()
local bounding,arrow = gen(75),constructor(55)
local img = cairo.ImageSurface(cairo.Format.ARGB32, 75, 75)
local cr = cairo.Context(img)
local bounding,arrow = col_utils.draw_round_rect(cr,0,0,75,75,10),col_utils.arrow(55,color(beautiful.fg_normal),color(beautiful.bg_normal))
wiboxes = {}
for k,v in ipairs({"up","right","down","left","center"}) do
wiboxes[v] = wibox({})

View File

@ -1,4 +1,4 @@
local capi = {root=root,client=client,mouse=mouse,
local capi = {root=root,client=client,mouse=mouse, timer=timer
screen = screen, keygrabber = keygrabber}
local util = require( "awful.util" )
local awful = require( "awful" )
@ -9,6 +9,7 @@ local module = {
_resize = require( "collision.resize"),
_max = require( "collision.max" ),
_screen = require( "collision.screen"),
_mouse = require( "collision.mouse" ),
settings= col_utils.settings ,
util = col_utils ,
}
@ -127,11 +128,23 @@ function module.screen(direction, move)
end
function module.select_screen(idx)
if idx and idx > 0 and idx < capi.screen.count() then
if idx and idx > 0 and idx <= capi.screen.count() then
module._screen.select_screen(idx)
end
end
function module.highlight_cursor(timeout)
module._mouse.highlight()
if timer then
local timer = capi.timer({ timeout = timeout }) -- 30 mins
timer:connect_signal("timeout", function()
module._mouse.hide()
timer:stop()
end)
timer:start()
end
end
local function new(k)
-- Replace the keys array. The new one has to have a valid mapping
keys = k or keys

88
mouse.lua Normal file
View File

@ -0,0 +1,88 @@
local capi = {screen=screen,client=client,mouse=mouse, keygrabber = keygrabber}
local math,table = math,table
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 col_utils = require( "collision.util" )
local module = {}
local w = nil
function module.highlight()
if not w then
w = wibox{}
w.height = 100
w.width = 100
w.ontop = true
local img = cairo.ImageSurface(cairo.Format.A8, 100,100)
local cr = cairo.Context(img)
-- cr:set_operator(cairo.Operator.CLEAR)
cr:set_source_rgba(0,0,0,0)
cr:paint()
cr:set_operator(cairo.Operator.SOURCE)
cr:set_source_rgba(1,1,1,1)
cr:save()
cr:translate(0,-30)
cr:move_to(50,50)
cr:rotate(math.pi)
col_utils.arrow_path(cr,40)
cr:fill()
cr:restore()
cr:save()
cr:translate(-30,0)
cr:move_to(50,50)
cr:rotate(math.pi/2)
col_utils.arrow_path(cr,40)
cr:fill()
cr:restore()
cr:save()
cr:translate(30,0)
cr:move_to(50,50)
cr:rotate(-math.pi/2)
col_utils.arrow_path(cr,40)
cr:fill()
cr:restore()
cr:save()
cr:translate(0,30)
cr:move_to(50,50)
col_utils.arrow_path(cr,40)
cr:fill()
cr:restore()
cr:arc(50,50,50,0,2*math.pi)
cr:set_line_width(5)
cr:stroke()
cr:set_source_rgba(1,0,0,1)
w.shape_bounding = img._native
img = cairo.ImageSurface(cairo.Format.ARGB32, 100,100)
cr = cairo.Context(img)
cr:set_source(color(beautiful.bg_urgent))
cr:paint()
cr:set_source(color(beautiful.fg_normal))
cr:arc(50,50,50,0,2*math.pi)
cr:set_line_width(5)
cr:stroke()
w:set_bg(cairo.Pattern.create_for_surface(img))
end
w.x = capi.mouse.coords().x -50
w.y = capi.mouse.coords().y -50
w.visible = true
end
function module.hide()
w.visible = false
end
return module

View File

@ -1,13 +1,14 @@
local capi = {screen=screen,client=client,mouse=mouse, keygrabber = keygrabber}
local math,table = math,table
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 pango = require( "lgi" ).Pango
local pangocairo = require( "lgi" ).PangoCairo
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 pango = require( "lgi" ).Pango
local pangocairo = require( "lgi" ).PangoCairo
local mouse = require( "collision.mouse" )
local module = {}
@ -17,6 +18,10 @@ local shape = nil
local pss = 1
local opss = nil
-- Keep an index of the last selection client for each screen
local last_clients = setmetatable({},{__mode="v"})
local last_clients_coords = {}
-- Screen order is not always geometrical, sort them
local function get_first_screen()
local ret = {}
@ -52,6 +57,9 @@ local function create_text(text)
local cr = cairo.Context(img)
local selected = text == screens[pss]
cr:set_source(color(selected and beautiful.bg_urgent or beautiful.bg_alternate or beautiful.bg_normal))
if selected then
opss = screens_inv[text]
end
cr:paint()
cr:set_source(color(beautiful.fg_normal))
cr:set_line_width(6)
@ -102,8 +110,21 @@ local function init_wiboxes(direction)
end
local function select_screen(scr_index,move,old_screen)
local geom = capi.screen[scr_index].geometry
capi.mouse.coords({x=geom.x+geom.width/2,y=geom.y+geom.height/2+55})
if scr_index ~= old_screen then
local c = last_clients[scr_index]
if c and c:isvisible() then
local geom = c:geometry()
if last_clients_coords[scr_index] and last_clients_coords[scr_index].client == c then
capi.mouse.coords(last_clients_coords[scr_index])
else
capi.mouse.coords({x=geom.x+geom.width/2,y=geom.y+geom.height/2+55})
end
mouse.highlight()
else
local geom = capi.screen[scr_index].geometry
capi.mouse.coords({x=geom.x+geom.width/2,y=geom.y+geom.height/2+55})
end
end
if move then
local t = awful.tag.selected(old_screen)
@ -119,6 +140,30 @@ local function select_screen(scr_index,move,old_screen)
return scr_index
end
local function in_rect(c,point)
if not c then return true end
local geo = c:geometry()
return (
geo.x < point.x and geo.y < point.y and
geo.x + geo.width > point.x and geo.y + geo.height > point.y
)
end
local function save_cursor_position()
local coords = capi.mouse.coords()
local c = capi.client.focus
-- Be sure that that mouse in inside of the selected client before doing that
if c and in_rect(c,coords) then
last_clients_coords[c.screen] = {
client = c,
x = coords.x,
y = coords.y,
}
else
last_clients_coords[capi.mouse.screen] = nil
end
end
local function next_screen(ss,dir,move)
local scr_index = screens_inv[ss]
@ -135,8 +180,9 @@ function module.display(_,dir,move)
if #wiboxes == 0 then
init_wiboxes(dir)
end
save_cursor_position()
module.reload(nil,direction)
local ss,opss = current_screen(move),pss
local ss = current_screen(move)
next_screen(ss,dir,move)
module.reload(nil,direction)
end
@ -159,6 +205,7 @@ function module.hide()
for s=1, capi.screen.count() do
wiboxes[s].visible = false
end
mouse.hide()
end
local function show()
@ -168,7 +215,6 @@ local function show()
end
function module.reload(mod,dir,__,___,move)
opss = pss
local ss = current_screen(move)
if dir then
ss = next_screen(ss,dir:lower(),move or (mod and #mod == 4))
@ -182,20 +228,20 @@ function module.reload(mod,dir,__,___,move)
end
function module.select_screen(idx)
save_cursor_position()
select_screen(screens_inv[idx],false)
print("ENTER",idx)
if #wiboxes == 0 then
init_wiboxes(dir)
end
highlight_screen(idx)
highlight_screen(screens_inv[idx])
show()
capi.keygrabber.run(function(mod, key, event)
print("EVENT",event)
if event == "release" then
module.hide()
mouse.hide()
capi.keygrabber.stop()
return false
end
@ -203,5 +249,12 @@ function module.select_screen(idx)
end)
end
-- capi.mouse.connect_signal("property::screen",1,function(i)
-- print("FOO",i)
-- end)
capi.client.connect_signal("focus",function(c)
last_clients[c.screen] = c
end)
return module
-- kate: space-indent on; indent-width 2; replace-tabs on;

View File

@ -2,6 +2,7 @@ local math = math
local color = require( "gears.color" )
local beautiful = require( "beautiful" )
local glib = require("lgi").GLib
local cairo = require( "lgi" ).cairo
local module = {settings={}}
@ -16,6 +17,30 @@ function module.get_rgb()
return rr,rg,rb
end
function module.arrow_path(cr,width)
cr:rel_move_to( 0 , -width/2 )
cr:rel_line_to( width/2 , width/2 )
cr:rel_line_to( -10 , 0 )
cr:rel_line_to( 0 , width/2 )
cr:rel_line_to( (-width)+20 , 0 )
cr:rel_line_to( 0 , -width/2 )
cr:rel_line_to( -10 , 0 )
cr:rel_line_to( width/2 , -width/2)
cr:close_path()
end
function module.arrow(width,bg,fg)
local img = cairo.ImageSurface(cairo.Format.ARGB32, width, width)
local cr = cairo.Context(img)
cr:set_source(fg)
cr:paint()
cr:set_source(bg)
cr:move_to(width/2,width/2)
module.arrow_path(cr,width)
cr:fill()
return cairo.Pattern.create_for_surface(img)
end
function module.draw_round_rect(cr,x,y,w,h,radius)
cr:save()
cr:translate(x,y)