resize: Port to the new upstreamed APIs and add options
Most of the old code has been upstreamed. I used the reduced complexity to add tons of new visual options. It looks great! This remove support for resizing tiled layouts. First of all, it never worked properly. Also, I have a new layout system with a saner way of doing this. As it wont make it for 3.6, I will merge it into Collision.
This commit is contained in:
parent
1a87e0734a
commit
906f430f04
19
README.md
19
README.md
|
@ -96,11 +96,18 @@ namespace
|
|||
|
||||
## Focus
|
||||
|
||||
| Variable | Description |
|
||||
| :-------------------: | ----------------------------------------------------- |
|
||||
| collision_bg_focus | The background of the focus change arrow |
|
||||
| collision_fg_focus | The foregroung filling color of the arrow |
|
||||
| collision_bg_center | The focussed client circle background |
|
||||
| Variable | Description |
|
||||
| :---------------------------: | ------------------------------------------------------ |
|
||||
| collision_bg_focus | The background of the focus change arrow |
|
||||
| collision_fg_focus | The foregroung filling color of the arrow |
|
||||
| collision_bg_center | The focussed client circle background |
|
||||
| collision_resize_width | The size of the resize handles |
|
||||
| collision_resize_shape | The gears.shape used for the resize handle |
|
||||
| collision_resize_border_width | The resize handles border width |
|
||||
| collision_resize_border_color | The resize handles border colors |
|
||||
| collision_resize_padding | The resize handles padding between the boder and arrow |
|
||||
| collision_resize_bg | The resize handles background color |
|
||||
| collision_resize_fg | The resize handles arrow color |
|
||||
|
||||
# Settings
|
||||
|
||||
|
@ -120,4 +127,4 @@ cursor position.
|
|||
Use `collision.mouse.highlight()` and `collision.mouse.hide()`
|
||||
# Notes
|
||||
|
||||
Using the focus arrows to select empty screens only work in Awesome 3.5.7+
|
||||
Using the focus arrows to select empty screens only work in Awesome 3.5.7+
|
||||
|
|
285
resize.lua
285
resize.lua
|
@ -1,214 +1,133 @@
|
|||
local capi = { client = client, mouse=mouse,mousegrabber=mousegrabber }
|
||||
local ipairs,print = ipairs,print
|
||||
local wibox,color = require( "wibox" ) , require( "gears.color" )
|
||||
local cairo,beautiful = require( "lgi").cairo , require( "beautiful" )
|
||||
local awful = require("awful")
|
||||
local col_utils = require( "collision.util" )
|
||||
local d_resize = nil
|
||||
local capi = { client = client }
|
||||
local wibox = require( "wibox" )
|
||||
local beautiful = require( "beautiful" )
|
||||
local awful = require( "awful" )
|
||||
local surface = require( "gears.surface" )
|
||||
local shape = require( "gears.shape" )
|
||||
|
||||
-- This module is optional
|
||||
pcall(function() d_resize = require( "awful.layout.dynamic.resize" ) end)
|
||||
local module,indicators,cur_c,auto_hide = {},nil,nil
|
||||
local module,indicators,cur_c = {},nil,nil
|
||||
|
||||
local values = {"top" , "top_right" , "right" , "bottom_right" ,
|
||||
"bottom" , "bottom_left", "left" , "top_left" }
|
||||
|
||||
local invert = {
|
||||
left = "right" ,
|
||||
right = "left" ,
|
||||
top = "bottom",
|
||||
bottom = "top"
|
||||
left = "right",
|
||||
right = "left" ,
|
||||
up = "down" ,
|
||||
down = "up" ,
|
||||
}
|
||||
|
||||
local function gen_shape_bounding(radius)
|
||||
local img = cairo.ImageSurface(cairo.Format.ARGB32, radius,radius)
|
||||
local cr = cairo.Context(img)
|
||||
cr:set_source_rgba(0,0,0,0 )
|
||||
cr:paint ( )
|
||||
cr:set_source_rgba(1,1,1,1 )
|
||||
cr:arc ( radius/2,radius/2,radius/2,0,2*math.pi )
|
||||
cr:fill ( )
|
||||
return img._native
|
||||
end
|
||||
local r_ajust = {
|
||||
left = function(c, d) return { x = c.x - d, width = c.width + d } end,
|
||||
right = function(c, d) return { width = c.width + d, } end,
|
||||
up = function(c, d) return { y = c.y - d, height = c.height + d } end,
|
||||
down = function(c, d) return { height = c.height + d, } end,
|
||||
}
|
||||
|
||||
local function create_indicators()
|
||||
indicators = {}
|
||||
local arr = col_utils.arrow(20, 7, 10, beautiful.bg_alternate or "#ff0000", beautiful.fg_normal or "#0000ff")
|
||||
local arr_focus = col_utils.arrow(20, 7, 10, beautiful.fg_normal or "#ff0000", beautiful.bg_normal or "#0000ff")
|
||||
local angle = 0
|
||||
local shape_bounding = gen_shape_bounding(40)
|
||||
for k,v in ipairs(values) do
|
||||
local w = wibox({width=40,height=40,ontop=true,visible= true})
|
||||
local ib = wibox.widget.imagebox()
|
||||
local arr_rot,arr_rot_focus = cairo.ImageSurface(cairo.Format.ARGB32, 40, 40),cairo.ImageSurface(cairo.Format.ARGB32, 40, 40)
|
||||
for k2,v2 in ipairs({arr_rot,arr_rot_focus}) do
|
||||
local cr2= cairo.Context(v2)
|
||||
cr2:translate(20,20)
|
||||
cr2:rotate(angle)
|
||||
cr2:translate(-20,-20)
|
||||
cr2:set_source(v2 == arr_rot and arr or arr_focus)
|
||||
cr2:paint()
|
||||
local ret = {}
|
||||
local angle = -((2*math.pi)/8)
|
||||
|
||||
-- Get the parameters
|
||||
local size = beautiful.collision_resize_width or 40
|
||||
local s = beautiful.collision_resize_shape or shape.circle
|
||||
local bw = beautiful.collision_resize_border_width
|
||||
local bc = beautiful.collision_resize_border_color
|
||||
local padding = beautiful.collision_resize_padding or 7
|
||||
local bg = beautiful.collision_resize_bg or beautiful.bg_alternate or "#ff0000"
|
||||
local fg = beautiful.collision_resize_fg or beautiful.fg_normal or "#0000ff"
|
||||
|
||||
for k,v in ipairs(values) do
|
||||
local w = wibox {
|
||||
width = size,
|
||||
height = size,
|
||||
ontop = true,
|
||||
visible = true
|
||||
}
|
||||
|
||||
angle = angle + (2*math.pi)/8
|
||||
|
||||
local tr = (size - 2*padding) / 2
|
||||
|
||||
w:setup {
|
||||
{
|
||||
{
|
||||
{
|
||||
widget = wibox.widget.imagebox
|
||||
},
|
||||
shape = shape.transform(shape.arrow)
|
||||
: translate( tr,tr )
|
||||
: rotate ( angle )
|
||||
: translate( -tr,-tr ),
|
||||
bg = fg,
|
||||
widget = wibox.container.background
|
||||
},
|
||||
margins = padding,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
bg = bg,
|
||||
shape = s,
|
||||
shape_border_width = bw,
|
||||
shape_border_color = bc,
|
||||
widget = wibox.container.background
|
||||
}
|
||||
|
||||
surface.apply_shape_bounding(w, s)
|
||||
|
||||
ret[v] = w
|
||||
end
|
||||
ib:set_image(arr_rot)
|
||||
angle = angle + (2*math.pi)/8
|
||||
w:set_widget(ib)
|
||||
w.shape_bounding = shape_bounding
|
||||
w:set_bg(beautiful.bg_alternate or "#ff0000")
|
||||
w:connect_signal("mouse::enter",function() ib:set_image(arr_rot_focus) end)
|
||||
w:connect_signal("mouse::leave",function()
|
||||
ib:set_image(arr_rot)
|
||||
if auto_hide then
|
||||
module.hide()
|
||||
auto_hide = false
|
||||
end
|
||||
end)
|
||||
ib:buttons( awful.util.table.join(
|
||||
awful.button({ }, 1, function(geometry)
|
||||
ib:set_image(arr_rot)
|
||||
awful.mouse.client.resize(cur_c,v,function(c) module.display(c,true) end)
|
||||
end)))
|
||||
indicators[v] = w
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Resize using the mouse
|
||||
local placement_f = {
|
||||
left = function(g) return {x = g.x , y = g.y + g.height/2 } end,
|
||||
top_left = function(g) return {x = g.x , y = g.y } end,
|
||||
bottom_left = function(g) return {x = g.x , y = g.y+g.height } end,
|
||||
right = function(g) return {x = g.x + g.width , y = g.y+g.height/2 } end,
|
||||
top_right = function(g) return {x = g.x + g.width , y = g.y } end,
|
||||
bottom_right = function(g) return {x = g.x + g.width , y = g.y+g.height } end,
|
||||
top = function(g) return {x = g.x + g.width/2 , y = g.y } end,
|
||||
bottom = function(g) return {x = g.x + g.width/2 , y = g.y+g.height } end,
|
||||
}
|
||||
|
||||
-- Resize floating using the keyboard
|
||||
local r_orientation = { right = "width", left = "width", up = "height", down = "height" }
|
||||
local r_direction = { right = "x" , left = "x" , up = "y" , down = "y" }
|
||||
local r_sign = { right = 1 , left = -1 , up = -1 , down = 1 }
|
||||
|
||||
-- Resize tiled using the keyboard
|
||||
local layouts_all = {
|
||||
[awful.layout.suit.floating] = { right = "" },
|
||||
[awful.layout.suit.tile] = { right = {mwfact= 0.05}, left = {mwfact=-0.05}, up ={wfact=-0.1 }, down = {wfact = 0.1 } },
|
||||
[awful.layout.suit.tile.left] = { right = {mwfact=-0.05}, left = {mwfact= 0.05}, up ={wfact= 0.1 }, down = {wfact =-0.1 } },
|
||||
[awful.layout.suit.tile.bottom] = { right = {wfact=-0.1 }, left = {wfact= 0.1 }, up ={mwfact=-0.05}, down = {mwfact= 0.05} },
|
||||
[awful.layout.suit.tile.top] = { right = {wfact=-0.1 }, left = {wfact= 0.1 }, up ={mwfact= 0.05}, down = {mwfact=-0.05} },
|
||||
[awful.layout.suit.spiral] = { right = {wfact=-0.1 }, left = {wfact= 0.1 }, up ={mwfact= 0.05}, down = {mwfact=-0.05} },
|
||||
[awful.layout.suit.magnifier] = { right = {mwfact= 0.05}, left = {mwfact=-0.05}, up ={mwfact= 0.05}, down = {mwfact=-0.05} },
|
||||
-- The other layouts cannot be resized using variables
|
||||
}
|
||||
|
||||
function module.hide()
|
||||
for k,v in ipairs(values) do indicators[v].visible = false end
|
||||
for k,v in ipairs(values) do indicators[v].visible = false end
|
||||
|
||||
cur_c:disconnect_signal("property::geometry", module.display)
|
||||
cur_c = nil
|
||||
return
|
||||
end
|
||||
|
||||
function module.display(c,toggle)
|
||||
if type(c) ~= "client" then --HACK
|
||||
c = capi.client.focus
|
||||
if not c then return end
|
||||
end
|
||||
|
||||
if not indicators then
|
||||
create_indicators()
|
||||
end
|
||||
if c ~= cur_c then
|
||||
if cur_c then
|
||||
cur_c:disconnect_signal("property::geometry", module.display)
|
||||
if type(c) ~= "client" then --HACK
|
||||
c = capi.client.focus
|
||||
end
|
||||
|
||||
if not c then return end
|
||||
|
||||
indicators = indicators or create_indicators()
|
||||
|
||||
if c ~= cur_c then
|
||||
if cur_c then
|
||||
cur_c:disconnect_signal("property::geometry", module.display)
|
||||
end
|
||||
c:connect_signal("property::geometry", module.display)
|
||||
cur_c = c
|
||||
elseif toggle == true then
|
||||
module.hide()
|
||||
end
|
||||
|
||||
for k,v in ipairs(values) do
|
||||
local w = indicators[v]
|
||||
awful.placement[v](w, {parent=c})
|
||||
w.visible = true
|
||||
end
|
||||
c:connect_signal("property::geometry", module.display)
|
||||
cur_c = c
|
||||
elseif toggle == true then
|
||||
module.hide()
|
||||
end
|
||||
for k,v in ipairs(values) do
|
||||
local w,pos = indicators[v],placement_f[v](c:geometry())
|
||||
w.x,w.y,w.visible = math.floor(pos.x - 20), math.floor(pos.y - 20),true
|
||||
end
|
||||
end
|
||||
|
||||
function module.resize(mod,key,event,direction,is_swap,is_max)
|
||||
local c = capi.client.focus
|
||||
if not c then return true end
|
||||
local lay = awful.layout.get(c.screen)
|
||||
if awful.client.floating.get(c) or lay == awful.layout.suit.floating then
|
||||
local new_geo = c:geometry()
|
||||
new_geo[r_orientation[direction]] = new_geo[r_orientation[direction]] + r_sign[direction]*100*(is_swap and -1 or 1)
|
||||
if is_swap then
|
||||
new_geo[r_direction[direction]] = new_geo[r_direction[direction]] + r_sign[direction]*100
|
||||
end
|
||||
c:geometry(new_geo)
|
||||
elseif lay.is_dynamic then
|
||||
d_resize.ajust_geometry(c, 100 * (is_swap and -1 or 1), is_swap and invert[direction] or direction)
|
||||
elseif layouts_all[lay] then
|
||||
local ret = layouts_all[lay][direction]
|
||||
if ret.mwfact then
|
||||
awful.tag.incmwfact(ret.mwfact)
|
||||
end
|
||||
if ret.wfact then
|
||||
awful.client.incwfact(ret.wfact,c)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
local c = capi.client.focus
|
||||
if not c then return true end
|
||||
|
||||
local corners = {
|
||||
tl = function(geom,mouse,curX,curY) return {x=geom.x+(mouse.x-curX),y=geom.y+(mouse.y-curY),width=geom.width-(mouse.x-curX),height=geom.height-(mouse.y-curY)} end,
|
||||
bl = function(geom,mouse,curX,curY) return {x=geom.x+(mouse.x-curX),y=geom.y ,width=geom.width-(mouse.x-curX),height=geom.height-(curY-mouse.y)} end,
|
||||
br = function(geom,mouse,curX,curY) return {x=geom.x ,y=geom.y ,width=geom.width-(curX-mouse.x),height=geom.height-(curY-mouse.y)} end,
|
||||
}
|
||||
local del = is_swap and -100 or 100
|
||||
direction = is_swap and invert[direction] or direction
|
||||
|
||||
-- Resize from the top left corner
|
||||
function module.mouse_resize(c,corner)
|
||||
if not c then return end
|
||||
c:emit_signal("request::geometry", "mouse.resize", r_ajust[direction](c, del))
|
||||
|
||||
module.display(c)
|
||||
|
||||
-- Check if the dynamic resize codepath is available
|
||||
local lay = awful.layout.get(c.screen)
|
||||
if lay.is_dynamic then
|
||||
d_resize.generic_mouse_resize_handler(c, nil, nil, nil,{
|
||||
leave_callback = module.hide
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
-- Use the internal resizing code
|
||||
local geom,curX,curY = c:geometry(),capi.mouse.coords().x,capi.mouse.coords().y
|
||||
capi.mousegrabber.run(function(mouse)
|
||||
if mouse.buttons[1] == false then
|
||||
module.hide()
|
||||
return false
|
||||
elseif mouse.x ~= curX and mouse.y ~= curY then
|
||||
|
||||
-- Apply the changes
|
||||
local new = corners[corner or "tl"](geom,mouse,curX,curY)
|
||||
|
||||
-- Check for critically low values
|
||||
if new.width < 5 then
|
||||
new.width = 5
|
||||
end
|
||||
|
||||
if new.height < 5 then
|
||||
new.height = 5
|
||||
end
|
||||
|
||||
--Newer awesome version support checking size hints
|
||||
if c.apply_size_hints then
|
||||
local w,h = c:apply_size_hints(new.width,new.height)
|
||||
new.x,new.y,new.width,new.height = new.x - (w-new.width),new.y - (h-new.height),w,h
|
||||
end
|
||||
|
||||
c:geometry(new)
|
||||
end
|
||||
return true
|
||||
end,"fleur")
|
||||
end
|
||||
|
||||
-- Always display the arrows when resizing
|
||||
awful.mouse.resize.add_enter_callback(module.display, "mouse.resize")
|
||||
awful.mouse.resize.add_leave_callback(module.hide , "mouse.resize")
|
||||
|
||||
return module
|
||||
-- kate: space-indent on; indent-width 2; replace-tabs on;
|
||||
-- kate: space-indent on; indent-width 4; replace-tabs on;
|
||||
|
|
Loading…
Reference in New Issue