placement: Re-introduce many placements features lost during the re-write
The menu can be attached to a widget or the mouse again, and more This commit also fix some tasklist/taglist issues and introduce minor features like item.shape.
This commit is contained in:
parent
c1285321a1
commit
bcd6c7c2cd
|
@ -13,7 +13,7 @@ local function set_visible(i, value)
|
||||||
local w, pg = i.w, i.private_data.parent_geometry
|
local w, pg = i.w, i.private_data.parent_geometry
|
||||||
|
|
||||||
if value then
|
if value then
|
||||||
w:move_by_parent(pg, true)
|
w:move_by_parent(pg, "widget")
|
||||||
end
|
end
|
||||||
|
|
||||||
w.visible = value
|
w.visible = value
|
||||||
|
@ -66,7 +66,7 @@ local function new(args)
|
||||||
local ret = base(args)
|
local ret = base(args)
|
||||||
|
|
||||||
ret:connect_signal("parent_geometry::changed", function()
|
ret:connect_signal("parent_geometry::changed", function()
|
||||||
args.internal.w:move_by_parent(ret.parent_geometry, true)
|
args.internal.w:move_by_parent(ret.parent_geometry, "widget")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Init the style
|
-- Init the style
|
||||||
|
|
9
dock.lua
9
dock.lua
|
@ -95,7 +95,14 @@ local function get_wibox(data, screen)
|
||||||
adapt_size(data, w.width, w.height, 1)
|
adapt_size(data, w.width, w.height, 1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
placement.pin(w, placement.corner, "left", screen or 1)
|
local f = nil
|
||||||
|
if beautiful.dock_always_show then
|
||||||
|
f = placement.attach_struts
|
||||||
|
else
|
||||||
|
f = placement.attach
|
||||||
|
end
|
||||||
|
|
||||||
|
f(w, placement.align, "left", screen or 1)
|
||||||
|
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,8 @@ local placement = require( "radical.placement" )
|
||||||
|
|
||||||
local module = {}
|
local module = {}
|
||||||
|
|
||||||
|
--TODO add "wrap cursor mode"
|
||||||
|
|
||||||
local wibox_to_req = {}
|
local wibox_to_req = {}
|
||||||
|
|
||||||
local corners_geo = {
|
local corners_geo = {
|
||||||
|
@ -43,7 +45,7 @@ local function create_hot_corner(corner, s)
|
||||||
local size = corners_geo[corner](s_geo, w_geo)
|
local size = corners_geo[corner](s_geo, w_geo)
|
||||||
local w = wibox(util.table.crush(size, {ontop=true, opacity = 0, visible=true}))
|
local w = wibox(util.table.crush(size, {ontop=true, opacity = 0, visible=true}))
|
||||||
|
|
||||||
placement.corner(w, corner, s, false, false)
|
placement.align(w, corner, s, false, false)
|
||||||
|
|
||||||
local req = {wibox = w, screen = s, corner = corner}
|
local req = {wibox = w, screen = s, corner = corner}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ end
|
||||||
function module.screenshot(clients,geo)
|
function module.screenshot(clients,geo)
|
||||||
if not clients then return end
|
if not clients then return end
|
||||||
|
|
||||||
local prev_menu= radical.context({layout=radical.layout.horizontal,item_width=140,item_height=140,icon_size=100,
|
local prev_menu= radical.context({layout=radical.layout.horizontal,item_layout=radical.item.layout.centerred,item_width=140,item_height=140,icon_size=100,
|
||||||
arrow_type=radical.base.arrow_type.CENTERED,enable_keyboard=false,item_style=radical.item.style.rounded})
|
arrow_type=radical.base.arrow_type.CENTERED,enable_keyboard=false,item_style=radical.item.style.rounded})
|
||||||
local t = type(clients)
|
local t = type(clients)
|
||||||
if t == "client" then
|
if t == "client" then
|
||||||
|
|
|
@ -8,21 +8,6 @@ local tag_list = nil
|
||||||
|
|
||||||
local module = {}
|
local module = {}
|
||||||
|
|
||||||
local fallback_layouts = {
|
|
||||||
suits.floating,
|
|
||||||
suits.tile,
|
|
||||||
suits.tile.left,
|
|
||||||
suits.tile.bottom,
|
|
||||||
suits.tile.top,
|
|
||||||
suits.fair,
|
|
||||||
suits.fair.horizontal,
|
|
||||||
suits.spiral,
|
|
||||||
suits.spiral.dwindle,
|
|
||||||
suits.max,
|
|
||||||
suits.max.fullscreen,
|
|
||||||
suits.magnifier
|
|
||||||
}
|
|
||||||
|
|
||||||
local function createTagList(aScreen,args)
|
local function createTagList(aScreen,args)
|
||||||
if not tag_list then
|
if not tag_list then
|
||||||
tag_list = require("radical.impl.taglist")
|
tag_list = require("radical.impl.taglist")
|
||||||
|
@ -62,7 +47,8 @@ end
|
||||||
function module.layouts(menu,layouts)
|
function module.layouts(menu,layouts)
|
||||||
local cur = awful.layout.get(awful.tag.getscreen(awful.tag.selected(capi.client.focus and capi.client.focus.screen)))
|
local cur = awful.layout.get(awful.tag.getscreen(awful.tag.selected(capi.client.focus and capi.client.focus.screen)))
|
||||||
local screenSelect = menu or radical.context {}
|
local screenSelect = menu or radical.context {}
|
||||||
local layouts = layouts or awful.layout.layouts or fallback_layouts
|
|
||||||
|
local layouts = layouts or awful.layout.layouts
|
||||||
for i, layout_real in ipairs(layouts) do
|
for i, layout_real in ipairs(layouts) do
|
||||||
local layout2 = awful.layout.getname(layout_real)
|
local layout2 = awful.layout.getname(layout_real)
|
||||||
local is_current = cur and ((layout_real == cur) or (layout_real.name == cur.name))
|
local is_current = cur and ((layout_real == cur) or (layout_real.name == cur.name))
|
||||||
|
@ -107,13 +93,15 @@ function module.layout_item(menu,args)
|
||||||
|
|
||||||
local function update()
|
local function update()
|
||||||
local layout = awful.layout.getname(awful.layout.get(screen))
|
local layout = awful.layout.getname(awful.layout.get(screen))
|
||||||
local ic = beautiful["layout_small_" ..layout] or beautiful["layout_" ..layout]
|
local ic = beautiful["layout_" ..layout]
|
||||||
item.icon = ic
|
item.icon = ic
|
||||||
end
|
end
|
||||||
update()
|
update()
|
||||||
|
|
||||||
awful.tag.attached_connect_signal(screen, "property::selected", update)
|
awful.tag.attached_connect_signal(screen, "property::selected", update)
|
||||||
awful.tag.attached_connect_signal(screen, "property::layout" , update)
|
awful.tag.attached_connect_signal(screen, "property::layout" , update)
|
||||||
|
|
||||||
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(module, { __call = function(_, ...) return module.listTags(...) end })
|
return setmetatable(module, { __call = function(_, ...) return module.listTags(...) end })
|
||||||
|
|
|
@ -38,9 +38,11 @@ local cache = setmetatable({}, { __mode = 'k' })
|
||||||
|
|
||||||
module.buttons = { [1] = awful.tag.viewonly,
|
module.buttons = { [1] = awful.tag.viewonly,
|
||||||
[2] = awful.tag.viewtoggle,
|
[2] = awful.tag.viewtoggle,
|
||||||
[3] = function(q,w,e,r)
|
[3] = function(t,menu,item,button_id,mod,geo)
|
||||||
local menu = tag_menu(q)
|
local menu = tag_menu(t)
|
||||||
|
menu.parent_geometry = geo
|
||||||
menu.visible = true
|
menu.visible = true
|
||||||
|
menu._internal.w:move_by_parent(geo, "cursor")
|
||||||
end,
|
end,
|
||||||
[4] = function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end,
|
[4] = function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end,
|
||||||
[5] = function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end,
|
[5] = function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end,
|
||||||
|
@ -117,10 +119,10 @@ local function create_item(t,s)
|
||||||
end
|
end
|
||||||
-- menu:move(item,index)
|
-- menu:move(item,index)
|
||||||
|
|
||||||
menu:connect_signal("button::press",function(menu,item,button_id,mod)
|
menu:connect_signal("button::press",function(menu,item,button_id,mod,geo)
|
||||||
if module.buttons and module.buttons[button_id] then
|
if module.buttons and module.buttons[button_id] then
|
||||||
if item.tag[1] then
|
if item.tag[1] then
|
||||||
module.buttons[button_id](item.tag[1],menu,item,button_id,mod)
|
module.buttons[button_id](item.tag[1],menu,item,button_id,mod,geo)
|
||||||
else
|
else
|
||||||
print("Invalid tag")
|
print("Invalid tag")
|
||||||
end
|
end
|
||||||
|
|
|
@ -120,7 +120,7 @@ local function new(t)
|
||||||
local mainMenu2 = menu{layout=radical.layout.grid,column=6,}
|
local mainMenu2 = menu{layout=radical.layout.grid,column=6,}
|
||||||
|
|
||||||
-- TODO port to async
|
-- TODO port to async
|
||||||
local f = io.popen('find '..config.iconPath .. "tags/ -maxdepth 1 -iname \"*.png\" -type f","r")
|
local f = io.popen('find '..config.iconPath .. "tags_invert/ -maxdepth 1 -iname \"*.png\" -type f","r")
|
||||||
local counter = 0
|
local counter = 0
|
||||||
while true do
|
while true do
|
||||||
local file = f:read("*line")
|
local file = f:read("*line")
|
||||||
|
|
|
@ -26,7 +26,7 @@ theme.register_color(MINIMIZED , "minimized" , "tasklist_minimized" , true )
|
||||||
|
|
||||||
-- Default button implementation
|
-- Default button implementation
|
||||||
module.buttons = {
|
module.buttons = {
|
||||||
[1] = function (c)
|
[1] = function(c,menu,item,button_id,mod, geo)
|
||||||
if c == capi.client.focus then
|
if c == capi.client.focus then
|
||||||
c.minimized = true
|
c.minimized = true
|
||||||
else
|
else
|
||||||
|
@ -42,16 +42,18 @@ module.buttons = {
|
||||||
c:raise()
|
c:raise()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
[3] = function(c)
|
[3] = function(c,menu,item,button_id,mod, geo)
|
||||||
client_menu.client = c
|
client_menu.client = c
|
||||||
local menu = client_menu()
|
local menu = client_menu()
|
||||||
|
menu.parent_geometry = geo
|
||||||
menu.visible = not menu.visible
|
menu.visible = not menu.visible
|
||||||
|
menu._internal.w:move_by_parent(geo, "cursor")
|
||||||
end,
|
end,
|
||||||
[4] = function ()
|
[4] = function(c,menu,item,button_id,mod, geo)
|
||||||
client.focus.byidx(1)
|
client.focus.byidx(1)
|
||||||
if capi.client.focus then capi.client.focus:raise() end
|
if capi.client.focus then capi.client.focus:raise() end
|
||||||
end,
|
end,
|
||||||
[5] = function ()
|
[5] = function(c,menu,item,button_id,mod, geo)
|
||||||
client.focus.byidx(-1)
|
client.focus.byidx(-1)
|
||||||
if capi.client.focus then capi.client.focus:raise() end
|
if capi.client.focus then capi.client.focus:raise() end
|
||||||
end
|
end
|
||||||
|
@ -203,14 +205,14 @@ local function create_client_item(c,screen)
|
||||||
item.state[MINIMIZED] = true
|
item.state[MINIMIZED] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
item:connect_signal("mouse::enter", function()
|
-- item:connect_signal("mouse::enter", function()
|
||||||
item.infoshapes = {
|
-- item.infoshapes = {
|
||||||
{text = "1:23:45", bg = beautiful.tasklist_bg_overlay, align = "center"},
|
-- {text = "1:23:45", bg = beautiful.tasklist_bg_overlay, align = "center"},
|
||||||
{text = c.pid , bg = beautiful.tasklist_bg_overlay, align = "center"}
|
-- {text = c.pid , bg = beautiful.tasklist_bg_overlay, align = "center"}
|
||||||
}
|
-- }
|
||||||
end)
|
-- end)
|
||||||
item:connect_signal("mouse::leave", function()
|
item:connect_signal("mouse::leave", function()
|
||||||
item.infoshapes = {}
|
-- item.infoshapes = {}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
item.add_suffix = function(w,w2)
|
item.add_suffix = function(w,w2)
|
||||||
|
@ -334,9 +336,9 @@ local function new(screen)
|
||||||
|
|
||||||
load_clients(tag.selected(screen))
|
load_clients(tag.selected(screen))
|
||||||
|
|
||||||
menu:connect_signal("button::press",function(menu,item,button_id,mod)
|
menu:connect_signal("button::press",function(menu,item,button_id,mod,geo)
|
||||||
if module.buttons and module.buttons[button_id] then
|
if module.buttons and module.buttons[button_id] then
|
||||||
module.buttons[button_id](item.client,menu,item,button_id,mod)
|
module.buttons[button_id](item.client,menu,item,button_id,mod,geo)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -344,7 +346,7 @@ local function new(screen)
|
||||||
display_screenshot(i.client,geo,true)
|
display_screenshot(i.client,geo,true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return menu,menu._internal.layout
|
return menu,menu._internal.widget
|
||||||
end
|
end
|
||||||
|
|
||||||
function module.item(client)
|
function module.item(client)
|
||||||
|
|
6
init.lua
6
init.lua
|
@ -22,10 +22,12 @@ end
|
||||||
-- @tparam[opt="button1::pressed"] string event The event trigger for showing
|
-- @tparam[opt="button1::pressed"] string event The event trigger for showing
|
||||||
-- the menu.
|
-- the menu.
|
||||||
-- @tparam[opt=1] button_id The mouse button 1 (1= left, 3=right)
|
-- @tparam[opt=1] button_id The mouse button 1 (1= left, 3=right)
|
||||||
local function set_menu(self,menu, event, button_id)
|
-- @tparam[opt=widget] The position mode (see `radical.placement`)
|
||||||
|
local function set_menu(self,menu, event, button_id, mode)
|
||||||
if not menu then return end
|
if not menu then return end
|
||||||
local event = event or "button::pressed"
|
local event = event or "button::pressed"
|
||||||
local button_id = button_id or 1
|
local button_id = button_id or 1
|
||||||
|
mode = mode or "widget"
|
||||||
|
|
||||||
|
|
||||||
local function trigger(_, geo)
|
local function trigger(_, geo)
|
||||||
|
@ -47,7 +49,7 @@ local function set_menu(self,menu, event, button_id)
|
||||||
if not m then return end
|
if not m then return end
|
||||||
|
|
||||||
m.parent_geometry = geo
|
m.parent_geometry = geo
|
||||||
m._internal.w:move_by_parent(geo)
|
m._internal.w:move_by_parent(geo, mode)
|
||||||
|
|
||||||
m.visible = not m.visible
|
m.visible = not m.visible
|
||||||
end
|
end
|
||||||
|
|
|
@ -120,6 +120,7 @@ local function new_item(data,args)
|
||||||
style = args.style or data.item_style ,
|
style = args.style or data.item_style ,
|
||||||
layout = args.layout or args.item_layout or nil ,
|
layout = args.layout or args.item_layout or nil ,
|
||||||
infoshapes = args.infoshapes or nil ,
|
infoshapes = args.infoshapes or nil ,
|
||||||
|
shape = args.shape or data.item_shape ,
|
||||||
overlay_draw= args.overlay_draw or data.overlay_draw ,
|
overlay_draw= args.overlay_draw or data.overlay_draw ,
|
||||||
item_border_color = args.item_border_color or data.item_border_color or nil ,
|
item_border_color = args.item_border_color or data.item_border_color or nil ,
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,7 +19,7 @@ local function generic(_, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
local function draw(item)
|
local function draw(item)
|
||||||
item.widget:set_shape(args.shape, unpack(args.shape_args or {}))
|
item.widget:set_shape(args.shape or item.shape, unpack(args.shape_args or {}))
|
||||||
item.widget:set_shape_border_width(item.border_width)
|
item.widget:set_shape_border_width(item.border_width)
|
||||||
theme.update_colors(item)
|
theme.update_colors(item)
|
||||||
end
|
end
|
||||||
|
|
262
placement.lua
262
placement.lua
|
@ -9,7 +9,6 @@ local module = {}
|
||||||
-- Compute the new `x` and `y`.
|
-- Compute the new `x` and `y`.
|
||||||
-- The workarea position need to be applied by the caller
|
-- The workarea position need to be applied by the caller
|
||||||
local map = {
|
local map = {
|
||||||
-- Corners
|
|
||||||
top_left = function(sw, sh, dw, dh) return {x=0 , y=0 } end,
|
top_left = function(sw, sh, dw, dh) return {x=0 , y=0 } end,
|
||||||
top_right = function(sw, sh, dw, dh) return {x=sw-dw , y=0 } end,
|
top_right = function(sw, sh, dw, dh) return {x=sw-dw , y=0 } end,
|
||||||
bottom_left = function(sw, sh, dw, dh) return {x=0 , y=sh-dh } end,
|
bottom_left = function(sw, sh, dw, dh) return {x=0 , y=sh-dh } end,
|
||||||
|
@ -18,8 +17,14 @@ local map = {
|
||||||
right = function(sw, sh, dw, dh) return {x=sw-dw , y=sh/2-dh/2} end,
|
right = function(sw, sh, dw, dh) return {x=sw-dw , y=sh/2-dh/2} end,
|
||||||
top = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=0 } end,
|
top = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=0 } end,
|
||||||
bottom = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=sh-dh } end,
|
bottom = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=sh-dh } end,
|
||||||
|
centered = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y=sh/2-dh/2} end,
|
||||||
|
center_vertical = function(sw, sh, dw, dh) return {x= nil , y=sh-dh } end,
|
||||||
|
center_horizontal = function(sw, sh, dw, dh) return {x=sw/2-dw/2, y= nil } end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Store function -> keys
|
||||||
|
local reverse_map = {}
|
||||||
|
|
||||||
-- Create the geometry rectangle 1=best case, 2=fallback
|
-- Create the geometry rectangle 1=best case, 2=fallback
|
||||||
local positions = {
|
local positions = {
|
||||||
left1 = function(x, y, w, h) return {x = x - w, y = y , width = w, height = h} end,
|
left1 = function(x, y, w, h) return {x = x - w, y = y , width = w, height = h} end,
|
||||||
|
@ -48,55 +53,208 @@ local function fit_in_screen(s, geo)
|
||||||
return geo2.width == geo.width and geo2.height == geo.height
|
return geo2.width == geo.width and geo2.height == geo.height
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Move the drawable (client or wibox) `d` to a screen corner or side.
|
--- Move the drawable (client or wibox) `d` to a screen position or side.
|
||||||
function module.corner(d, corner, s, honor_wa, update_wa)
|
--
|
||||||
local sgeo = capi.screen[s][honor_wa and "workarea" or "geometry"]
|
-- Supported positions are:
|
||||||
local dgeo = d:geometry()
|
--
|
||||||
|
-- * top_left
|
||||||
|
-- * top_right
|
||||||
|
-- * bottom_left
|
||||||
|
-- * bottom_right
|
||||||
|
-- * left
|
||||||
|
-- * right
|
||||||
|
-- * top
|
||||||
|
-- * bottom
|
||||||
|
-- * centered
|
||||||
|
-- * center_vertical
|
||||||
|
-- * center_horizontal
|
||||||
|
--
|
||||||
|
-- The valid other arguments are:
|
||||||
|
--
|
||||||
|
-- * *honor_workarea*: Take workarea into account when placing the drawable (default: false)
|
||||||
|
--
|
||||||
|
-- @param drawable A drawable (like `client` or `wibox`)
|
||||||
|
-- @tparam string position One of the position mentionned above
|
||||||
|
-- @param[opt=d.screen or capi.mouse.screen] parent The parent geometry
|
||||||
|
-- @tparam[opt={}] table args Other arguments
|
||||||
|
function module.align(drawable, position, parent, args)
|
||||||
|
args = args or {}
|
||||||
|
parent = parent or drawable.screen or capi.mouse.screen
|
||||||
|
|
||||||
local pos = map[corner](sgeo.width, sgeo.height, dgeo.width, dgeo.height)
|
local sgeo = nil
|
||||||
|
|
||||||
d : geometry {
|
-- Get the parent geometry
|
||||||
x = math.ceil(sgeo.x + pos.x) ,
|
local parent_type = type(parent)
|
||||||
y = math.ceil(sgeo.y + pos.y) ,
|
|
||||||
|
if parent_type == "screen" or parent_type == "number" then
|
||||||
|
sgeo = capi.screen[parent][args.honor_workarea and "workarea" or "geometry"]
|
||||||
|
else
|
||||||
|
sgeo = parent:geometry()
|
||||||
|
end
|
||||||
|
|
||||||
|
local dgeo = drawable:geometry()
|
||||||
|
|
||||||
|
local pos = map[position](sgeo.width, sgeo.height, dgeo.width, dgeo.height)
|
||||||
|
|
||||||
|
drawable : geometry {
|
||||||
|
x = pos.x and math.ceil(sgeo.x + pos.x) or dgeo.x,
|
||||||
|
y = pos.y and math.ceil(sgeo.y + pos.y) or dgeo.y,
|
||||||
width = math.ceil(dgeo.width ) ,
|
width = math.ceil(dgeo.width ) ,
|
||||||
height = math.ceil(dgeo.height ) ,
|
height = math.ceil(dgeo.height ) ,
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
--TODO update_wa
|
-- Create many placement functions
|
||||||
|
for k,v in pairs(map) do
|
||||||
|
module[k] = function(d, p, args)
|
||||||
|
module.align(d, k, p, args)
|
||||||
|
end
|
||||||
|
|
||||||
|
reverse_map[module[k]] = k
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Pin a drawable to a placement function.
|
--- Pin a drawable to a placement function.
|
||||||
-- Auto update the position when the size change
|
-- Automatically update the position when the size change.
|
||||||
function module.pin(d, f, ...)
|
-- All other arguments will be passed to the `position` function (if any)
|
||||||
--TODO memory leak
|
-- @param drawable A drawable (like `client` or `wibox`)
|
||||||
|
-- @param position A position name (see `align`) or a position function
|
||||||
|
function module.attach(drawable, position, ...)
|
||||||
|
if type(position) == "string" then
|
||||||
|
position = module[position]
|
||||||
|
end
|
||||||
|
|
||||||
|
if not position then return end
|
||||||
|
|
||||||
local args = {...}
|
local args = {...}
|
||||||
|
|
||||||
local function tracker()
|
local function tracker()
|
||||||
f(d, unpack(args))
|
position(drawable, unpack(args))
|
||||||
end
|
end
|
||||||
|
|
||||||
d:connect_signal("property::width" , tracker)
|
drawable:connect_signal("property::width" , tracker)
|
||||||
d:connect_signal("property::height", tracker)
|
drawable:connect_signal("property::height", tracker)
|
||||||
|
|
||||||
tracker()
|
tracker()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Update the workarea
|
||||||
|
local function wibox_update_strut(d, position)
|
||||||
|
-- If the drawable isn't visible, remove the struts
|
||||||
|
if not d.visible then
|
||||||
|
d:struts { left = 0, right = 0, bottom = 0, top = 0 }
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Detect horizontal or vertical drawables
|
||||||
|
local geo = d:geometry()
|
||||||
|
local vertical = geo.width < geo.height
|
||||||
|
|
||||||
|
-- Look into the `position` string to find the relevants sides to crop from
|
||||||
|
-- the workarea
|
||||||
|
local struts = { left = 0, right = 0, bottom = 0, top = 0 }
|
||||||
|
|
||||||
|
if vertical then
|
||||||
|
for k, v in ipairs {"right", "left"} do
|
||||||
|
if (not position) or position:match(v) then
|
||||||
|
struts[v] = geo.width + 2 * d.border_width
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for k, v in ipairs {"top", "bottom"} do
|
||||||
|
if (not position) or position:match(v) then
|
||||||
|
struts[v] = geo.height + 2 * d.border_width
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update the workarea
|
||||||
|
d:struts(struts)
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.attach_struts(d, f, ...)
|
||||||
|
module.attach(d, f, ...)
|
||||||
|
--TODO if there is multiple attach_struts, update them, see `raise_attached_struts`
|
||||||
|
|
||||||
|
local function tracker()
|
||||||
|
wibox_update_strut(d, reverse_map[f])
|
||||||
|
end
|
||||||
|
|
||||||
|
d:connect_signal("property::geometry" , tracker)
|
||||||
|
d:connect_signal("property::visible" , tracker)
|
||||||
|
|
||||||
|
tracker()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Move a drawable to the "top priority" of attached_structs
|
||||||
|
function module.raise_attached_struts()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a pair of rectangles used to set the relative areas.
|
||||||
|
-- v=vertical, h=horizontal
|
||||||
|
local function get_cross_sections(abs_geo, mode)
|
||||||
|
if not mode or mode == "cursor" then
|
||||||
|
-- A 1px cross section centered around the mouse position
|
||||||
|
|
||||||
|
local coords = capi.mouse.coords()
|
||||||
|
return {
|
||||||
|
h = {
|
||||||
|
x = abs_geo.drawable_geo.x ,
|
||||||
|
y = coords.y ,
|
||||||
|
width = abs_geo.drawable_geo.width ,
|
||||||
|
height = 1 ,
|
||||||
|
},
|
||||||
|
v = {
|
||||||
|
x = coords.x ,
|
||||||
|
y = abs_geo.drawable_geo.y ,
|
||||||
|
width = 1 ,
|
||||||
|
height = abs_geo.drawable_geo.height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif mode == "widget" then
|
||||||
|
-- The widget geometry extended to reach the end of the drawable
|
||||||
|
|
||||||
|
return {
|
||||||
|
h = {
|
||||||
|
x = abs_geo.drawable_geo.x ,
|
||||||
|
y = abs_geo.y ,
|
||||||
|
width = abs_geo.drawable_geo.width ,
|
||||||
|
height = abs_geo.height ,
|
||||||
|
},
|
||||||
|
v = {
|
||||||
|
x = abs_geo.x ,
|
||||||
|
y = abs_geo.drawable_geo.y ,
|
||||||
|
width = abs_geo.width ,
|
||||||
|
height = abs_geo.drawable_geo.height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif mode == "cursor_inside" then
|
||||||
|
-- A 1x1 rectangle centered around the mouse position
|
||||||
|
|
||||||
|
local coords = capi.mouse.coords()
|
||||||
|
coords.width,coords.height = 1,1
|
||||||
|
return {h=coords, v=coords}
|
||||||
|
elseif mode == "widget_inside" then
|
||||||
|
-- The widget absolute geometry, unchanged
|
||||||
|
|
||||||
|
return {h=abs_geo, v=abs_geo}
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(false)
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the possible 2D anchor points around a widget geometry.
|
--- Get the possible 2D anchor points around a widget geometry.
|
||||||
-- This take into account the widget drawable (wibox) and try to avoid
|
-- This take into account the widget drawable (wibox) and try to avoid
|
||||||
-- overlapping.
|
-- overlapping.
|
||||||
function module.get_relative_points(geo, mode)
|
function module.get_relative_points(geo, mode) --TODO rename regions
|
||||||
local use_mouse = true --TODO support modes
|
mode = mode or "widget"
|
||||||
|
|
||||||
-- The closest points around the geometry
|
|
||||||
local dps = {}
|
|
||||||
|
|
||||||
-- Use the mouse position and the wibox/client under it
|
-- Use the mouse position and the wibox/client under it
|
||||||
if not geo then
|
if not geo then
|
||||||
local draw = mouse.drawin_under_pointer()
|
local draw = mouse.drawin_under_pointer()
|
||||||
geo = draw and draw:geometry() or capi.mouse.coords()
|
geo = draw and draw:geometry() or capi.mouse.coords()
|
||||||
geo.drawable = draw
|
geo.drawable = draw
|
||||||
elseif geo.x and geo.width then
|
elseif (not geo.drawable) and geo.x and geo.width then
|
||||||
local coords = capi.mouse.coords()
|
local coords = capi.mouse.coords()
|
||||||
|
|
||||||
-- Check id the mouse is in the rect
|
-- Check id the mouse is in the rect
|
||||||
|
@ -104,59 +262,59 @@ function module.get_relative_points(geo, mode)
|
||||||
coords.y > geo.y and coords.y < geo.y+geo.height then
|
coords.y > geo.y and coords.y < geo.y+geo.height then
|
||||||
geo.drawable = mouse.drawin_under_pointer()
|
geo.drawable = mouse.drawin_under_pointer()
|
||||||
end
|
end
|
||||||
--TODO add drawin_at(x,y) in the C core
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if geo.drawable then
|
-- Get the drawable geometry
|
||||||
-- Case 1: A widget
|
local dpos = geo.drawable and geo.drawable.drawable:geometry() or {x=0, y=0}
|
||||||
|
|
||||||
local dgeo = geo.drawable.drawable:geometry()
|
|
||||||
|
|
||||||
-- Compute the absolute widget geometry
|
-- Compute the absolute widget geometry
|
||||||
local abs_widget_geo = {
|
local abs_widget_geo = {
|
||||||
x = dgeo.x + geo.x,
|
x = dpos.x + geo.x ,
|
||||||
y = dgeo.y + geo.y,
|
y = dpos.y + geo.y ,
|
||||||
width = geo.width ,
|
width = geo.width ,
|
||||||
height = geo.height ,
|
height = geo.height ,
|
||||||
drawable = geo.drawable ,
|
drawable = geo.drawable ,
|
||||||
|
drawable_geo = geo.drawable and dpos or geo,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Get the comparaison point
|
-- Get the comparaison point
|
||||||
local center_point = use_mouse and capi.mouse.coords() or {
|
local center_point = mode:match("cursor") and capi.mouse.coords() or {
|
||||||
x = abs_widget_geo.x + abs_widget_geo.width / 2,
|
x = abs_widget_geo.x + abs_widget_geo.width / 2,
|
||||||
y = abs_widget_geo.y + abs_widget_geo.height / 2,
|
y = abs_widget_geo.y + abs_widget_geo.height / 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Get the 4 cloest points from `center_point` around the wibox
|
-- Get widget regions for both axis
|
||||||
local points = {
|
local cs = get_cross_sections(abs_widget_geo, mode)
|
||||||
left = {x = dgeo.x , y = center_point.y },
|
|
||||||
right = {x = dgeo.x + dgeo.width , y = center_point.y },
|
|
||||||
top = {x = center_point.x , y = dgeo.y },
|
-- Get the 4 closest points from `center_point` around the wibox
|
||||||
bottom = {x = center_point.x , y = dgeo.y + dgeo.height },
|
local regions = {
|
||||||
|
left = {x = cs.h.x , y = cs.h.y },
|
||||||
|
right = {x = cs.h.x+cs.h.width, y = cs.h.y },
|
||||||
|
top = {x = cs.v.x , y = cs.v.y },
|
||||||
|
bottom = {x = cs.v.x , y = cs.v.y+cs.v.height},
|
||||||
}
|
}
|
||||||
|
|
||||||
local s = geo.drawable.screen or screen.getbycoord(
|
-- Assume the section is part of a single screen until someone complain.
|
||||||
|
-- It is much faster to compute and getting it wrong probably have no side
|
||||||
|
-- effects.
|
||||||
|
local s = geo.drawable and geo.drawable.screen or screen.getbycoord(
|
||||||
center_point.x,
|
center_point.x,
|
||||||
center_point.y
|
center_point.y
|
||||||
)
|
)
|
||||||
|
|
||||||
-- Compute the distance (dp) between the `center_point` and the sides
|
-- Compute the distance (dp) between the `center_point` and the sides.
|
||||||
for k, v in pairs(points) do
|
-- This is only relevant for "cursor" and "cursor_inside" modes.
|
||||||
|
for k, v in pairs(regions) do
|
||||||
local dx, dy = v.x - center_point.x, v.y - center_point.y
|
local dx, dy = v.x - center_point.x, v.y - center_point.y
|
||||||
dps[k] = {
|
|
||||||
distance = math.sqrt(dx*dx + dy*dy),
|
v.distance = math.sqrt(dx*dx + dy*dy)
|
||||||
x = v.x,
|
v.width = cs.v.width
|
||||||
y = v.y,
|
v.height = cs.h.height
|
||||||
screen = s
|
v.screen = s
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
return regions
|
||||||
-- Case 2: A random geometry
|
|
||||||
--TODO
|
|
||||||
end
|
|
||||||
|
|
||||||
return dps
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @tparam drawable d A wibox or client
|
-- @tparam drawable d A wibox or client
|
||||||
|
@ -164,7 +322,7 @@ end
|
||||||
-- @tparam[opt={}] table preferred_positions The preferred positions (position as key,
|
-- @tparam[opt={}] table preferred_positions The preferred positions (position as key,
|
||||||
-- and index as value)
|
-- and index as value)
|
||||||
-- @treturn string The choosen position
|
-- @treturn string The choosen position
|
||||||
function module.move_relative(d, points, preferred_positions)
|
function module.move_relative(d, points, preferred_positions) --TODO inside/outside
|
||||||
local w,h = d.width, d.height
|
local w,h = d.width, d.height
|
||||||
|
|
||||||
local pref_idx, pref_name = 99, nil
|
local pref_idx, pref_name = 99, nil
|
||||||
|
|
23
radial.lua
23
radial.lua
|
@ -14,6 +14,7 @@ local wibox = require( "wibox" )
|
||||||
local tag = require( "awful.tag" )
|
local tag = require( "awful.tag" )
|
||||||
local color = require( "gears.color" )
|
local color = require( "gears.color" )
|
||||||
local cairo = require( "lgi" ).cairo
|
local cairo = require( "lgi" ).cairo
|
||||||
|
local shape = require( "gears.shape" )
|
||||||
|
|
||||||
local default = {width=90,height=30,radius=40,base_radius=60}
|
local default = {width=90,height=30,radius=40,base_radius=60}
|
||||||
|
|
||||||
|
@ -114,14 +115,28 @@ function module.radial_client_select(args)
|
||||||
data.indicator.cr:set_operator(cairo.Operator.SOURCE)
|
data.indicator.cr:set_operator(cairo.Operator.SOURCE)
|
||||||
end
|
end
|
||||||
data.indicator.cr:set_source_rgb(1,0,0)
|
data.indicator.cr:set_source_rgb(1,0,0)
|
||||||
data.indicator.cr:arc ( data.width/2 + (default.base_radius-20)*math.cos(angle),data.width/2 + (default.base_radius-20)*math.sin(angle),5,0,2*math.pi )
|
|
||||||
data.indicator.cr:close_path()
|
-- The Inner dot around the dotted circle
|
||||||
|
local littledot_rad = 5
|
||||||
|
local dot = shape.transform(shape.circle) : translate(
|
||||||
|
data.width/2 + (default.base_radius-20)*math.cos(angle) -littledot_rad,
|
||||||
|
data.width/2 + (default.base_radius-20)*math.sin(angle) -littledot_rad
|
||||||
|
)
|
||||||
|
|
||||||
|
dot(data.indicator.cr, 2*littledot_rad, 2*littledot_rad)
|
||||||
data.indicator.cr:fill()
|
data.indicator.cr:fill()
|
||||||
|
|
||||||
|
-- The little arc on top of the border
|
||||||
data.indicator.cr:set_line_width(4)
|
data.indicator.cr:set_line_width(4)
|
||||||
data.indicator.cr:arc( data.width/2,data.height/2,default.radius + default.base_radius ,angle-0.15,angle+0.15 )
|
data.indicator.cr:arc( data.width/2,data.height/2,default.radius + default.base_radius ,angle-0.15,angle+0.15 )
|
||||||
data.indicator.cr:stroke()
|
data.indicator.cr:stroke()
|
||||||
data.indicator.cr:arc ( data.width/2+170,data.height/2,10,0,2*math.pi )
|
|
||||||
data.indicator.cr:close_path()
|
-- The Big red dot TODO make it move
|
||||||
|
dot = shape.transform(shape.circle) : translate(
|
||||||
|
data.width/2+170 -2*littledot_rad,
|
||||||
|
data.height/2 -2*littledot_rad
|
||||||
|
)
|
||||||
|
dot(data.indicator.cr, 4*littledot_rad, 4*littledot_rad)
|
||||||
data.indicator.cr:fill()
|
data.indicator.cr:fill()
|
||||||
data.angle_cache = data.angle
|
data.angle_cache = data.angle
|
||||||
end
|
end
|
||||||
|
|
|
@ -162,9 +162,9 @@ end
|
||||||
-- direction to avoid going off-screen.
|
-- direction to avoid going off-screen.
|
||||||
-- @param[opt=mouse.coords()] geo A geometry table. It is given as parameter
|
-- @param[opt=mouse.coords()] geo A geometry table. It is given as parameter
|
||||||
-- from buttons callbacks and signals such as `mouse::enter`.
|
-- from buttons callbacks and signals such as `mouse::enter`.
|
||||||
-- @param use_mouse Use the mouse position instead of the widget center as
|
-- @param mode Use the mouse position instead of the widget center as
|
||||||
-- reference point.
|
-- reference point.
|
||||||
function wb_func:move_by_parent(geo, use_mouse)
|
function wb_func:move_by_parent(geo, mode)
|
||||||
if rawget(self, "is_relative") == false then return end
|
if rawget(self, "is_relative") == false then return end
|
||||||
|
|
||||||
local dps = placement.get_relative_points(geo, mode)
|
local dps = placement.get_relative_points(geo, mode)
|
||||||
|
|
|
@ -41,7 +41,7 @@ end
|
||||||
|
|
||||||
local function get_extents(text, height)
|
local function get_extents(text, height)
|
||||||
local l = init_pango(height)
|
local l = init_pango(height)
|
||||||
l.text = text
|
l.text = text or ""
|
||||||
return l:get_pixel_extents()
|
return l:get_pixel_extents()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue