Merge pull request #878 from Elv13/geometry_overhaul_p3.02
Geometry overhaul part 3.02: Wibars
This commit is contained in:
commit
32eeaa9513
|
@ -196,7 +196,7 @@ awful.screen.connect_for_each_screen(function(s)
|
||||||
mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
|
mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)
|
||||||
|
|
||||||
-- Create the wibox
|
-- Create the wibox
|
||||||
mywibox[s] = awful.wibox({ position = "top", screen = s })
|
mywibox[s] = awful.wibar({ position = "top", screen = s })
|
||||||
|
|
||||||
-- Add widgets to the wibox
|
-- Add widgets to the wibox
|
||||||
mywibox[s]:setup {
|
mywibox[s]:setup {
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
--- Border width.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::border_width*
|
||||||
|
--
|
||||||
|
-- @property border_width
|
||||||
|
-- @param integer
|
||||||
|
|
||||||
|
--- Border color.
|
||||||
|
--
|
||||||
|
-- Please note that this property only support string based 24 bit or 32 bit
|
||||||
|
-- colors:
|
||||||
|
--
|
||||||
|
-- Red Blue
|
||||||
|
-- _| _|
|
||||||
|
-- #FF00FF
|
||||||
|
-- T‾
|
||||||
|
-- Green
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- Red Blue
|
||||||
|
-- _| _|
|
||||||
|
-- #FF00FF00
|
||||||
|
-- T‾ ‾T
|
||||||
|
-- Green Alpha
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::border_color*
|
||||||
|
--
|
||||||
|
-- @property border_color
|
||||||
|
-- @param string
|
||||||
|
|
||||||
|
--- On top of other windows.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::ontop*
|
||||||
|
--
|
||||||
|
-- @property ontop
|
||||||
|
-- @param boolean
|
||||||
|
|
||||||
|
--- The mouse cursor.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::cursor*
|
||||||
|
--
|
||||||
|
-- @property cursor
|
||||||
|
-- @param string
|
||||||
|
-- @see mouse
|
||||||
|
|
||||||
|
--- Visibility.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::visible*
|
||||||
|
--
|
||||||
|
-- @property visible
|
||||||
|
-- @param boolean
|
||||||
|
|
||||||
|
--- The opacity of the wibox, between 0 and 1.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::opacity*
|
||||||
|
--
|
||||||
|
-- @property opacity
|
||||||
|
-- @tparam number opacity (between 0 and 1)
|
||||||
|
|
||||||
|
--- The window type (desktop, normal, dock, ...).
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::type*
|
||||||
|
--
|
||||||
|
-- @property type
|
||||||
|
-- @param string
|
||||||
|
-- @see client.type
|
||||||
|
|
||||||
|
--- The x coordinates.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::x*
|
||||||
|
--
|
||||||
|
-- @property x
|
||||||
|
-- @param integer
|
||||||
|
|
||||||
|
--- The y coordinates.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::y*
|
||||||
|
--
|
||||||
|
-- @property y
|
||||||
|
-- @param integer
|
||||||
|
|
||||||
|
--- The width of the wibox.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::width*
|
||||||
|
--
|
||||||
|
-- @property width
|
||||||
|
-- @param width
|
||||||
|
|
||||||
|
--- The height of the wibox.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::height*
|
||||||
|
--
|
||||||
|
-- @property height
|
||||||
|
-- @param height
|
||||||
|
|
||||||
|
--- The wibox screen.
|
||||||
|
--
|
||||||
|
-- @property screen
|
||||||
|
-- @param screen
|
||||||
|
|
||||||
|
--- The wibox's `drawable`.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::drawable*
|
||||||
|
--
|
||||||
|
-- @property drawable
|
||||||
|
-- @tparam drawable drawable
|
||||||
|
|
||||||
|
--- The widget that the `wibox` displays.
|
||||||
|
-- @property widget
|
||||||
|
-- @param widget
|
||||||
|
|
||||||
|
--- The X window id.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::window*
|
||||||
|
--
|
||||||
|
-- @property window
|
||||||
|
-- @param string
|
||||||
|
-- @see client.window
|
||||||
|
|
||||||
|
--- The wibox's bounding shape as a (native) cairo surface.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::shape_bounding*
|
||||||
|
--
|
||||||
|
-- @property shape_bounding
|
||||||
|
-- @param surface._native
|
||||||
|
|
||||||
|
--- The wibox's clip shape as a (native) cairo surface.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::shape_clip*
|
||||||
|
--
|
||||||
|
-- @property shape_clip
|
||||||
|
-- @param surface._native
|
||||||
|
|
||||||
|
--- Get or set mouse buttons bindings to a wibox.
|
||||||
|
--
|
||||||
|
-- @param buttons_table A table of buttons objects, or nothing.
|
||||||
|
-- @function wibox.buttons
|
||||||
|
|
||||||
|
--- Get or set wibox geometry. That's the same as accessing or setting the x,
|
||||||
|
-- y, width or height properties of a wibox.
|
||||||
|
--
|
||||||
|
-- @param A table with coordinates to modify.
|
||||||
|
-- @return A table with wibox coordinates and geometry.
|
||||||
|
-- @function wibox.geometry
|
||||||
|
|
||||||
|
--- Get or set wibox struts.
|
||||||
|
--
|
||||||
|
-- @param strut A table with new strut, or nothing
|
||||||
|
-- @return The wibox strut in a table.
|
||||||
|
-- @function wibox.struts
|
||||||
|
-- @see client.struts
|
||||||
|
|
||||||
|
--- The default background color.
|
||||||
|
-- @beautiful beautiful.bg_normal
|
||||||
|
-- @see bg
|
||||||
|
|
||||||
|
--- The default foreground (text) color.
|
||||||
|
-- @beautiful beautiful.fg_normal
|
||||||
|
-- @see fg
|
||||||
|
|
||||||
|
--- Set a declarative widget hierarchy description.
|
||||||
|
-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
|
||||||
|
-- @param args An array containing the widgets disposition
|
||||||
|
-- @name setup
|
||||||
|
-- @class function
|
||||||
|
|
||||||
|
--- The background of the wibox.
|
||||||
|
-- @param c The background to use. This must either be a cairo pattern object,
|
||||||
|
-- nil or a string that gears.color() understands.
|
||||||
|
-- @property bg
|
||||||
|
-- @see gears.color
|
||||||
|
|
||||||
|
--- The background image of the drawable.
|
||||||
|
-- If `image` is a function, it will be called with `(context, cr, width, height)`
|
||||||
|
-- as arguments. Any other arguments passed to this method will be appended.
|
||||||
|
-- @param image A background image or a function
|
||||||
|
-- @property bgimage
|
||||||
|
-- @see gears.surface
|
||||||
|
|
||||||
|
--- The foreground (text) of the wibox.
|
||||||
|
-- @param c The foreground to use. This must either be a cairo pattern object,
|
||||||
|
-- nil or a string that gears.color() understands.
|
||||||
|
-- @property fg
|
||||||
|
-- @see gears.color
|
||||||
|
|
||||||
|
--- Find a widget by a point.
|
||||||
|
-- The wibox must have drawn itself at least once for this to work.
|
||||||
|
-- @tparam number x X coordinate of the point
|
||||||
|
-- @tparam number y Y coordinate of the point
|
||||||
|
-- @treturn table A sorted table of widgets positions. The first element is the biggest
|
||||||
|
-- container while the last is the topmost widget. The table contains *x*, *y*,
|
||||||
|
-- *width*, *height* and *widget*.
|
||||||
|
-- @name find_widgets
|
||||||
|
-- @class function
|
|
@ -11,6 +11,7 @@
|
||||||
local util = require("awful.util")
|
local util = require("awful.util")
|
||||||
local spawn = require("awful.spawn")
|
local spawn = require("awful.spawn")
|
||||||
local object = require("gears.object")
|
local object = require("gears.object")
|
||||||
|
local grect = require("gears.geometry").rectangle
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local type = type
|
local type = type
|
||||||
local ipairs = ipairs
|
local ipairs = ipairs
|
||||||
|
@ -197,7 +198,7 @@ function client.swap.bydirection(dir, c, stacked)
|
||||||
for i,cl in ipairs(cltbl) do
|
for i,cl in ipairs(cltbl) do
|
||||||
geomtbl[i] = cl:geometry()
|
geomtbl[i] = cl:geometry()
|
||||||
end
|
end
|
||||||
local target = util.get_rectangle_in_direction(dir, geomtbl, sel:geometry())
|
local target = grect.get_in_direction(dir, geomtbl, sel:geometry())
|
||||||
|
|
||||||
-- If we found a client to swap with, then go for it
|
-- If we found a client to swap with, then go for it
|
||||||
if target then
|
if target then
|
||||||
|
@ -693,6 +694,54 @@ function client.floating.delete(c)
|
||||||
client.object.set_floating(c, nil)
|
client.object.set_floating(c, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- The x coordinates.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::x*
|
||||||
|
--
|
||||||
|
-- @property x
|
||||||
|
-- @param integer
|
||||||
|
|
||||||
|
--- The y coordinates.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::y*
|
||||||
|
--
|
||||||
|
-- @property y
|
||||||
|
-- @param integer
|
||||||
|
|
||||||
|
--- The width of the wibox.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::width*
|
||||||
|
--
|
||||||
|
-- @property width
|
||||||
|
-- @param width
|
||||||
|
|
||||||
|
--- The height of the wibox.
|
||||||
|
--
|
||||||
|
-- **Signal:**
|
||||||
|
--
|
||||||
|
-- * *property::height*
|
||||||
|
--
|
||||||
|
-- @property height
|
||||||
|
-- @param height
|
||||||
|
|
||||||
|
-- Add the geometry helpers to match the wibox API
|
||||||
|
for _, v in ipairs {"x", "y", "width", "height"} do
|
||||||
|
client.object["get_"..v] = function(c)
|
||||||
|
return c:geometry()[v]
|
||||||
|
end
|
||||||
|
|
||||||
|
client.object["set_"..v] = function(c, value)
|
||||||
|
return c:geometry({[v] = value})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Restore (=unminimize) a random client.
|
--- Restore (=unminimize) a random client.
|
||||||
-- @function awful.client.restore
|
-- @function awful.client.restore
|
||||||
-- @param s The screen to use.
|
-- @param s The screen to use.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
-- @release @AWESOME_VERSION@
|
-- @release @AWESOME_VERSION@
|
||||||
-- @submodule client
|
-- @submodule client
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
local util = require("awful.util")
|
local grect = require("gears.geometry").rectangle
|
||||||
|
|
||||||
local capi =
|
local capi =
|
||||||
{
|
{
|
||||||
|
@ -168,7 +168,7 @@ function focus.bydirection(dir, c, stacked)
|
||||||
geomtbl[i] = cl:geometry()
|
geomtbl[i] = cl:geometry()
|
||||||
end
|
end
|
||||||
|
|
||||||
local target = util.get_rectangle_in_direction(dir, geomtbl, sel:geometry())
|
local target = grect.get_in_direction(dir, geomtbl, sel:geometry())
|
||||||
|
|
||||||
-- If we found a client to focus, then do it.
|
-- If we found a client to focus, then do it.
|
||||||
if target then
|
if target then
|
||||||
|
@ -200,7 +200,7 @@ function focus.global_bydirection(dir, c, stacked)
|
||||||
for i,cl in ipairs(cltbl) do
|
for i,cl in ipairs(cltbl) do
|
||||||
geomtbl[i] = cl:geometry()
|
geomtbl[i] = cl:geometry()
|
||||||
end
|
end
|
||||||
local target = util.get_rectangle_in_direction(dir, geomtbl, scr.geometry)
|
local target = grect.get_in_direction(dir, geomtbl, scr.geometry)
|
||||||
|
|
||||||
if target then
|
if target then
|
||||||
cltbl[target]:emit_signal("request::activate",
|
cltbl[target]:emit_signal("request::activate",
|
||||||
|
|
|
@ -51,6 +51,7 @@ return
|
||||||
remote = require("awful.remote");
|
remote = require("awful.remote");
|
||||||
key = require("awful.key");
|
key = require("awful.key");
|
||||||
button = require("awful.button");
|
button = require("awful.button");
|
||||||
|
wibar = require("awful.wibar");
|
||||||
wibox = require("awful.wibox");
|
wibox = require("awful.wibox");
|
||||||
startup_notification = require("awful.startup_notification");
|
startup_notification = require("awful.startup_notification");
|
||||||
tooltip = require("awful.tooltip");
|
tooltip = require("awful.tooltip");
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
-- Grab environment we need
|
-- Grab environment we need
|
||||||
local layout = require("awful.layout")
|
local layout = require("awful.layout")
|
||||||
local aplace = require("awful.placement")
|
local aplace = require("awful.placement")
|
||||||
local awibox = require("awful.wibox")
|
|
||||||
local util = require("awful.util")
|
local util = require("awful.util")
|
||||||
local type = type
|
local type = type
|
||||||
local ipairs = ipairs
|
local ipairs = ipairs
|
||||||
|
@ -123,43 +122,31 @@ end
|
||||||
|
|
||||||
--- Move the wibox under the cursor.
|
--- Move the wibox under the cursor.
|
||||||
-- @function awful.mouse.wibox.move
|
-- @function awful.mouse.wibox.move
|
||||||
--@param w The wibox to move, or none to use that under the pointer
|
--@tparam wibox w The wibox to move, or none to use that under the pointer
|
||||||
function mouse.wibox.move(w)
|
function mouse.wibox.move(w)
|
||||||
w = w or mouse.wibox_under_pointer()
|
w = w or mouse.wibox_under_pointer()
|
||||||
if not w then return end
|
if not w then return end
|
||||||
|
|
||||||
|
if not w
|
||||||
|
or w.type == "desktop"
|
||||||
|
or w.type == "splash"
|
||||||
|
or w.type == "dock" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Compute the offset
|
||||||
|
local coords = capi.mouse.coords()
|
||||||
|
local geo = aplace.centered(capi.mouse,{parent=w, pretend=true})
|
||||||
|
|
||||||
local offset = {
|
local offset = {
|
||||||
x = w.x - capi.mouse.coords().x,
|
x = geo.x - coords.x,
|
||||||
y = w.y - capi.mouse.coords().y
|
y = geo.y - coords.y,
|
||||||
}
|
}
|
||||||
|
|
||||||
capi.mousegrabber.run(function (_mouse)
|
mouse.resize(w, "mouse.move", {
|
||||||
local button_down = false
|
placement = aplace.under_mouse,
|
||||||
if awibox.get_position(w) == "floating" then
|
offset = offset
|
||||||
w.x = capi.mouse.coords().x + offset.x
|
})
|
||||||
w.y = capi.mouse.coords().y + offset.y
|
|
||||||
else
|
|
||||||
local wa = capi.screen[capi.mouse.screen].workarea
|
|
||||||
|
|
||||||
if capi.mouse.coords()["y"] > wa.y + wa.height - 10 then
|
|
||||||
awibox.set_position(w, "bottom", w.screen)
|
|
||||||
elseif capi.mouse.coords()["y"] < wa.y + 10 then
|
|
||||||
awibox.set_position(w, "top", w.screen)
|
|
||||||
elseif capi.mouse.coords()["x"] > wa.x + wa.width - 10 then
|
|
||||||
awibox.set_position(w, "right", w.screen)
|
|
||||||
elseif capi.mouse.coords()["x"] < wa.x + 10 then
|
|
||||||
awibox.set_position(w, "left", w.screen)
|
|
||||||
end
|
|
||||||
w.screen = capi.mouse.screen
|
|
||||||
end
|
|
||||||
for _, v in ipairs(_mouse.buttons) do
|
|
||||||
if v then button_down = true end
|
|
||||||
end
|
|
||||||
if not button_down then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end, "fleur")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get a client corner coordinates.
|
--- Get a client corner coordinates.
|
||||||
|
@ -234,22 +221,11 @@ function mouse.resize_handler(c, context, hints)
|
||||||
local lay = c.screen.selected_tag.layout
|
local lay = c.screen.selected_tag.layout
|
||||||
|
|
||||||
if lay == layout.suit.floating or c.floating then
|
if lay == layout.suit.floating or c.floating then
|
||||||
local offset = hints and hints.offset or {}
|
|
||||||
|
|
||||||
if type(offset) == "number" then
|
|
||||||
offset = {
|
|
||||||
x = offset,
|
|
||||||
y = offset,
|
|
||||||
width = offset,
|
|
||||||
height = offset,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
c:geometry {
|
c:geometry {
|
||||||
x = hints.x + (offset.x or 0 ),
|
x = hints.x,
|
||||||
y = hints.y + (offset.y or 0 ),
|
y = hints.y,
|
||||||
width = hints.width + (offset.width or 0 ),
|
width = hints.width,
|
||||||
height = hints.height + (offset.height or 0 ),
|
height = hints.height,
|
||||||
}
|
}
|
||||||
elseif lay.resize_handler then
|
elseif lay.resize_handler then
|
||||||
lay.resize_handler(c, context, hints)
|
lay.resize_handler(c, context, hints)
|
||||||
|
|
|
@ -51,6 +51,11 @@
|
||||||
--
|
--
|
||||||
-- **attach** (*boolean*):
|
-- **attach** (*boolean*):
|
||||||
--
|
--
|
||||||
|
-- When the parent geometry (like the screen) changes, re-apply the placement
|
||||||
|
-- function. This will add a `detach_callback` function to the drawable. Call
|
||||||
|
-- this to detach the function. This will be called automatically when a new
|
||||||
|
-- attached function is set.
|
||||||
|
--
|
||||||
-- **offset** (*table or number*):
|
-- **offset** (*table or number*):
|
||||||
--
|
--
|
||||||
-- The offset(s) to apply to the new geometry.
|
-- The offset(s) to apply to the new geometry.
|
||||||
|
@ -88,6 +93,7 @@ local capi =
|
||||||
local client = require("awful.client")
|
local client = require("awful.client")
|
||||||
local layout = require("awful.layout")
|
local layout = require("awful.layout")
|
||||||
local a_screen = require("awful.screen")
|
local a_screen = require("awful.screen")
|
||||||
|
local grect = require("gears.geometry").rectangle
|
||||||
local util = require("awful.util")
|
local util = require("awful.util")
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
local dpi = require("beautiful").xresources.apply_dpi
|
||||||
|
|
||||||
|
@ -96,6 +102,15 @@ local function get_screen(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
local wrap_client = nil
|
local wrap_client = nil
|
||||||
|
local placement
|
||||||
|
|
||||||
|
-- Store function -> keys
|
||||||
|
local reverse_align_map = {}
|
||||||
|
|
||||||
|
-- Forward declarations
|
||||||
|
local area_common
|
||||||
|
local wibox_update_strut
|
||||||
|
local attach
|
||||||
|
|
||||||
--- Allow multiple placement functions to be daisy chained.
|
--- Allow multiple placement functions to be daisy chained.
|
||||||
-- This also allow the functions to be aware they are being chained and act
|
-- This also allow the functions to be aware they are being chained and act
|
||||||
|
@ -123,7 +138,8 @@ local function compose(...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = wrap_client(function(d, args, ...)
|
local ret
|
||||||
|
ret = wrap_client(function(d, args, ...)
|
||||||
local rets = {}
|
local rets = {}
|
||||||
local last_geo = nil
|
local last_geo = nil
|
||||||
|
|
||||||
|
@ -134,13 +150,16 @@ local function compose(...)
|
||||||
-- Only apply the geometry once, not once per chain node, to do this,
|
-- Only apply the geometry once, not once per chain node, to do this,
|
||||||
-- Force the "pretend" argument and restore the original value for
|
-- Force the "pretend" argument and restore the original value for
|
||||||
-- the last node.
|
-- the last node.
|
||||||
local pretend_real = args.pretend
|
local attach_real = args.attach
|
||||||
|
|
||||||
args.pretend = true
|
args.pretend = true
|
||||||
|
args.attach = false
|
||||||
|
args.offset = {}
|
||||||
|
|
||||||
for k, f in ipairs(queue) do
|
for k, f in ipairs(queue) do
|
||||||
if k == #queue then
|
if k == #queue then
|
||||||
args.pretend = pretend_real or false
|
-- Let them fallback to the parent table
|
||||||
|
args.pretend = nil
|
||||||
|
args.offset = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local r = {f(d, args, ...)}
|
local r = {f(d, args, ...)}
|
||||||
|
@ -160,6 +179,11 @@ local function compose(...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if attach_real then
|
||||||
|
args.attach = true
|
||||||
|
attach(d, ret, args)
|
||||||
|
end
|
||||||
|
|
||||||
return last_geo, rets
|
return last_geo, rets
|
||||||
end, "compose")
|
end, "compose")
|
||||||
|
|
||||||
|
@ -189,7 +213,7 @@ local placement_private = {}
|
||||||
--
|
--
|
||||||
-- (awful.placement.no_overlap + awful.placement.no_offscreen)(c)
|
-- (awful.placement.no_overlap + awful.placement.no_offscreen)(c)
|
||||||
--
|
--
|
||||||
local placement = setmetatable({}, {
|
placement = setmetatable({}, {
|
||||||
__index = placement_private,
|
__index = placement_private,
|
||||||
__newindex = function(_, k, f)
|
__newindex = function(_, k, f)
|
||||||
placement_private[k] = wrap_client(f, k)
|
placement_private[k] = wrap_client(f, k)
|
||||||
|
@ -221,9 +245,6 @@ local align_map = {
|
||||||
center_horizontal = function(sw, _ , dw, _ ) return {x=sw/2-dw/2, y= nil } end,
|
center_horizontal = function(sw, _ , dw, _ ) return {x=sw/2-dw/2, y= nil } end,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Store function -> keys
|
|
||||||
local reverse_align_map = {}
|
|
||||||
|
|
||||||
-- Some parameters to correctly compute the final size
|
-- Some parameters to correctly compute the final size
|
||||||
local resize_to_point_map = {
|
local resize_to_point_map = {
|
||||||
-- Corners
|
-- Corners
|
||||||
|
@ -259,39 +280,61 @@ local function store_geometry(d, reqtype)
|
||||||
data[d][reqtype].screen = d.screen
|
data[d][reqtype].screen = d.screen
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Apply some modifications before applying the new geometry.
|
--- Get the margins and offset
|
||||||
-- @tparam table new_geo The new geometry
|
-- @tparam table args The arguments
|
||||||
-- @tparam table args The common arguments
|
-- @treturn table The margins
|
||||||
-- @treturn table|nil The new geometry
|
-- @treturn table The offsets
|
||||||
local function fix_new_geometry(new_geo, args)
|
local function get_decoration(args)
|
||||||
if args.pretend or not new_geo then return nil end
|
local offset = args.offset
|
||||||
|
|
||||||
local offset = args.offset or {}
|
-- Offset are "blind" values added to the output
|
||||||
|
offset = type(offset) == "number" and {
|
||||||
if type(offset) == "number" then
|
|
||||||
offset = {
|
|
||||||
x = offset,
|
x = offset,
|
||||||
y = offset,
|
y = offset,
|
||||||
width = offset,
|
width = offset,
|
||||||
height = offset,
|
height = offset,
|
||||||
|
} or args.offset or {}
|
||||||
|
|
||||||
|
-- Margins are distances on each side to substract from the area`
|
||||||
|
local m = type(args.margins) == "table" and args.margins or {
|
||||||
|
left = args.margins or 0 , right = args.margins or 0,
|
||||||
|
top = args.margins or 0 , bottom = args.margins or 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return m, offset
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Apply some modifications before applying the new geometry.
|
||||||
|
-- @tparam table new_geo The new geometry
|
||||||
|
-- @tparam table args The common arguments
|
||||||
|
-- @tparam boolean force Always ajust the geometry, even in pretent mode. This
|
||||||
|
-- should only be used when returning the final geometry as it would otherwise
|
||||||
|
-- mess the pipeline.
|
||||||
|
-- @treturn table|nil The new geometry
|
||||||
|
local function fix_new_geometry(new_geo, args, force)
|
||||||
|
if (args.pretend and not force) or not new_geo then return nil end
|
||||||
|
|
||||||
|
local m, offset = get_decoration(args)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x = new_geo.x and (new_geo.x + (offset.x or 0)),
|
x = new_geo.x and (new_geo.x + (offset.x or 0) + (m.left or 0) ),
|
||||||
y = new_geo.y and (new_geo.y + (offset.y or 0)),
|
y = new_geo.y and (new_geo.y + (offset.y or 0) + (m.top or 0) ),
|
||||||
width = new_geo.width and (new_geo.width + (offset.width or 0)),
|
width = new_geo.width and math.max(
|
||||||
height = new_geo.height and (new_geo.height + (offset.height or 0)),
|
1, (new_geo.width + (offset.width or 0) - (m.left or 0) - (m.right or 0) )
|
||||||
|
),
|
||||||
|
height = new_geo.height and math.max(
|
||||||
|
1, (new_geo.height + (offset.height or 0) - (m.top or 0) - (m.bottom or 0) )
|
||||||
|
),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the area covered by a drawin.
|
-- Get the area covered by a drawin.
|
||||||
-- @param d The drawin
|
-- @param d The drawin
|
||||||
-- @tparam[opt=nil] table new_geo A new geometry
|
-- @tparam[opt=nil] table new_geo A new geometry
|
||||||
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
|
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
|
||||||
-- @tparam table args the method arguments
|
-- @tparam table args the method arguments
|
||||||
-- @treturn The drawin's area.
|
-- @treturn The drawin's area.
|
||||||
local function area_common(d, new_geo, ignore_border_width, args)
|
area_common = function(d, new_geo, ignore_border_width, args)
|
||||||
-- The C side expect no arguments, nil isn't valid
|
-- The C side expect no arguments, nil isn't valid
|
||||||
local geometry = new_geo and d:geometry(new_geo) or d:geometry()
|
local geometry = new_geo and d:geometry(new_geo) or d:geometry()
|
||||||
local border = ignore_border_width and 0 or d.border_width or 0
|
local border = ignore_border_width and 0 or d.border_width or 0
|
||||||
|
@ -316,7 +359,6 @@ end
|
||||||
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
|
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
|
||||||
-- @treturn table A table with *x*, *y*, *width* and *height*.
|
-- @treturn table A table with *x*, *y*, *width* and *height*.
|
||||||
local function geometry_common(obj, args, new_geo, ignore_border_width)
|
local function geometry_common(obj, args, new_geo, ignore_border_width)
|
||||||
|
|
||||||
-- Store the current geometry in a singleton-memento
|
-- Store the current geometry in a singleton-memento
|
||||||
if args.store_geometry and new_geo and args.context then
|
if args.store_geometry and new_geo and args.context then
|
||||||
store_geometry(obj, args.context)
|
store_geometry(obj, args.context)
|
||||||
|
@ -338,16 +380,13 @@ local function geometry_common(obj, args, new_geo, ignore_border_width)
|
||||||
|
|
||||||
-- Apply the margins
|
-- Apply the margins
|
||||||
if args.margins then
|
if args.margins then
|
||||||
local delta = type(args.margins) == "table" and args.margins or {
|
local delta = get_decoration(args)
|
||||||
left = args.margins , right = args.margins,
|
|
||||||
top = args.margins , bottom = args.margins
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x = dgeo.x + (delta.left or 0),
|
x = dgeo.x - (delta.left or 0),
|
||||||
y = dgeo.y + (delta.top or 0),
|
y = dgeo.y - (delta.top or 0),
|
||||||
width = dgeo.width - (delta.left or 0) - (delta.right or 0),
|
width = dgeo.width + (delta.left or 0) + (delta.right or 0),
|
||||||
height = dgeo.height - (delta.top or 0) - (delta.bottom or 0),
|
height = dgeo.height + (delta.top or 0) + (delta.bottom or 0),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -367,12 +406,18 @@ end
|
||||||
-- @tparam table args the method arguments
|
-- @tparam table args the method arguments
|
||||||
-- @treturn table A table with *x*, *y*, *width* and *height*.
|
-- @treturn table A table with *x*, *y*, *width* and *height*.
|
||||||
local function get_parent_geometry(obj, args)
|
local function get_parent_geometry(obj, args)
|
||||||
|
-- Didable override_geometry, context and other to avoid mutating the state
|
||||||
|
-- or using the wrong geo.
|
||||||
|
|
||||||
if args.bounding_rect then
|
if args.bounding_rect then
|
||||||
return args.bounding_rect
|
return args.bounding_rect
|
||||||
elseif args.parent then
|
elseif args.parent then
|
||||||
return geometry_common(args.parent, args)
|
return geometry_common(args.parent, {})
|
||||||
elseif obj.screen then
|
elseif obj.screen then
|
||||||
return geometry_common(obj.screen, args)
|
return geometry_common(obj.screen, {
|
||||||
|
honor_padding = args.honor_padding,
|
||||||
|
honor_workarea = args.honor_workarea
|
||||||
|
})
|
||||||
else
|
else
|
||||||
return geometry_common(capi.screen[capi.mouse.screen], args)
|
return geometry_common(capi.screen[capi.mouse.screen], args)
|
||||||
end
|
end
|
||||||
|
@ -405,7 +450,7 @@ local function move_into_geometry(source, target)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update the workarea
|
-- Update the workarea
|
||||||
local function wibox_update_strut(d, position)
|
wibox_update_strut = function(d, position, args)
|
||||||
-- If the drawable isn't visible, remove the struts
|
-- If the drawable isn't visible, remove the struts
|
||||||
if not d.visible then
|
if not d.visible then
|
||||||
d:struts { left = 0, right = 0, bottom = 0, top = 0 }
|
d:struts { left = 0, right = 0, bottom = 0, top = 0 }
|
||||||
|
@ -420,16 +465,18 @@ local function wibox_update_strut(d, position)
|
||||||
-- the workarea
|
-- the workarea
|
||||||
local struts = { left = 0, right = 0, bottom = 0, top = 0 }
|
local struts = { left = 0, right = 0, bottom = 0, top = 0 }
|
||||||
|
|
||||||
|
local m = get_decoration(args)
|
||||||
|
|
||||||
if vertical then
|
if vertical then
|
||||||
for _, v in ipairs {"right", "left"} do
|
for _, v in ipairs {"right", "left"} do
|
||||||
if (not position) or position:match(v) then
|
if (not position) or position:match(v) then
|
||||||
struts[v] = geo.width
|
struts[v] = geo.width + m[v]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
for _, v in ipairs {"top", "bottom"} do
|
for _, v in ipairs {"top", "bottom"} do
|
||||||
if (not position) or position:match(v) then
|
if (not position) or position:match(v) then
|
||||||
struts[v] = geo.height
|
struts[v] = geo.height + m[v]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -438,16 +485,18 @@ local function wibox_update_strut(d, position)
|
||||||
d:struts(struts)
|
d:struts(struts)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Pin a drawable to a placement function.
|
-- Pin a drawable to a placement function.
|
||||||
-- Automatically update the position when the size change.
|
-- Automatically update the position when the size change.
|
||||||
-- All other arguments will be passed to the `position` function (if any)
|
-- All other arguments will be passed to the `position` function (if any)
|
||||||
-- @tparam[opt=client.focus] drawable d A drawable (like `client`, `mouse`
|
-- @tparam[opt=client.focus] drawable d A drawable (like `client`, `mouse`
|
||||||
-- or `wibox`)
|
-- or `wibox`)
|
||||||
-- @param position_f A position name (see `align`) or a position function
|
-- @param position_f A position name (see `align`) or a position function
|
||||||
-- @tparam[opt={}] table args Other arguments
|
-- @tparam[opt={}] table args Other arguments
|
||||||
local function attach(d, position_f, args)
|
attach = function(d, position_f, args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
|
if args.pretend then return end
|
||||||
|
|
||||||
if not args.attach then return end
|
if not args.attach then return end
|
||||||
|
|
||||||
-- Avoid a connection loop
|
-- Avoid a connection loop
|
||||||
|
@ -462,110 +511,78 @@ local function attach(d, position_f, args)
|
||||||
|
|
||||||
if not position_f then return end
|
if not position_f then return end
|
||||||
|
|
||||||
|
-- If there is multiple attached function, there is an high risk of infinite
|
||||||
|
-- loop. While some combinaisons are harmless, other are very hard to debug.
|
||||||
|
--
|
||||||
|
-- Use the placement composition to build explicit multi step attached
|
||||||
|
-- placement functions.
|
||||||
|
if d.detach_callback then
|
||||||
|
d.detach_callback()
|
||||||
|
d.detach_callback = nil
|
||||||
|
end
|
||||||
|
|
||||||
local function tracker()
|
local function tracker()
|
||||||
position_f(d, args)
|
position_f(d, args)
|
||||||
end
|
end
|
||||||
|
|
||||||
d:connect_signal("property::width" , tracker)
|
d:connect_signal("property::width" , tracker)
|
||||||
d:connect_signal("property::height" , tracker)
|
d:connect_signal("property::height" , tracker)
|
||||||
|
d:connect_signal("property::border_width", tracker)
|
||||||
|
|
||||||
tracker()
|
|
||||||
|
|
||||||
if args.update_workarea then
|
|
||||||
local function tracker_struts()
|
local function tracker_struts()
|
||||||
--TODO this is too fragile and doesn't work with all methods.
|
--TODO this is too fragile and doesn't work with all methods.
|
||||||
wibox_update_strut(d, reverse_align_map[position_f])
|
wibox_update_strut(d, d.position or reverse_align_map[position_f], args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local parent = args.parent or d.screen
|
||||||
|
|
||||||
|
if args.update_workarea then
|
||||||
d:connect_signal("property::geometry" , tracker_struts)
|
d:connect_signal("property::geometry" , tracker_struts)
|
||||||
d:connect_signal("property::visible" , tracker_struts)
|
d:connect_signal("property::visible" , tracker_struts)
|
||||||
|
capi.client.connect_signal("property::struts", tracker_struts)
|
||||||
|
|
||||||
tracker_struts()
|
tracker_struts()
|
||||||
|
elseif parent == d.screen then
|
||||||
|
if args.honor_workarea then
|
||||||
|
parent:connect_signal("property::workarea", tracker)
|
||||||
|
end
|
||||||
|
|
||||||
|
if args.honor_padding then
|
||||||
|
parent:connect_signal("property::padding", tracker)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If there is a parent drawable, screen or mouse, also track it
|
-- If there is a parent drawable, screen or mouse, also track it
|
||||||
local parent = args.parent or d.screen
|
|
||||||
if parent then
|
if parent then
|
||||||
args.parent:connect_signal("property::geometry" , tracker)
|
parent:connect_signal("property::geometry" , tracker)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if an area intersect another area.
|
-- Create a way to detach a placement function
|
||||||
-- @param a The area.
|
d:add_signal("property::detach_callback")
|
||||||
-- @param b The other area.
|
function d.detach_callback()
|
||||||
-- @return True if they intersect, false otherwise.
|
d:disconnect_signal("property::width" , tracker)
|
||||||
local function area_intersect_area(a, b)
|
d:disconnect_signal("property::height" , tracker)
|
||||||
return (b.x < a.x + a.width
|
d:disconnect_signal("property::border_width", tracker)
|
||||||
and b.x + b.width > a.x
|
if parent then
|
||||||
and b.y < a.y + a.height
|
parent:disconnect_signal("property::geometry" , tracker)
|
||||||
and b.y + b.height > a.y)
|
|
||||||
|
if parent == d.screen then
|
||||||
|
if args.honor_workarea then
|
||||||
|
parent:disconnect_signal("property::workarea", tracker)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the intersect area between a and b.
|
if args.honor_padding then
|
||||||
-- @param a The area.
|
parent:disconnect_signal("property::padding", tracker)
|
||||||
-- @param b The other area.
|
|
||||||
-- @return The intersect area.
|
|
||||||
local function area_intersect_area_get(a, b)
|
|
||||||
local g = {}
|
|
||||||
g.x = math.max(a.x, b.x)
|
|
||||||
g.y = math.max(a.y, b.y)
|
|
||||||
g.width = math.min(a.x + a.width, b.x + b.width) - g.x
|
|
||||||
g.height = math.min(a.y + a.height, b.y + b.height) - g.y
|
|
||||||
return g
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove an area from a list, splitting the space between several area that
|
|
||||||
-- can overlap.
|
|
||||||
-- @param areas Table of areas.
|
|
||||||
-- @param elem Area to remove.
|
|
||||||
-- @return The new area list.
|
|
||||||
local function area_remove(areas, elem)
|
|
||||||
for i = #areas, 1, -1 do
|
|
||||||
-- Check if the 'elem' intersect
|
|
||||||
if area_intersect_area(areas[i], elem) then
|
|
||||||
-- It does? remove it
|
|
||||||
local r = table.remove(areas, i)
|
|
||||||
local inter = area_intersect_area_get(r, elem)
|
|
||||||
|
|
||||||
if inter.x > r.x then
|
|
||||||
table.insert(areas, {
|
|
||||||
x = r.x,
|
|
||||||
y = r.y,
|
|
||||||
width = inter.x - r.x,
|
|
||||||
height = r.height
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if inter.y > r.y then
|
|
||||||
table.insert(areas, {
|
|
||||||
x = r.x,
|
|
||||||
y = r.y,
|
|
||||||
width = r.width,
|
|
||||||
height = inter.y - r.y
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if inter.x + inter.width < r.x + r.width then
|
|
||||||
table.insert(areas, {
|
|
||||||
x = inter.x + inter.width,
|
|
||||||
y = r.y,
|
|
||||||
width = (r.x + r.width) - (inter.x + inter.width),
|
|
||||||
height = r.height
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if inter.y + inter.height < r.y + r.height then
|
|
||||||
table.insert(areas, {
|
|
||||||
x = r.x,
|
|
||||||
y = inter.y + inter.height,
|
|
||||||
width = r.width,
|
|
||||||
height = (r.y + r.height) - (inter.y + inter.height)
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return areas
|
if args.update_workarea then
|
||||||
|
d:disconnect_signal("property::geometry" , tracker_struts)
|
||||||
|
d:disconnect_signal("property::visible" , tracker_struts)
|
||||||
|
capi.client.disconnect_signal("property::struts", tracker_struts)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Convert 2 points into a rectangle
|
-- Convert 2 points into a rectangle
|
||||||
|
@ -633,7 +650,7 @@ function placement.closest_corner(d, args)
|
||||||
local new_args = setmetatable({position = corner}, {__index=args})
|
local new_args = setmetatable({position = corner}, {__index=args})
|
||||||
local ngeo = placement_private.align(d, new_args)
|
local ngeo = placement_private.align(d, new_args)
|
||||||
|
|
||||||
return ngeo, corner
|
return fix_new_geometry(ngeo, args, true), corner
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Place the client so no part of it will be outside the screen (workarea).
|
--- Place the client so no part of it will be outside the screen (workarea).
|
||||||
|
@ -685,7 +702,7 @@ function placement.no_overlap(c)
|
||||||
local areas = { screen.workarea }
|
local areas = { screen.workarea }
|
||||||
for _, cl in pairs(cls) do
|
for _, cl in pairs(cls) do
|
||||||
if cl ~= c and cl.type ~= "desktop" and (cl.floating or curlay == layout.suit.floating) then
|
if cl ~= c and cl.type ~= "desktop" and (cl.floating or curlay == layout.suit.floating) then
|
||||||
areas = area_remove(areas, area_common(cl))
|
areas = grect.area_remove(areas, area_common(cl))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -751,7 +768,9 @@ function placement.under_mouse(d, args)
|
||||||
ngeo.width = ngeo.width - 2*bw
|
ngeo.width = ngeo.width - 2*bw
|
||||||
ngeo.height = ngeo.height - 2*bw
|
ngeo.height = ngeo.height - 2*bw
|
||||||
|
|
||||||
return ngeo
|
geometry_common(d, args, ngeo)
|
||||||
|
|
||||||
|
return fix_new_geometry(ngeo, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Place the client next to the mouse.
|
--- Place the client next to the mouse.
|
||||||
|
@ -862,7 +881,7 @@ function placement.resize_to_mouse(d, args)
|
||||||
|
|
||||||
geometry_common(d, args, ngeo)
|
geometry_common(d, args, ngeo)
|
||||||
|
|
||||||
return ngeo
|
return fix_new_geometry(ngeo, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Move the drawable (client or wibox) `d` to a screen position or side.
|
--- Move the drawable (client or wibox) `d` to a screen position or side.
|
||||||
|
@ -913,7 +932,7 @@ function placement.align(d, args)
|
||||||
|
|
||||||
attach(d, placement[args.position], args)
|
attach(d, placement[args.position], args)
|
||||||
|
|
||||||
return ngeo
|
return fix_new_geometry(ngeo, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add the alias functions
|
-- Add the alias functions
|
||||||
|
@ -1002,7 +1021,7 @@ function placement.stretch(d, args)
|
||||||
|
|
||||||
attach(d, placement["stretch_"..args.direction], args)
|
attach(d, placement["stretch_"..args.direction], args)
|
||||||
|
|
||||||
return ngeo
|
return fix_new_geometry(ngeo, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add the alias functions
|
-- Add the alias functions
|
||||||
|
@ -1056,7 +1075,7 @@ function placement.maximize(d, args)
|
||||||
|
|
||||||
attach(d, placement.maximize, args)
|
attach(d, placement.maximize, args)
|
||||||
|
|
||||||
return ngeo
|
return fix_new_geometry(ngeo, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add the alias functions
|
-- Add the alias functions
|
||||||
|
@ -1121,7 +1140,7 @@ function placement.scale(d, args)
|
||||||
|
|
||||||
attach(d, placement.maximize, args)
|
attach(d, placement.maximize, args)
|
||||||
|
|
||||||
return ngeo
|
return fix_new_geometry(ngeo, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@DOC_awful_placement_maximize_vertically_EXAMPLE@
|
---@DOC_awful_placement_maximize_vertically_EXAMPLE@
|
||||||
|
|
|
@ -16,6 +16,7 @@ local capi =
|
||||||
}
|
}
|
||||||
local util = require("awful.util")
|
local util = require("awful.util")
|
||||||
local object = require("gears.object")
|
local object = require("gears.object")
|
||||||
|
local grect = require("gears.geometry").rectangle
|
||||||
|
|
||||||
local function get_screen(s)
|
local function get_screen(s)
|
||||||
return s and capi.screen[s]
|
return s and capi.screen[s]
|
||||||
|
@ -62,20 +63,7 @@ end
|
||||||
-- @tparam number y Y coordinate of point
|
-- @tparam number y Y coordinate of point
|
||||||
-- @treturn number The squared distance of the screen to the provided point
|
-- @treturn number The squared distance of the screen to the provided point
|
||||||
function screen.object.get_square_distance(self, x, y)
|
function screen.object.get_square_distance(self, x, y)
|
||||||
self = get_screen(self)
|
return grect.get_square_distance(get_screen(self).geometry, x, y)
|
||||||
local geom = self.geometry
|
|
||||||
local dist_x, dist_y = 0, 0
|
|
||||||
if x < geom.x then
|
|
||||||
dist_x = geom.x - x
|
|
||||||
elseif x >= geom.x + geom.width then
|
|
||||||
dist_x = x - geom.x - geom.width + 1
|
|
||||||
end
|
|
||||||
if y < geom.y then
|
|
||||||
dist_y = geom.y - y
|
|
||||||
elseif y >= geom.y + geom.height then
|
|
||||||
dist_y = y - geom.y - geom.height + 1
|
|
||||||
end
|
|
||||||
return dist_x * dist_x + dist_y * dist_y
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -83,20 +71,18 @@ end
|
||||||
-- The number returned can be used as an index into the global
|
-- The number returned can be used as an index into the global
|
||||||
-- `screen` table/object.
|
-- `screen` table/object.
|
||||||
-- @function awful.screen.getbycoord
|
-- @function awful.screen.getbycoord
|
||||||
-- @param x The x coordinate
|
-- @tparam number x The x coordinate
|
||||||
-- @param y The y coordinate
|
-- @tparam number y The y coordinate
|
||||||
|
-- @treturn ?number The screen index
|
||||||
function screen.getbycoord(x, y)
|
function screen.getbycoord(x, y)
|
||||||
local dist = math.huge
|
local s, sgeos = capi.screen.primary, {}
|
||||||
local s = capi.screen.primary
|
|
||||||
if s then
|
for scr in capi.screen do
|
||||||
dist = screen.object.get_square_distance(s, x, y)
|
sgeos[scr] = scr.geometry
|
||||||
end
|
|
||||||
for i in capi.screen do
|
|
||||||
local d = screen.object.get_square_distance(i, x, y)
|
|
||||||
if d < dist then
|
|
||||||
s, dist = capi.screen[i], d
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
s = grect.get_closest_by_coord(sgeos, x, y) or s
|
||||||
|
|
||||||
return s and s.index
|
return s and s.index
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -151,7 +137,7 @@ function screen.focus_bydirection(dir, _screen)
|
||||||
for s in capi.screen do
|
for s in capi.screen do
|
||||||
geomtbl[s] = capi.screen[s].geometry
|
geomtbl[s] = capi.screen[s].geometry
|
||||||
end
|
end
|
||||||
local target = util.get_rectangle_in_direction(dir, geomtbl, sel.geometry)
|
local target = grect.get_in_direction(dir, geomtbl, sel.geometry)
|
||||||
if target then
|
if target then
|
||||||
return screen.focus(target)
|
return screen.focus(target)
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,6 +20,7 @@ local type = type
|
||||||
local rtable = table
|
local rtable = table
|
||||||
local string = string
|
local string = string
|
||||||
local lgi = require("lgi")
|
local lgi = require("lgi")
|
||||||
|
local grect = require("gears.geometry").rectangle
|
||||||
local Gio = require("lgi").Gio
|
local Gio = require("lgi").Gio
|
||||||
local Pango = lgi.Pango
|
local Pango = lgi.Pango
|
||||||
local capi =
|
local capi =
|
||||||
|
@ -301,76 +302,18 @@ function util.subsets(set)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return true whether rectangle B is in the right direction
|
|
||||||
-- compared to rectangle A.
|
|
||||||
-- @param dir The direction.
|
|
||||||
-- @param gA The geometric specification for rectangle A.
|
|
||||||
-- @param gB The geometric specification for rectangle B.
|
|
||||||
-- @return True if B is in the direction of A.
|
|
||||||
local function is_in_direction(dir, gA, gB)
|
|
||||||
if dir == "up" then
|
|
||||||
return gA.y > gB.y
|
|
||||||
elseif dir == "down" then
|
|
||||||
return gA.y < gB.y
|
|
||||||
elseif dir == "left" then
|
|
||||||
return gA.x > gB.x
|
|
||||||
elseif dir == "right" then
|
|
||||||
return gA.x < gB.x
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Calculate distance between two points.
|
|
||||||
-- i.e: if we want to move to the right, we will take the right border
|
|
||||||
-- of the currently focused screen and the left side of the checked screen.
|
|
||||||
-- @param dir The direction.
|
|
||||||
-- @param _gA The first rectangle.
|
|
||||||
-- @param _gB The second rectangle.
|
|
||||||
-- @return The distance between the screens.
|
|
||||||
local function calculate_distance(dir, _gA, _gB)
|
|
||||||
local gAx = _gA.x
|
|
||||||
local gAy = _gA.y
|
|
||||||
local gBx = _gB.x
|
|
||||||
local gBy = _gB.y
|
|
||||||
|
|
||||||
if dir == "up" then
|
|
||||||
gBy = _gB.y + _gB.height
|
|
||||||
elseif dir == "down" then
|
|
||||||
gAy = _gA.y + _gA.height
|
|
||||||
elseif dir == "left" then
|
|
||||||
gBx = _gB.x + _gB.width
|
|
||||||
elseif dir == "right" then
|
|
||||||
gAx = _gA.x + _gA.width
|
|
||||||
end
|
|
||||||
|
|
||||||
return math.sqrt(math.pow(gBx - gAx, 2) + math.pow(gBy - gAy, 2))
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the nearest rectangle in the given direction. Every rectangle is specified as a table
|
--- Get the nearest rectangle in the given direction. Every rectangle is specified as a table
|
||||||
-- with 'x', 'y', 'width', 'height' keys, the same as client or screen geometries.
|
-- with 'x', 'y', 'width', 'height' keys, the same as client or screen geometries.
|
||||||
|
-- @deprecated awful.util.get_rectangle_in_direction
|
||||||
-- @param dir The direction, can be either "up", "down", "left" or "right".
|
-- @param dir The direction, can be either "up", "down", "left" or "right".
|
||||||
-- @param recttbl A table of rectangle specifications.
|
-- @param recttbl A table of rectangle specifications.
|
||||||
-- @param cur The current rectangle.
|
-- @param cur The current rectangle.
|
||||||
-- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found.
|
-- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found.
|
||||||
|
-- @see gears.geometry
|
||||||
function util.get_rectangle_in_direction(dir, recttbl, cur)
|
function util.get_rectangle_in_direction(dir, recttbl, cur)
|
||||||
local dist, dist_min
|
util.deprecate("gears.geometry.rectangle.get_in_direction")
|
||||||
local target = nil
|
|
||||||
|
|
||||||
-- We check each object
|
return grect.get_in_direction(dir, recttbl, cur)
|
||||||
for i, rect in pairs(recttbl) do
|
|
||||||
-- Check geometry to see if object is located in the right direction.
|
|
||||||
if is_in_direction(dir, cur, rect) then
|
|
||||||
-- Calculate distance between current and checked object.
|
|
||||||
dist = calculate_distance(dir, cur, rect)
|
|
||||||
|
|
||||||
-- If distance is shorter then keep the object.
|
|
||||||
if not target or dist < dist_min then
|
|
||||||
target = i
|
|
||||||
dist_min = dist
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return target
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Join all tables given as parameters.
|
--- Join all tables given as parameters.
|
||||||
|
|
|
@ -0,0 +1,352 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
--- Wibox module for awful.
|
||||||
|
-- This module allows you to easily create wibox and attach them to the edge of
|
||||||
|
-- a screen.
|
||||||
|
--
|
||||||
|
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
||||||
|
-- @copyright 2016 Emmanuel Lepage Vallee
|
||||||
|
-- @release @AWESOME_VERSION@
|
||||||
|
-- @classmod awful.wibar
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Grab environment we need
|
||||||
|
local capi =
|
||||||
|
{
|
||||||
|
screen = screen,
|
||||||
|
client = client
|
||||||
|
}
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local tostring = tostring
|
||||||
|
local ipairs = ipairs
|
||||||
|
local error = error
|
||||||
|
local wibox = require("wibox")
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
local util = require("awful.util")
|
||||||
|
local placement = require("awful.placement")
|
||||||
|
|
||||||
|
local function get_screen(s)
|
||||||
|
return s and capi.screen[s]
|
||||||
|
end
|
||||||
|
|
||||||
|
local awfulwibar = { mt = {} }
|
||||||
|
|
||||||
|
--- Array of table with wiboxes inside.
|
||||||
|
-- It's an array so it is ordered.
|
||||||
|
local wiboxes = setmetatable({}, {__mode = "v"})
|
||||||
|
|
||||||
|
-- Compute the margin on one side
|
||||||
|
local function get_margin(w, position, auto_stop)
|
||||||
|
local h_or_w = (position == "top" or position == "bottom") and "height" or "width"
|
||||||
|
local ret = 0
|
||||||
|
|
||||||
|
for _, v in ipairs(wiboxes) do
|
||||||
|
-- Ignore the wibars placed after this one
|
||||||
|
if auto_stop and v == w then break end
|
||||||
|
|
||||||
|
if v.position == position and v.screen == w.screen and v.visible then
|
||||||
|
ret = ret + v[h_or_w]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
-- `honor_workarea` cannot be used as it does modify the workarea itself.
|
||||||
|
-- a manual padding has to be generated.
|
||||||
|
local function get_margins(w)
|
||||||
|
local position = w.position
|
||||||
|
assert(position)
|
||||||
|
|
||||||
|
local margins = {left=0, right=0, top=0, bottom=0}
|
||||||
|
|
||||||
|
margins[position] = get_margin(w, position, true)
|
||||||
|
|
||||||
|
-- Avoid overlapping wibars
|
||||||
|
if position == "left" or position == "right" then
|
||||||
|
margins.top = get_margin(w, "top" )
|
||||||
|
margins.bottom = get_margin(w, "bottom")
|
||||||
|
end
|
||||||
|
|
||||||
|
return margins
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the placement function
|
||||||
|
local function gen_placement(position, stretch)
|
||||||
|
local maximize = (position == "right" or position == "left") and
|
||||||
|
"maximize_vertically" or "maximize_horizontally"
|
||||||
|
|
||||||
|
return placement[position] + (stretch and placement[maximize] or nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attach the placement function.
|
||||||
|
local function attach(wb, align)
|
||||||
|
gen_placement(align, wb._stretch)(wb, {
|
||||||
|
attach = true,
|
||||||
|
update_workarea = true,
|
||||||
|
margins = get_margins(wb)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Re-attach all wibars on a given wibar screen
|
||||||
|
local function reattach(wb)
|
||||||
|
local s = wb.screen
|
||||||
|
for _, w in ipairs(wiboxes) do
|
||||||
|
if w ~= wb and w.screen == s then
|
||||||
|
if w.detach_callback then
|
||||||
|
w.detach_callback()
|
||||||
|
w.detach_callback = nil
|
||||||
|
end
|
||||||
|
attach(w, w.position)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The wibox position.
|
||||||
|
-- @property position
|
||||||
|
-- @param string Either "left", right", "top" or "bottom"
|
||||||
|
|
||||||
|
local function get_position(wb)
|
||||||
|
return wb._position or "top"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_position(wb, position)
|
||||||
|
-- Detach first to avoid any uneeded callbacks
|
||||||
|
if wb.detach_callback then
|
||||||
|
wb.detach_callback()
|
||||||
|
|
||||||
|
-- Avoid disconnecting twice, this produces a lot of warnings
|
||||||
|
wb.detach_callback = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Move the wibar to the end of the list to avoid messing up the others in
|
||||||
|
-- case there is stacked wibars on one side.
|
||||||
|
if wb._position then
|
||||||
|
for k, w in ipairs(wiboxes) do
|
||||||
|
if w == wb then
|
||||||
|
table.remove(wiboxes, k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(wiboxes, wb)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- In case the position changed, it may be necessary to reset the size
|
||||||
|
if (wb._position == "left" or wb._position == "right")
|
||||||
|
and (position == "top" or position == "bottom") then
|
||||||
|
wb.height = math.ceil(beautiful.get_font_height(wb.font) * 1.5)
|
||||||
|
elseif (wb._position == "top" or wb._position == "bottom")
|
||||||
|
and (position == "left" or position == "right") then
|
||||||
|
wb.width = math.ceil(beautiful.get_font_height(wb.font) * 1.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Changing the position will also cause the other margins to be invalidated.
|
||||||
|
-- For example, adding a wibar to the top will change the margins of any left
|
||||||
|
-- or right wibars. To solve, this, they need to be re-attached.
|
||||||
|
reattach(wb)
|
||||||
|
|
||||||
|
-- Set the new position
|
||||||
|
wb._position = position
|
||||||
|
|
||||||
|
-- Attach to the new position
|
||||||
|
attach(wb, position)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stretch the wibar.
|
||||||
|
--
|
||||||
|
-- @property stretch
|
||||||
|
-- @param[opt=true] boolean
|
||||||
|
|
||||||
|
local function get_stretch(w)
|
||||||
|
return w._stretch
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_stretch(w, value)
|
||||||
|
w._stretch = value
|
||||||
|
|
||||||
|
attach(w, w.position)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a wibar.
|
||||||
|
-- @function remove
|
||||||
|
local function remove(self)
|
||||||
|
self.visible = false
|
||||||
|
|
||||||
|
if self.detach_callback then
|
||||||
|
self.detach_callback()
|
||||||
|
self.detach_callback = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, w in ipairs(wiboxes) do
|
||||||
|
if w == self then
|
||||||
|
table.remove(wiboxes, k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self._screen = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a wibox position if it has been set, or return top.
|
||||||
|
-- @param wb The wibox
|
||||||
|
-- @deprecated awful.wibar.get_position
|
||||||
|
-- @return The wibox position.
|
||||||
|
function awfulwibar.get_position(wb)
|
||||||
|
util.deprecate("Use wb:get_position() instead of awful.wibar.get_position")
|
||||||
|
return get_position(wb)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Put a wibox on a screen at this position.
|
||||||
|
-- @param wb The wibox to attach.
|
||||||
|
-- @param position The position: top, bottom left or right.
|
||||||
|
-- @param screen This argument is deprecated, use wb.screen directly.
|
||||||
|
-- @deprecated awful.wibar.set_position
|
||||||
|
function awfulwibar.set_position(wb, position, screen) --luacheck: no unused args
|
||||||
|
util.deprecate("Use wb:set_position(position) instead of awful.wibar.set_position")
|
||||||
|
|
||||||
|
set_position(wb, position)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Attach a wibox to a screen.
|
||||||
|
-- If a wibox is attached, it will be automatically be moved when other wiboxes
|
||||||
|
-- will be attached.
|
||||||
|
-- @param wb The wibox to attach.
|
||||||
|
-- @param position The position of the wibox: top, bottom, left or right.
|
||||||
|
-- @param screen The screen to attach to
|
||||||
|
-- @deprecated awful.wibar.attach
|
||||||
|
function awfulwibar.attach(wb, position, screen) --luacheck: no unused args
|
||||||
|
util.deprecate("awful.wibar.attach is deprecated, use the 'attach' property"..
|
||||||
|
" of awful.placement. This method doesn't do anything anymore"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Align a wibox.
|
||||||
|
--
|
||||||
|
-- Supported alignment are:
|
||||||
|
--
|
||||||
|
-- * top_left
|
||||||
|
-- * top_right
|
||||||
|
-- * bottom_left
|
||||||
|
-- * bottom_right
|
||||||
|
-- * left
|
||||||
|
-- * right
|
||||||
|
-- * top
|
||||||
|
-- * bottom
|
||||||
|
-- * centered
|
||||||
|
-- * center_vertical
|
||||||
|
-- * center_horizontal
|
||||||
|
--
|
||||||
|
-- @param wb The wibox.
|
||||||
|
-- @param align The alignment
|
||||||
|
-- @param screen This argument is deprecated. It is not used. Use wb.screen
|
||||||
|
-- directly.
|
||||||
|
-- @deprecated awful.wibar.align
|
||||||
|
-- @see awful.placement.align
|
||||||
|
function awfulwibar.align(wb, align, screen) --luacheck: no unused args
|
||||||
|
if align == "center" then
|
||||||
|
util.deprecate("awful.wibar.align(wb, 'center' is deprecated, use 'centered'")
|
||||||
|
align = "centered"
|
||||||
|
end
|
||||||
|
|
||||||
|
if screen then
|
||||||
|
util.deprecate("awful.wibar.align 'screen' argument is deprecated")
|
||||||
|
end
|
||||||
|
|
||||||
|
attach(wb, align)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stretch a wibox so it takes all screen width or height.
|
||||||
|
--
|
||||||
|
-- **This function has been removed.**
|
||||||
|
--
|
||||||
|
-- @deprecated awful.wibox.stretch
|
||||||
|
-- @see awful.placement
|
||||||
|
-- @see stretch
|
||||||
|
|
||||||
|
--- Create a new wibox and attach it to a screen edge.
|
||||||
|
-- @see wibox
|
||||||
|
-- @param arg A table with standard arguments to wibox() creator.
|
||||||
|
-- You can add also position key with value top, bottom, left or right.
|
||||||
|
-- You can also use width or height in % and set align to center, right or left.
|
||||||
|
-- You can also set the screen key with a screen number to attach the wibox.
|
||||||
|
-- If not specified, 1 is assumed.
|
||||||
|
-- @return The wibox created.
|
||||||
|
function awfulwibar.new(arg)
|
||||||
|
arg = arg or {}
|
||||||
|
local position = arg.position or "top"
|
||||||
|
local has_to_stretch = true
|
||||||
|
local screen = get_screen(arg.screen or 1)
|
||||||
|
|
||||||
|
arg.type = arg.type or "dock"
|
||||||
|
|
||||||
|
if position ~= "top" and position ~="bottom"
|
||||||
|
and position ~= "left" and position ~= "right" then
|
||||||
|
error("Invalid position in awful.wibar(), you may only use"
|
||||||
|
.. " 'top', 'bottom', 'left' and 'right'")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set default size
|
||||||
|
if position == "left" or position == "right" then
|
||||||
|
arg.width = arg.width or math.ceil(beautiful.get_font_height(arg.font) * 1.5)
|
||||||
|
if arg.height then
|
||||||
|
has_to_stretch = false
|
||||||
|
if arg.screen then
|
||||||
|
local hp = tostring(arg.height):match("(%d+)%%")
|
||||||
|
if hp then
|
||||||
|
arg.height = math.ceil(screen.geometry.height * hp / 100)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
arg.height = arg.height or math.ceil(beautiful.get_font_height(arg.font) * 1.5)
|
||||||
|
if arg.width then
|
||||||
|
has_to_stretch = false
|
||||||
|
if arg.screen then
|
||||||
|
local wp = tostring(arg.width):match("(%d+)%%")
|
||||||
|
if wp then
|
||||||
|
arg.width = math.ceil(screen.geometry.width * wp / 100)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local w = wibox(arg)
|
||||||
|
|
||||||
|
w.screen = screen
|
||||||
|
w._screen = screen --HACK When a screen is removed, then getbycoords wont work
|
||||||
|
w._stretch = arg.stretch == nil and has_to_stretch or arg.stretch
|
||||||
|
|
||||||
|
w:add_signal("property::position")
|
||||||
|
w.get_position = get_position
|
||||||
|
w.set_position = set_position
|
||||||
|
|
||||||
|
w:add_signal("property::stretch")
|
||||||
|
w.get_stretch = get_stretch
|
||||||
|
w.set_stretch = set_stretch
|
||||||
|
w.remove = remove
|
||||||
|
|
||||||
|
w.visible = true
|
||||||
|
|
||||||
|
w:set_position(position)
|
||||||
|
|
||||||
|
table.insert(wiboxes, w)
|
||||||
|
|
||||||
|
w:connect_signal("property::visible", function() reattach(w) end)
|
||||||
|
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
|
||||||
|
capi.screen.connect_signal("removed", function(s)
|
||||||
|
for _, wibar in ipairs(wiboxes) do
|
||||||
|
if wibar._screen == s then
|
||||||
|
wibar:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function awfulwibar.mt:__call(...)
|
||||||
|
return awfulwibar.new(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
--@DOC_wibox_COMMON@
|
||||||
|
|
||||||
|
return setmetatable(awfulwibar, awfulwibar.mt)
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -1,302 +1,32 @@
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
--- Wibox module for awful.
|
--- This module is deprecated and has been renamed `awful.wibar`
|
||||||
-- This module allows you to easily create wibox and attach them to the edge of
|
|
||||||
-- a screen.
|
|
||||||
--
|
--
|
||||||
-- @author Julien Danjou <julien@danjou.info>
|
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
||||||
-- @copyright 2009 Julien Danjou
|
-- @copyright 2016 Emmanuel Lepage Vallee
|
||||||
-- @release @AWESOME_VERSION@
|
-- @release @AWESOME_VERSION@
|
||||||
-- @module awful.wibox
|
-- @module awful.wibox
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
local util = require("awful.util")
|
||||||
|
local wibar = require("awful.wibar")
|
||||||
|
|
||||||
-- Grab environment we need
|
local function call(_,...)
|
||||||
local capi =
|
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||||
{
|
|
||||||
screen = screen,
|
|
||||||
client = client
|
|
||||||
}
|
|
||||||
local setmetatable = setmetatable
|
|
||||||
local tostring = tostring
|
|
||||||
local ipairs = ipairs
|
|
||||||
local table = table
|
|
||||||
local error = error
|
|
||||||
local wibox = require("wibox")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local round = require("awful.util").round
|
|
||||||
|
|
||||||
local function get_screen(s)
|
return wibar(...)
|
||||||
return s and capi.screen[s]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local awfulwibox = { mt = {} }
|
local function index(_, k)
|
||||||
|
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||||
|
|
||||||
--- Array of table with wiboxes inside.
|
return wibar[k]
|
||||||
-- It's an array so it is ordered.
|
|
||||||
local wiboxes = {}
|
|
||||||
|
|
||||||
--- Get a wibox position if it has been set, or return top.
|
|
||||||
-- @param wb The wibox
|
|
||||||
-- @return The wibox position.
|
|
||||||
function awfulwibox.get_position(wb)
|
|
||||||
for _, wprop in ipairs(wiboxes) do
|
|
||||||
if wprop.wibox == wb then
|
|
||||||
return wprop.position
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return "top"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Put a wibox on a screen at this position.
|
local function newindex(_, k, v)
|
||||||
-- @param wb The wibox to attach.
|
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||||
-- @param position The position: top, bottom left or right.
|
|
||||||
-- @param screen If the wibox it not attached to a screen, specified on which
|
|
||||||
-- screen the position should be set.
|
|
||||||
function awfulwibox.set_position(wb, position, screen)
|
|
||||||
local area = get_screen(screen).geometry
|
|
||||||
|
|
||||||
-- The "length" of a wibox is always chosen to be the optimal size
|
wibar[k] = v
|
||||||
-- (non-floating).
|
|
||||||
-- The "width" of a wibox is kept if it exists.
|
|
||||||
if position == "right" then
|
|
||||||
wb.x = area.x + area.width - (wb.width + 2 * wb.border_width)
|
|
||||||
elseif position == "left" then
|
|
||||||
wb.x = area.x
|
|
||||||
elseif position == "bottom" then
|
|
||||||
wb.y = (area.y + area.height) - (wb.height + 2 * wb.border_width)
|
|
||||||
elseif position == "top" then
|
|
||||||
wb.y = area.y
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, wprop in ipairs(wiboxes) do
|
return setmetatable({}, {__call = call, __index = index, __newindex = newindex})
|
||||||
if wprop.wibox == wb then
|
|
||||||
wprop.position = position
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Reset all wiboxes positions.
|
|
||||||
local function update_all_wiboxes_position()
|
|
||||||
for _, wprop in ipairs(wiboxes) do
|
|
||||||
awfulwibox.set_position(wprop.wibox, wprop.position, wprop.screen)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function call_wibox_position_hook_on_prop_update()
|
|
||||||
update_all_wiboxes_position()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function wibox_update_strut(wb)
|
|
||||||
for _, wprop in ipairs(wiboxes) do
|
|
||||||
if wprop.wibox == wb then
|
|
||||||
if not wb.visible then
|
|
||||||
wb:struts { left = 0, right = 0, bottom = 0, top = 0 }
|
|
||||||
elseif wprop.position == "top" then
|
|
||||||
wb:struts { left = 0, right = 0, bottom = 0, top = wb.height + 2 * wb.border_width }
|
|
||||||
elseif wprop.position == "bottom" then
|
|
||||||
wb:struts { left = 0, right = 0, bottom = wb.height + 2 * wb.border_width, top = 0 }
|
|
||||||
elseif wprop.position == "left" then
|
|
||||||
wb:struts { left = wb.width + 2 * wb.border_width, right = 0, bottom = 0, top = 0 }
|
|
||||||
elseif wprop.position == "right" then
|
|
||||||
wb:struts { left = 0, right = wb.width + 2 * wb.border_width, bottom = 0, top = 0 }
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Attach a wibox to a screen.
|
|
||||||
-- If a wibox is attached, it will be automatically be moved when other wiboxes
|
|
||||||
-- will be attached.
|
|
||||||
-- @param wb The wibox to attach.
|
|
||||||
-- @param position The position of the wibox: top, bottom, left or right.
|
|
||||||
-- @param screen The screen to attach to
|
|
||||||
function awfulwibox.attach(wb, position, screen)
|
|
||||||
screen = get_screen(screen)
|
|
||||||
-- Store wibox as attached in a weak-valued table
|
|
||||||
local wibox_prop_table
|
|
||||||
-- Start from end since we sometimes remove items
|
|
||||||
for i = #wiboxes, 1, -1 do
|
|
||||||
-- Since wiboxes are stored as weak value, they can disappear.
|
|
||||||
-- If they did, remove their entries
|
|
||||||
if wiboxes[i].wibox == nil then
|
|
||||||
table.remove(wiboxes, i)
|
|
||||||
elseif wiboxes[i].wibox == wb then
|
|
||||||
wibox_prop_table = wiboxes[i]
|
|
||||||
-- We could break here, but well, let's check if there is no other
|
|
||||||
-- table with their wiboxes been garbage collected.
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not wibox_prop_table then
|
|
||||||
table.insert(wiboxes, setmetatable({ wibox = wb, position = position, screen = screen }, { __mode = 'v' }))
|
|
||||||
else
|
|
||||||
wibox_prop_table.position = position
|
|
||||||
end
|
|
||||||
|
|
||||||
wb:connect_signal("property::width", wibox_update_strut)
|
|
||||||
wb:connect_signal("property::height", wibox_update_strut)
|
|
||||||
wb:connect_signal("property::visible", wibox_update_strut)
|
|
||||||
|
|
||||||
wb:connect_signal("property::width", call_wibox_position_hook_on_prop_update)
|
|
||||||
wb:connect_signal("property::height", call_wibox_position_hook_on_prop_update)
|
|
||||||
wb:connect_signal("property::visible", call_wibox_position_hook_on_prop_update)
|
|
||||||
wb:connect_signal("property::border_width", call_wibox_position_hook_on_prop_update)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Align a wibox.
|
|
||||||
-- @param wb The wibox.
|
|
||||||
-- @param align The alignment: left, right or center.
|
|
||||||
-- @param screen If the wibox is not attached to any screen, you can specify the
|
|
||||||
-- screen where to align.
|
|
||||||
function awfulwibox.align(wb, align, screen)
|
|
||||||
screen = get_screen(screen)
|
|
||||||
local position = awfulwibox.get_position(wb)
|
|
||||||
local area = screen.workarea
|
|
||||||
|
|
||||||
if position == "right" then
|
|
||||||
if align == "right" then
|
|
||||||
wb.y = area.y
|
|
||||||
elseif align == "left" then
|
|
||||||
wb.y = area.y + area.height - (wb.height + 2 * wb.border_width)
|
|
||||||
elseif align == "center" then
|
|
||||||
wb.y = area.y + round((area.height - wb.height) / 2)
|
|
||||||
end
|
|
||||||
elseif position == "left" then
|
|
||||||
if align == "right" then
|
|
||||||
wb.y = (area.y + area.height) - (wb.height + 2 * wb.border_width)
|
|
||||||
elseif align == "left" then
|
|
||||||
wb.y = area.y
|
|
||||||
elseif align == "center" then
|
|
||||||
wb.y = area.y + round((area.height - wb.height) / 2)
|
|
||||||
end
|
|
||||||
elseif position == "bottom" then
|
|
||||||
if align == "right" then
|
|
||||||
wb.x = area.x + area.width - (wb.width + 2 * wb.border_width)
|
|
||||||
elseif align == "left" then
|
|
||||||
wb.x = area.x
|
|
||||||
elseif align == "center" then
|
|
||||||
wb.x = area.x + round((area.width - wb.width) / 2)
|
|
||||||
end
|
|
||||||
elseif position == "top" then
|
|
||||||
if align == "right" then
|
|
||||||
wb.x = area.x + area.width - (wb.width + 2 * wb.border_width)
|
|
||||||
elseif align == "left" then
|
|
||||||
wb.x = area.x
|
|
||||||
elseif align == "center" then
|
|
||||||
wb.x = area.x + round((area.width - wb.width) / 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update struts regardless of changes
|
|
||||||
wibox_update_strut(wb)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stretch a wibox so it takes all screen width or height.
|
|
||||||
-- @param wb The wibox.
|
|
||||||
-- @param screen The screen to stretch on, or the wibox screen.
|
|
||||||
function awfulwibox.stretch(wb, screen)
|
|
||||||
if screen then
|
|
||||||
screen = get_screen(screen)
|
|
||||||
local position = awfulwibox.get_position(wb)
|
|
||||||
local area = screen.workarea
|
|
||||||
if position == "right" or position == "left" then
|
|
||||||
wb.height = area.height - (2 * wb.border_width)
|
|
||||||
wb.y = area.y
|
|
||||||
else
|
|
||||||
wb.width = area.width - (2 * wb.border_width)
|
|
||||||
wb.x = area.x
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new wibox and attach it to a screen edge.
|
|
||||||
-- @see wibox
|
|
||||||
-- @param arg A table with standard arguments to wibox() creator.
|
|
||||||
-- You can add also position key with value top, bottom, left or right.
|
|
||||||
-- You can also use width or height in % and set align to center, right or left.
|
|
||||||
-- You can also set the screen key with a screen number to attach the wibox.
|
|
||||||
-- If not specified, 1 is assumed.
|
|
||||||
-- @return The wibox created.
|
|
||||||
function awfulwibox.new(arg)
|
|
||||||
arg = arg or {}
|
|
||||||
local position = arg.position or "top"
|
|
||||||
local has_to_stretch = true
|
|
||||||
local screen = get_screen(arg.screen or 1)
|
|
||||||
|
|
||||||
arg.type = arg.type or "dock"
|
|
||||||
|
|
||||||
if position ~= "top" and position ~="bottom"
|
|
||||||
and position ~= "left" and position ~= "right" then
|
|
||||||
error("Invalid position in awful.wibox(), you may only use"
|
|
||||||
.. " 'top', 'bottom', 'left' and 'right'")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set default size
|
|
||||||
if position == "left" or position == "right" then
|
|
||||||
arg.width = arg.width or round(beautiful.get_font_height(arg.font) * 1.5)
|
|
||||||
if arg.height then
|
|
||||||
has_to_stretch = false
|
|
||||||
if arg.screen then
|
|
||||||
local hp = tostring(arg.height):match("(%d+)%%")
|
|
||||||
if hp then
|
|
||||||
arg.height = round(screen.geometry.height * hp / 100)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
arg.height = arg.height or round(beautiful.get_font_height(arg.font) * 1.5)
|
|
||||||
if arg.width then
|
|
||||||
has_to_stretch = false
|
|
||||||
if arg.screen then
|
|
||||||
local wp = tostring(arg.width):match("(%d+)%%")
|
|
||||||
if wp then
|
|
||||||
arg.width = round(screen.geometry.width * wp / 100)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local w = wibox(arg)
|
|
||||||
|
|
||||||
w.visible = true
|
|
||||||
|
|
||||||
awfulwibox.attach(w, position, screen)
|
|
||||||
if has_to_stretch then
|
|
||||||
awfulwibox.stretch(w, screen)
|
|
||||||
else
|
|
||||||
awfulwibox.align(w, arg.align, screen)
|
|
||||||
end
|
|
||||||
|
|
||||||
awfulwibox.set_position(w, position, screen)
|
|
||||||
|
|
||||||
return w
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update_wiboxes_on_struts(c)
|
|
||||||
local struts = c:struts()
|
|
||||||
if struts.left ~= 0 or struts.right ~= 0
|
|
||||||
or struts.top ~= 0 or struts.bottom ~= 0 then
|
|
||||||
update_all_wiboxes_position()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Hook registered to reset all wiboxes position.
|
|
||||||
capi.client.connect_signal("property::struts", update_wiboxes_on_struts)
|
|
||||||
capi.client.connect_signal("unmanage", update_wiboxes_on_struts)
|
|
||||||
|
|
||||||
capi.screen.connect_signal("removed", function(s)
|
|
||||||
for _, wprop in ipairs(wiboxes) do
|
|
||||||
if wprop.screen == s then
|
|
||||||
wprop.wibox.visible = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
function awfulwibox.mt:__call(...)
|
|
||||||
return awfulwibox.new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(awfulwibox, awfulwibox.mt)
|
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local capi = { screen = screen }
|
local capi = { screen = screen, tag = tag }
|
||||||
local layout = require("awful.layout")
|
local layout = require("awful.layout")
|
||||||
local tooltip = require("awful.tooltip")
|
local tooltip = require("awful.tooltip")
|
||||||
local tag = require("awful.tag")
|
|
||||||
local beautiful = require("beautiful")
|
local beautiful = require("beautiful")
|
||||||
local imagebox = require("wibox.widget.imagebox")
|
local imagebox = require("wibox.widget.imagebox")
|
||||||
|
|
||||||
|
@ -48,8 +47,8 @@ function layoutbox.new(screen)
|
||||||
-- Do we already have the update callbacks registered?
|
-- Do we already have the update callbacks registered?
|
||||||
if boxes == nil then
|
if boxes == nil then
|
||||||
boxes = setmetatable({}, { __mode = "kv" })
|
boxes = setmetatable({}, { __mode = "kv" })
|
||||||
tag.attached_connect_signal(nil, "property::selected", update_from_tag)
|
capi.tag.connect_signal("property::selected", update_from_tag)
|
||||||
tag.attached_connect_signal(nil, "property::layout", update_from_tag)
|
capi.tag.connect_signal("property::layout", update_from_tag)
|
||||||
layoutbox.boxes = boxes
|
layoutbox.boxes = boxes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ function layoutbox.new(screen)
|
||||||
w._layoutbox_tooltip = tooltip({ objects = {w}, delay_show = 1 })
|
w._layoutbox_tooltip = tooltip({ objects = {w}, delay_show = 1 })
|
||||||
|
|
||||||
update(w, screen)
|
update(w, screen)
|
||||||
boxes[screen] = w
|
boxes[screen] = setmetatable({}, {__index = w, __newindex = w})
|
||||||
end
|
end
|
||||||
|
|
||||||
return w
|
return w
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Helper functions used to compute geometries.
|
||||||
|
--
|
||||||
|
-- When this module refer to a geometry table, this assume a table with at least
|
||||||
|
-- an *x*, *y*, *width* and *height* keys and numeric values.
|
||||||
|
--
|
||||||
|
-- @author Julien Danjou <julien@danjou.info>
|
||||||
|
-- @copyright 2008 Julien Danjou
|
||||||
|
-- @release @AWESOME_VERSION@
|
||||||
|
-- @module gears.geometry
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
local math = math
|
||||||
|
|
||||||
|
local gears = {geometry = {rectangle = {} } }
|
||||||
|
|
||||||
|
--- Get the square distance between a rectangle and a point.
|
||||||
|
-- @tparam table geom A rectangle
|
||||||
|
-- @tparam number geom.x The horizontal coordinate
|
||||||
|
-- @tparam number geom.y The vertical coordinate
|
||||||
|
-- @tparam number geom.width The rectangle width
|
||||||
|
-- @tparam number geom.height The rectangle height
|
||||||
|
-- @tparam number x X coordinate of point
|
||||||
|
-- @tparam number y Y coordinate of point
|
||||||
|
-- @treturn number The squared distance of the rectangle to the provided point
|
||||||
|
function gears.geometry.rectangle.get_square_distance(geom, x, y)
|
||||||
|
local dist_x, dist_y = 0, 0
|
||||||
|
if x < geom.x then
|
||||||
|
dist_x = geom.x - x
|
||||||
|
elseif x >= geom.x + geom.width then
|
||||||
|
dist_x = x - geom.x - geom.width + 1
|
||||||
|
end
|
||||||
|
if y < geom.y then
|
||||||
|
dist_y = geom.y - y
|
||||||
|
elseif y >= geom.y + geom.height then
|
||||||
|
dist_y = y - geom.y - geom.height + 1
|
||||||
|
end
|
||||||
|
return dist_x * dist_x + dist_y * dist_y
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the closest rectangle from `list` for a given point.
|
||||||
|
-- @tparam table list A list of geometry tables.
|
||||||
|
-- @tparam number x The x coordinate
|
||||||
|
-- @tparam number y The y coordinate
|
||||||
|
-- @return The key from the closest geometry.
|
||||||
|
function gears.geometry.rectangle.get_closest_by_coord(list, x, y)
|
||||||
|
local dist = math.huge
|
||||||
|
local ret = nil
|
||||||
|
|
||||||
|
for k, v in pairs(list) do
|
||||||
|
local d = gears.geometry.rectangle.get_square_distance(v, x, y)
|
||||||
|
if d < dist then
|
||||||
|
ret, dist = k, d
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the rectangle containing the [x, y] point.
|
||||||
|
--
|
||||||
|
-- Note that if multiple element from the geometry list contains the point, the
|
||||||
|
-- returned result is nondeterministic.
|
||||||
|
--
|
||||||
|
-- @tparam table list A list of geometry tables.
|
||||||
|
-- @tparam number x The x coordinate
|
||||||
|
-- @tparam number y The y coordinate
|
||||||
|
-- @return The key from the closest geometry. In case no result is found, *nil*
|
||||||
|
-- is returned.
|
||||||
|
function gears.geometry.rectangle.get_by_coord(list, x, y)
|
||||||
|
for k, geometry in pairs(list) do
|
||||||
|
if x >= geometry.x and x < geometry.x + geometry.width
|
||||||
|
and y >= geometry.y and y < geometry.y + geometry.height then
|
||||||
|
return k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return true whether rectangle B is in the right direction
|
||||||
|
-- compared to rectangle A.
|
||||||
|
-- @param dir The direction.
|
||||||
|
-- @param gA The geometric specification for rectangle A.
|
||||||
|
-- @param gB The geometric specification for rectangle B.
|
||||||
|
-- @return True if B is in the direction of A.
|
||||||
|
local function is_in_direction(dir, gA, gB)
|
||||||
|
if dir == "up" then
|
||||||
|
return gA.y > gB.y
|
||||||
|
elseif dir == "down" then
|
||||||
|
return gA.y < gB.y
|
||||||
|
elseif dir == "left" then
|
||||||
|
return gA.x > gB.x
|
||||||
|
elseif dir == "right" then
|
||||||
|
return gA.x < gB.x
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Calculate distance between two points.
|
||||||
|
-- i.e: if we want to move to the right, we will take the right border
|
||||||
|
-- of the currently focused screen and the left side of the checked screen.
|
||||||
|
-- @param dir The direction.
|
||||||
|
-- @param _gA The first rectangle.
|
||||||
|
-- @param _gB The second rectangle.
|
||||||
|
-- @return The distance between the screens.
|
||||||
|
local function calculate_distance(dir, _gA, _gB)
|
||||||
|
local gAx = _gA.x
|
||||||
|
local gAy = _gA.y
|
||||||
|
local gBx = _gB.x
|
||||||
|
local gBy = _gB.y
|
||||||
|
|
||||||
|
if dir == "up" then
|
||||||
|
gBy = _gB.y + _gB.height
|
||||||
|
elseif dir == "down" then
|
||||||
|
gAy = _gA.y + _gA.height
|
||||||
|
elseif dir == "left" then
|
||||||
|
gBx = _gB.x + _gB.width
|
||||||
|
elseif dir == "right" then
|
||||||
|
gAx = _gA.x + _gA.width
|
||||||
|
end
|
||||||
|
|
||||||
|
return math.sqrt(math.pow(gBx - gAx, 2) + math.pow(gBy - gAy, 2))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the nearest rectangle in the given direction. Every rectangle is specified as a table
|
||||||
|
-- with *x*, *y*, *width*, *height* keys, the same as client or screen geometries.
|
||||||
|
-- @tparam string dir The direction, can be either *up*, *down*, *left* or *right*.
|
||||||
|
-- @tparam table recttbl A table of rectangle specifications.
|
||||||
|
-- @tparam table cur The current rectangle.
|
||||||
|
-- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found.
|
||||||
|
function gears.geometry.rectangle.get_in_direction(dir, recttbl, cur)
|
||||||
|
local dist, dist_min
|
||||||
|
local target = nil
|
||||||
|
|
||||||
|
-- We check each object
|
||||||
|
for i, rect in pairs(recttbl) do
|
||||||
|
-- Check geometry to see if object is located in the right direction.
|
||||||
|
if is_in_direction(dir, cur, rect) then
|
||||||
|
-- Calculate distance between current and checked object.
|
||||||
|
dist = calculate_distance(dir, cur, rect)
|
||||||
|
|
||||||
|
-- If distance is shorter then keep the object.
|
||||||
|
if not target or dist < dist_min then
|
||||||
|
target = i
|
||||||
|
dist_min = dist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return target
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if an area intersect another area.
|
||||||
|
-- @param a The area.
|
||||||
|
-- @param b The other area.
|
||||||
|
-- @return True if they intersect, false otherwise.
|
||||||
|
local function area_intersect_area(a, b)
|
||||||
|
return (b.x < a.x + a.width
|
||||||
|
and b.x + b.width > a.x
|
||||||
|
and b.y < a.y + a.height
|
||||||
|
and b.y + b.height > a.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the intersect area between a and b.
|
||||||
|
-- @tparam table a The area.
|
||||||
|
-- @tparam number a.x The horizontal coordinate
|
||||||
|
-- @tparam number a.y The vertical coordinate
|
||||||
|
-- @tparam number a.width The rectangle width
|
||||||
|
-- @tparam number a.height The rectangle height
|
||||||
|
-- @tparam table b The other area.
|
||||||
|
-- @tparam number b.x The horizontal coordinate
|
||||||
|
-- @tparam number b.y The vertical coordinate
|
||||||
|
-- @tparam number b.width The rectangle width
|
||||||
|
-- @tparam number b.height The rectangle height
|
||||||
|
-- @treturn table The intersect area.
|
||||||
|
function gears.geometry.rectangle.get_intersection(a, b)
|
||||||
|
local g = {}
|
||||||
|
g.x = math.max(a.x, b.x)
|
||||||
|
g.y = math.max(a.y, b.y)
|
||||||
|
g.width = math.min(a.x + a.width, b.x + b.width) - g.x
|
||||||
|
g.height = math.min(a.y + a.height, b.y + b.height) - g.y
|
||||||
|
return g
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove an area from a list, splitting the space between several area that
|
||||||
|
-- can overlap.
|
||||||
|
-- @tparam table areas Table of areas.
|
||||||
|
-- @tparam table elem Area to remove.
|
||||||
|
-- @tparam number elem.x The horizontal coordinate
|
||||||
|
-- @tparam number elem.y The vertical coordinate
|
||||||
|
-- @tparam number elem.width The rectangle width
|
||||||
|
-- @tparam number elem.height The rectangle height
|
||||||
|
-- @return The new area list.
|
||||||
|
function gears.geometry.rectangle.area_remove(areas, elem)
|
||||||
|
for i = #areas, 1, -1 do
|
||||||
|
-- Check if the 'elem' intersect
|
||||||
|
if area_intersect_area(areas[i], elem) then
|
||||||
|
-- It does? remove it
|
||||||
|
local r = table.remove(areas, i)
|
||||||
|
local inter = gears.geometry.rectangle.get_intersection(r, elem)
|
||||||
|
|
||||||
|
if inter.x > r.x then
|
||||||
|
table.insert(areas, {
|
||||||
|
x = r.x,
|
||||||
|
y = r.y,
|
||||||
|
width = inter.x - r.x,
|
||||||
|
height = r.height
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if inter.y > r.y then
|
||||||
|
table.insert(areas, {
|
||||||
|
x = r.x,
|
||||||
|
y = r.y,
|
||||||
|
width = r.width,
|
||||||
|
height = inter.y - r.y
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if inter.x + inter.width < r.x + r.width then
|
||||||
|
table.insert(areas, {
|
||||||
|
x = inter.x + inter.width,
|
||||||
|
y = r.y,
|
||||||
|
width = (r.x + r.width) - (inter.x + inter.width),
|
||||||
|
height = r.height
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if inter.y + inter.height < r.y + r.height then
|
||||||
|
table.insert(areas, {
|
||||||
|
x = r.x,
|
||||||
|
y = inter.y + inter.height,
|
||||||
|
width = r.width,
|
||||||
|
height = (r.y + r.height) - (inter.y + inter.height)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return areas
|
||||||
|
end
|
||||||
|
|
||||||
|
return gears.geometry
|
|
@ -18,7 +18,7 @@ return
|
||||||
matrix = require("gears.matrix");
|
matrix = require("gears.matrix");
|
||||||
shape = require("gears.shape");
|
shape = require("gears.shape");
|
||||||
protected_call = require("gears.protected_call");
|
protected_call = require("gears.protected_call");
|
||||||
screen = require("gears.screen");
|
geometry = require("gears.geometry");
|
||||||
}
|
}
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
---------------------------------------------------------------------------
|
|
||||||
-- @author Uli Schlachter
|
|
||||||
-- @copyright 2016 Uli Schlachter
|
|
||||||
-- @release @AWESOME_VERSION@
|
|
||||||
-- @classmod gears.screen
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local ascreen = require("awful.screen")
|
|
||||||
local util = require("awful.util")
|
|
||||||
|
|
||||||
local module = {}
|
|
||||||
|
|
||||||
--- Call a function for each existing and created-in-the-future screen.
|
|
||||||
-- @tparam function func The function to call.
|
|
||||||
function module.connect_for_each_screen(func)
|
|
||||||
util.deprecate("Use awful.screen.connect_for_each_screen")
|
|
||||||
ascreen.connect_for_each_screen(func)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Undo the effect of connect_for_each_screen.
|
|
||||||
-- @tparam function func The function that should no longer be called.
|
|
||||||
function module.disconnect_for_each_screen(func)
|
|
||||||
util.deprecate("Use awful.screen.disconnect_for_each_screen")
|
|
||||||
ascreen.disconnect_for_each_screen(func)
|
|
||||||
end
|
|
||||||
|
|
||||||
return module
|
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
|
@ -19,30 +19,26 @@ local color = require("gears.color")
|
||||||
local object = require("gears.object")
|
local object = require("gears.object")
|
||||||
local surface = require("gears.surface")
|
local surface = require("gears.surface")
|
||||||
local timer = require("gears.timer")
|
local timer = require("gears.timer")
|
||||||
|
local grect = require("gears.geometry").rectangle
|
||||||
local matrix = require("gears.matrix")
|
local matrix = require("gears.matrix")
|
||||||
local hierarchy = require("wibox.hierarchy")
|
local hierarchy = require("wibox.hierarchy")
|
||||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||||
|
|
||||||
local drawables = setmetatable({}, { __mode = 'k' })
|
local drawables = setmetatable({}, { __mode = 'k' })
|
||||||
|
|
||||||
-- This is awful.screen.getbycoord() which we sadly cannot use from here (cyclic
|
|
||||||
-- dependencies are bad!)
|
|
||||||
local function screen_getbycoord(x, y)
|
|
||||||
for i in screen do
|
|
||||||
local geometry = screen[i].geometry
|
|
||||||
if x >= geometry.x and x < geometry.x + geometry.width
|
|
||||||
and y >= geometry.y and y < geometry.y + geometry.height then
|
|
||||||
return capi.screen[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return capi.screen.primary
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get the widget context. This should always return the same table (if
|
-- Get the widget context. This should always return the same table (if
|
||||||
-- possible), so that our draw and fit caches can work efficiently.
|
-- possible), so that our draw and fit caches can work efficiently.
|
||||||
local function get_widget_context(self)
|
local function get_widget_context(self)
|
||||||
local geom = self.drawable:geometry()
|
local geom = self.drawable:geometry()
|
||||||
local s = screen_getbycoord(geom.x, geom.y)
|
|
||||||
|
local sgeos = {}
|
||||||
|
|
||||||
|
for s in capi.screen do
|
||||||
|
sgeos[s] = s.geometry
|
||||||
|
end
|
||||||
|
|
||||||
|
local s = grect.get_by_coord(sgeos, geom.x, geom.y) or capi.screen.primary
|
||||||
|
|
||||||
local context = self._widget_context
|
local context = self._widget_context
|
||||||
local dpi = beautiful.xresources.get_dpi(s)
|
local dpi = beautiful.xresources.get_dpi(s)
|
||||||
if (not context) or context.screen ~= s or context.dpi ~= dpi then
|
if (not context) or context.screen ~= s or context.dpi ~= dpi then
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
local capi = {
|
local capi = {
|
||||||
drawin = drawin,
|
drawin = drawin,
|
||||||
root = root,
|
root = root,
|
||||||
awesome = awesome
|
awesome = awesome,
|
||||||
|
screen = screen
|
||||||
}
|
}
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local type = type
|
local type = type
|
||||||
local object = require("gears.object")
|
local object = require("gears.object")
|
||||||
|
local grect = require("gears.geometry").rectangle
|
||||||
local beautiful = require("beautiful")
|
local beautiful = require("beautiful")
|
||||||
local base = require("wibox.widget.base")
|
local base = require("wibox.widget.base")
|
||||||
|
|
||||||
|
@ -26,234 +28,57 @@ wibox.widget = require("wibox.widget")
|
||||||
wibox.drawable = require("wibox.drawable")
|
wibox.drawable = require("wibox.drawable")
|
||||||
wibox.hierarchy = require("wibox.hierarchy")
|
wibox.hierarchy = require("wibox.hierarchy")
|
||||||
|
|
||||||
--- Set the widget that the wibox displays
|
local force_forward = {
|
||||||
|
shape_bounding = true,
|
||||||
|
shape_clip = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
--@DOC_wibox_COMMON@
|
||||||
|
|
||||||
function wibox:set_widget(widget)
|
function wibox:set_widget(widget)
|
||||||
self._drawable:set_widget(widget)
|
self._drawable:set_widget(widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Import some drawin documentation
|
function wibox:get_widget()
|
||||||
|
return self._drawable.widget
|
||||||
|
end
|
||||||
|
|
||||||
--- Border width.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::border_width*
|
|
||||||
--
|
|
||||||
-- @property border_width
|
|
||||||
-- @param integer
|
|
||||||
|
|
||||||
--- Border color.
|
|
||||||
--
|
|
||||||
-- Please note that this property only support string based 24 bit or 32 bit
|
|
||||||
-- colors:
|
|
||||||
--
|
|
||||||
-- Red Blue
|
|
||||||
-- _| _|
|
|
||||||
-- #FF00FF
|
|
||||||
-- T‾
|
|
||||||
-- Green
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- Red Blue
|
|
||||||
-- _| _|
|
|
||||||
-- #FF00FF00
|
|
||||||
-- T‾ ‾T
|
|
||||||
-- Green Alpha
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::border_color*
|
|
||||||
--
|
|
||||||
-- @property border_color
|
|
||||||
-- @param string
|
|
||||||
|
|
||||||
--- On top of other windows.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::ontop*
|
|
||||||
--
|
|
||||||
-- @property ontop
|
|
||||||
-- @param boolean
|
|
||||||
|
|
||||||
--- The mouse cursor.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::cursor*
|
|
||||||
--
|
|
||||||
-- @property cursor
|
|
||||||
-- @param string
|
|
||||||
-- @see mouse
|
|
||||||
|
|
||||||
--- Visibility.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::visible*
|
|
||||||
--
|
|
||||||
-- @property visible
|
|
||||||
-- @param boolean
|
|
||||||
|
|
||||||
--- The opacity of the wibox, between 0 and 1.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::opacity*
|
|
||||||
--
|
|
||||||
-- @property opacity
|
|
||||||
-- @tparam number opacity (between 0 and 1)
|
|
||||||
|
|
||||||
--- The window type (desktop, normal, dock, ...).
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::type*
|
|
||||||
--
|
|
||||||
-- @property type
|
|
||||||
-- @param string
|
|
||||||
-- @see client.type
|
|
||||||
|
|
||||||
--- The x coordinates.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::x*
|
|
||||||
--
|
|
||||||
-- @property x
|
|
||||||
-- @param integer
|
|
||||||
|
|
||||||
--- The y coordinates.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::y*
|
|
||||||
--
|
|
||||||
-- @property y
|
|
||||||
-- @param integer
|
|
||||||
|
|
||||||
--- The width of the wibox.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::width*
|
|
||||||
--
|
|
||||||
-- @property width
|
|
||||||
-- @param width
|
|
||||||
|
|
||||||
--- The height of the wibox.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::height*
|
|
||||||
--
|
|
||||||
-- @property height
|
|
||||||
-- @param height
|
|
||||||
|
|
||||||
--- The wibox's `drawable`.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::drawable*
|
|
||||||
--
|
|
||||||
-- @property drawable
|
|
||||||
-- @tparam drawable drawable
|
|
||||||
|
|
||||||
--- The X window id.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::window*
|
|
||||||
--
|
|
||||||
-- @property window
|
|
||||||
-- @param string
|
|
||||||
-- @see client.window
|
|
||||||
|
|
||||||
--- The wibox's bounding shape as a (native) cairo surface.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::shape_bounding*
|
|
||||||
--
|
|
||||||
-- @property shape_bounding
|
|
||||||
-- @param surface._native
|
|
||||||
|
|
||||||
--- The wibox's clip shape as a (native) cairo surface.
|
|
||||||
--
|
|
||||||
-- **Signal:**
|
|
||||||
--
|
|
||||||
-- * *property::shape_clip*
|
|
||||||
--
|
|
||||||
-- @property shape_clip
|
|
||||||
-- @param surface._native
|
|
||||||
|
|
||||||
--- Get or set mouse buttons bindings to a wibox.
|
|
||||||
--
|
|
||||||
-- @param buttons_table A table of buttons objects, or nothing.
|
|
||||||
-- @function wibox.buttons
|
|
||||||
|
|
||||||
--- Get or set wibox geometry. That's the same as accessing or setting the x,
|
|
||||||
-- y, width or height properties of a wibox.
|
|
||||||
--
|
|
||||||
-- @param A table with coordinates to modify.
|
|
||||||
-- @return A table with wibox coordinates and geometry.
|
|
||||||
-- @function wibox.geometry
|
|
||||||
|
|
||||||
--- Get or set wibox struts.
|
|
||||||
--
|
|
||||||
-- @param strut A table with new strut, or nothing
|
|
||||||
-- @return The wibox strut in a table.
|
|
||||||
-- @function wibox.struts
|
|
||||||
-- @see client.struts
|
|
||||||
|
|
||||||
--- The default background color.
|
|
||||||
-- @beautiful beautiful.bg_normal
|
|
||||||
-- @see set_bg
|
|
||||||
|
|
||||||
--- The default foreground (text) color.
|
|
||||||
-- @beautiful beautiful.fg_normal
|
|
||||||
-- @see set_fg
|
|
||||||
|
|
||||||
--- Set a declarative widget hierarchy description.
|
|
||||||
-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
|
|
||||||
-- @param args An array containing the widgets disposition
|
|
||||||
-- @name setup
|
|
||||||
-- @class function
|
|
||||||
wibox.setup = base.widget.setup
|
wibox.setup = base.widget.setup
|
||||||
|
|
||||||
--- Set the background of the wibox
|
|
||||||
-- @param c The background to use. This must either be a cairo pattern object,
|
|
||||||
-- nil or a string that gears.color() understands.
|
|
||||||
function wibox:set_bg(c)
|
function wibox:set_bg(c)
|
||||||
self._drawable:set_bg(c)
|
self._drawable:set_bg(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the background image of the drawable
|
|
||||||
-- If `image` is a function, it will be called with `(context, cr, width, height)`
|
|
||||||
-- as arguments. Any other arguments passed to this method will be appended.
|
|
||||||
-- @param image A background image or a function
|
|
||||||
function wibox:set_bgimage(image, ...)
|
function wibox:set_bgimage(image, ...)
|
||||||
self._drawable:set_bgimage(image, ...)
|
self._drawable:set_bgimage(image, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the foreground of the wibox
|
|
||||||
-- @param c The foreground to use. This must either be a cairo pattern object,
|
|
||||||
-- nil or a string that gears.color() understands.
|
|
||||||
function wibox:set_fg(c)
|
function wibox:set_fg(c)
|
||||||
self._drawable:set_fg(c)
|
self._drawable:set_fg(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Find a widget by a point.
|
|
||||||
-- The wibox must have drawn itself at least once for this to work.
|
|
||||||
-- @tparam number x X coordinate of the point
|
|
||||||
-- @tparam number y Y coordinate of the point
|
|
||||||
-- @treturn table A sorted table of widgets positions. The first element is the biggest
|
|
||||||
-- container while the last is the topmost widget. The table contains *x*, *y*,
|
|
||||||
-- *width*, *height* and *widget*.
|
|
||||||
function wibox:find_widgets(x, y)
|
function wibox:find_widgets(x, y)
|
||||||
return self._drawable:find_widgets(x, y)
|
return self._drawable:find_widgets(x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function wibox:get_screen()
|
||||||
|
local sgeos = {}
|
||||||
|
|
||||||
|
for s in capi.screen do
|
||||||
|
sgeos[s] = s.geometry
|
||||||
|
end
|
||||||
|
|
||||||
|
return grect.get_closest_by_coord(sgeos, self.x, self.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
function wibox:set_screen(s)
|
||||||
|
s = capi.screen[s or 1]
|
||||||
|
if s ~= self:get_screen() then
|
||||||
|
self.x = s.geometry.x
|
||||||
|
self.y = s.geometry.y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do
|
for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do
|
||||||
wibox[k] = function(self, ...)
|
wibox[k] = function(self, ...)
|
||||||
return self.drawin[k](self.drawin, ...)
|
return self.drawin[k](self.drawin, ...)
|
||||||
|
@ -297,6 +122,7 @@ local function setup_signals(_wibox)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function new(args)
|
local function new(args)
|
||||||
|
args = args or {}
|
||||||
local ret = object()
|
local ret = object()
|
||||||
local w = capi.drawin(args)
|
local w = capi.drawin(args)
|
||||||
|
|
||||||
|
@ -339,10 +165,24 @@ local function new(args)
|
||||||
-- Make sure the wibox is drawn at least once
|
-- Make sure the wibox is drawn at least once
|
||||||
ret.draw()
|
ret.draw()
|
||||||
|
|
||||||
-- Redirect all non-existing indexes to the "real" drawin
|
-- If a value is not found, look in the drawin
|
||||||
setmetatable(ret, {
|
setmetatable(ret, {
|
||||||
__index = w,
|
__index = function(self, k)
|
||||||
__newindex = w
|
if rawget(self, "get_"..k) then
|
||||||
|
return self["get_"..k](self)
|
||||||
|
else
|
||||||
|
return w[k]
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
__newindex = function(self, k,v)
|
||||||
|
if rawget(self, "set_"..k) then
|
||||||
|
self["set_"..k](self, v)
|
||||||
|
elseif w[k] ~= nil or force_forward[k] then
|
||||||
|
w[k] = v
|
||||||
|
else
|
||||||
|
rawset(self, k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -3423,21 +3423,12 @@ client_class_setup(lua_State *L)
|
||||||
signal_add(&client_class.signals, "property::transient_for");
|
signal_add(&client_class.signals, "property::transient_for");
|
||||||
signal_add(&client_class.signals, "property::type");
|
signal_add(&client_class.signals, "property::type");
|
||||||
signal_add(&client_class.signals, "property::urgent");
|
signal_add(&client_class.signals, "property::urgent");
|
||||||
/**
|
|
||||||
* @signal property::width
|
|
||||||
*/
|
|
||||||
signal_add(&client_class.signals, "property::width");
|
signal_add(&client_class.signals, "property::width");
|
||||||
/**
|
/**
|
||||||
* @signal property::window
|
* @signal property::window
|
||||||
*/
|
*/
|
||||||
signal_add(&client_class.signals, "property::window");
|
signal_add(&client_class.signals, "property::window");
|
||||||
/**
|
|
||||||
* @signal property::x
|
|
||||||
*/
|
|
||||||
signal_add(&client_class.signals, "property::x");
|
signal_add(&client_class.signals, "property::x");
|
||||||
/**
|
|
||||||
* @signal property::y
|
|
||||||
*/
|
|
||||||
signal_add(&client_class.signals, "property::y");
|
signal_add(&client_class.signals, "property::y");
|
||||||
/** When a client should get activated (focused and/or raised).
|
/** When a client should get activated (focused and/or raised).
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
*
|
*
|
||||||
* It is also possible loop over all current screens using:
|
* It is also possible loop over all current screens using:
|
||||||
*
|
*
|
||||||
* for s, screen do
|
* for s in screen do
|
||||||
* -- do something
|
* -- do something
|
||||||
* end
|
* end
|
||||||
*
|
*
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
* The screen workarea.
|
* The screen workarea.
|
||||||
*
|
*
|
||||||
* The workarea is a subsection of the screen where clients can be placed. It
|
* The workarea is a subsection of the screen where clients can be placed. It
|
||||||
* usually excludes the toolbars (see `awful.wibox`) and dockable clients
|
* usually excludes the toolbars (see `awful.wibar`) and dockable clients
|
||||||
* (see `client.dockable`) like WindowMaker DockAPP.
|
* (see `client.dockable`) like WindowMaker DockAPP.
|
||||||
*
|
*
|
||||||
* It can be modified be altering the `wibox` or `client` struts.
|
* It can be modified be altering the `wibox` or `client` struts.
|
||||||
|
@ -756,8 +756,8 @@ void screen_update_workarea(screen_t *screen)
|
||||||
|
|
||||||
area.x += left;
|
area.x += left;
|
||||||
area.y += top;
|
area.y += top;
|
||||||
area.width -= left + right;
|
area.width -= MIN(area.width, left + right);
|
||||||
area.height -= top + bottom;
|
area.height -= MIN(area.height, top + bottom);
|
||||||
|
|
||||||
if (AREA_EQUAL(area, screen->workarea))
|
if (AREA_EQUAL(area, screen->workarea))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -6,3 +6,6 @@ mouse.coords {x= 50, y=50} --DOC_HIDE
|
||||||
mouse.push_history() --DOC_HIDE
|
mouse.push_history() --DOC_HIDE
|
||||||
|
|
||||||
awful.placement.under_mouse(client.focus)
|
awful.placement.under_mouse(client.focus)
|
||||||
|
|
||||||
|
assert(client.focus.x + client.focus.width /2 - mouse.coords().x <= 1) --DOC_HIDE
|
||||||
|
assert(client.focus.y + client.focus.height/2 - mouse.coords().y <= 1) --DOC_HIDE
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
local file_path, image_path, luacovpath = ...
|
local file_path, image_path, luacovpath = ...
|
||||||
|
|
||||||
-- Set the global shims
|
-- Set the global shims
|
||||||
-- luacheck: globals awesome client tag drawin
|
-- luacheck: globals awesome client tag drawin screen
|
||||||
awesome = require( "awesome" )
|
awesome = require( "awesome" )
|
||||||
client = require( "client" )
|
client = require( "client" )
|
||||||
tag = require( "tag" )
|
tag = require( "tag" )
|
||||||
drawin = require( "drawin" )
|
drawin = require( "drawin" )
|
||||||
|
screen = require( "screen" )
|
||||||
|
|
||||||
-- Force luacheck to be silent about setting those as unused globals
|
-- Force luacheck to be silent about setting those as unused globals
|
||||||
assert(awesome and client and tag)
|
assert(awesome and client and tag)
|
||||||
|
|
|
@ -4,6 +4,7 @@ local mouse = mouse
|
||||||
local class = tag
|
local class = tag
|
||||||
local obj = class({})
|
local obj = class({})
|
||||||
local handler = require("gears.object.properties")
|
local handler = require("gears.object.properties")
|
||||||
|
local wibox = require("wibox")
|
||||||
|
|
||||||
awesome.connect_signal("debug::index::miss", error)
|
awesome.connect_signal("debug::index::miss", error)
|
||||||
awesome.connect_signal("debug::newindex::miss", error)
|
awesome.connect_signal("debug::newindex::miss", error)
|
||||||
|
@ -35,4 +36,8 @@ assert(obj.key == 1337)
|
||||||
mouse.foo = "bar"
|
mouse.foo = "bar"
|
||||||
assert(mouse.foo == "bar")
|
assert(mouse.foo == "bar")
|
||||||
|
|
||||||
|
local w = wibox()
|
||||||
|
w.foo = "bar"
|
||||||
|
assert(w.foo == "bar")
|
||||||
|
|
||||||
require("_runner").run_steps({ function() return true end })
|
require("_runner").run_steps({ function() return true end })
|
||||||
|
|
|
@ -0,0 +1,322 @@
|
||||||
|
local placement = require("awful.placement")
|
||||||
|
local wibox = require("wibox")
|
||||||
|
local wibar = require("awful.wibar")
|
||||||
|
|
||||||
|
-- luacheck: globals mywibox
|
||||||
|
local steps = {}
|
||||||
|
|
||||||
|
local parent, small
|
||||||
|
|
||||||
|
local twibar, bwibar, lwibar, rwibar = mywibox[screen.primary]
|
||||||
|
|
||||||
|
-- Test the struts without using wibars
|
||||||
|
table.insert(steps, function()
|
||||||
|
local sgeo = screen.primary.geometry
|
||||||
|
|
||||||
|
-- Manually place at the bottom right
|
||||||
|
local w = wibox{
|
||||||
|
height = 50,
|
||||||
|
width = 50,
|
||||||
|
y = sgeo.y + sgeo.height - 50,
|
||||||
|
x = sgeo.x + sgeo.width - 50,
|
||||||
|
visible = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
w:struts {
|
||||||
|
left = 0,
|
||||||
|
top = 0,
|
||||||
|
bottom = 50,
|
||||||
|
right = 50,
|
||||||
|
}
|
||||||
|
|
||||||
|
local wa = screen.primary.workarea
|
||||||
|
|
||||||
|
assert(wa.x == 0 )
|
||||||
|
assert(wa.y == twibar.height )
|
||||||
|
assert(wa.width == sgeo.width - 50 )
|
||||||
|
assert(wa.height == sgeo.height - 50 - twibar.height)
|
||||||
|
|
||||||
|
w:struts {
|
||||||
|
left = 0,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0,
|
||||||
|
right = 0,
|
||||||
|
}
|
||||||
|
w.visible = false
|
||||||
|
|
||||||
|
wa = screen.primary.workarea
|
||||||
|
|
||||||
|
assert(wa.x == 0 )
|
||||||
|
assert(wa.y == twibar.height )
|
||||||
|
assert(wa.width == sgeo.width )
|
||||||
|
assert(wa.height == sgeo.height - twibar.height)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Test "attach" for wibox/client to wibox
|
||||||
|
table.insert(steps, function()
|
||||||
|
parent = wibox {
|
||||||
|
visible = true,
|
||||||
|
width = 500,
|
||||||
|
height = 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
placement.centered(parent)
|
||||||
|
|
||||||
|
small = wibox {
|
||||||
|
bg = "#ff0000",
|
||||||
|
height = 24,
|
||||||
|
ontop = true,
|
||||||
|
visible = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Add an attached function
|
||||||
|
placement.top_left(small, {parent = parent})
|
||||||
|
placement.maximize_horizontally(small, {parent = parent, attach = true})
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
assert(parent:geometry().width == 500)
|
||||||
|
assert(parent:geometry().height == 500)
|
||||||
|
|
||||||
|
assert(parent:geometry().y == small:geometry().y)
|
||||||
|
assert(parent:geometry().x == small:geometry().x)
|
||||||
|
assert(parent:geometry().width == small:geometry().width )
|
||||||
|
assert(small:geometry().height == 24)
|
||||||
|
|
||||||
|
-- Now, move the parent and see of the attached one is correctly updated
|
||||||
|
placement.stretch_left(parent)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
assert(parent:geometry().y == small:geometry().y)
|
||||||
|
assert(parent:geometry().x == small:geometry().x)
|
||||||
|
assert(parent:geometry().width == small:geometry().width )
|
||||||
|
assert(small:geometry().height == 24)
|
||||||
|
|
||||||
|
-- Do the same, but with placement compositing
|
||||||
|
small = wibox {
|
||||||
|
bg = "#ff0000",
|
||||||
|
height = 50,
|
||||||
|
width = 50,
|
||||||
|
ontop = true,
|
||||||
|
visible = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
local p = placement.bottom_right + placement.scale
|
||||||
|
|
||||||
|
p(small, {parent=parent, attach=true, direction="left", to_percent=0.5})
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function check_ratio()
|
||||||
|
assert(
|
||||||
|
(
|
||||||
|
parent:geometry().y
|
||||||
|
+ parent:geometry().height
|
||||||
|
- small :geometry().height
|
||||||
|
) == small:geometry().y
|
||||||
|
)
|
||||||
|
|
||||||
|
assert(math.abs(parent:geometry().x + math.ceil(parent:geometry().width/2) - small:geometry().x) <= 1)
|
||||||
|
assert(math.abs(math.ceil(parent:geometry().width/2) - small:geometry().width) <= 1)
|
||||||
|
assert(small:geometry().height == 50)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_ratio()
|
||||||
|
|
||||||
|
-- Now, do some more transformation on the parent and make sure the "small"
|
||||||
|
-- wibox follow.
|
||||||
|
placement.scale (parent, {direction="left", to_percent=0.2})
|
||||||
|
placement.scale (parent, {direction="up" , to_percent=0.2})
|
||||||
|
placement.bottom (parent )
|
||||||
|
placement.top_right(parent )
|
||||||
|
placement.centered (parent )
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Do the same checks to see if everything has followed as expected
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_ratio()
|
||||||
|
|
||||||
|
-- Now, test if the wibar has updated the workarea.
|
||||||
|
placement.maximize(parent, {honor_workarea = true})
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
local wa = screen.primary.workarea
|
||||||
|
local sgeo = screen.primary.geometry
|
||||||
|
local wgeo = twibar:geometry()
|
||||||
|
|
||||||
|
assert(wa.width == sgeo.width )
|
||||||
|
assert(wa.x == sgeo.x )
|
||||||
|
assert(wa.y == sgeo.y + wgeo.height )
|
||||||
|
-- assert(wa.height == sgeo.height - wgeo.height)
|
||||||
|
-- assert(wgeo.height == sgeo.height - wa.height )
|
||||||
|
|
||||||
|
assert(parent.y == wa.y )
|
||||||
|
assert(parent.x == wa.x )
|
||||||
|
assert(parent.width == wa.width )
|
||||||
|
assert(parent.height == wa.height )
|
||||||
|
|
||||||
|
-- Add more wibars
|
||||||
|
bwibar = wibar {position = "bottom", bg = "#00ff00"}
|
||||||
|
lwibar = wibar {position = "left" , bg = "#0000ff"}
|
||||||
|
rwibar = wibar {position = "right" , bg = "#ff00ff"}
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Make sure the maximized client has the right size and position
|
||||||
|
local function check_maximize()
|
||||||
|
local pgeo = parent:geometry()
|
||||||
|
|
||||||
|
local margins = {left=0, right=0, top=0, bottom=0}
|
||||||
|
|
||||||
|
for _, w in ipairs {twibar, lwibar, rwibar, bwibar} do
|
||||||
|
if w.visible then
|
||||||
|
local pos = w.position
|
||||||
|
local w_or_h = (pos == "left" or pos == "right") and "width" or "height"
|
||||||
|
margins[pos] = margins[pos] + w[w_or_h]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local sgeo = parent.screen.geometry
|
||||||
|
|
||||||
|
sgeo.x = sgeo.x + margins.left
|
||||||
|
sgeo.y = sgeo.y + margins.top
|
||||||
|
sgeo.width = sgeo.width - margins.left - margins.right
|
||||||
|
sgeo.height = sgeo.height - margins.top - margins.bottom
|
||||||
|
|
||||||
|
local wa = parent.screen.workarea
|
||||||
|
|
||||||
|
for k, v in pairs(wa) do
|
||||||
|
assert(sgeo[k] == v)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(sgeo.width == pgeo.width + 2*parent.border_width)
|
||||||
|
assert(sgeo.height == pgeo.height + 2*parent.border_width)
|
||||||
|
assert(sgeo.x == pgeo.x )
|
||||||
|
assert(sgeo.y == pgeo.y )
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
-- Attach the parent wibox to it is updated along the workarea
|
||||||
|
placement.maximize(parent, {honor_workarea = true, attach = true})
|
||||||
|
|
||||||
|
-- Make the wibox more visible
|
||||||
|
parent.border_color = "#ffff00"
|
||||||
|
parent.border_width = 10
|
||||||
|
parent.ontop = true
|
||||||
|
-- parent.visible = false
|
||||||
|
|
||||||
|
local wa = screen.primary.workarea
|
||||||
|
local sgeo = screen.primary.geometry
|
||||||
|
|
||||||
|
assert(lwibar.width == rwibar.width )
|
||||||
|
assert(lwibar.height == rwibar.height )
|
||||||
|
assert(twibar.x == bwibar.x )
|
||||||
|
assert(twibar.width == bwibar.width )
|
||||||
|
|
||||||
|
-- Check the left wibar size and position
|
||||||
|
assert(lwibar.x == wa.x - lwibar.width )
|
||||||
|
assert(lwibar.height == wa.height )
|
||||||
|
|
||||||
|
-- Check the right wibar size and position
|
||||||
|
assert(rwibar.x == wa.x + wa.width )
|
||||||
|
assert(rwibar.height == wa.height )
|
||||||
|
|
||||||
|
-- Check the bottom wibar size and position
|
||||||
|
assert(bwibar.width == sgeo.width )
|
||||||
|
assert(bwibar.x == 0 )
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
-- There should be a detach callback
|
||||||
|
assert(lwibar.detach_callback)
|
||||||
|
|
||||||
|
-- Begin to move wibars around
|
||||||
|
lwibar.position = "top"
|
||||||
|
assert(lwibar.position == "top")
|
||||||
|
assert(lwibar.y == twibar.height)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
bwibar.position = "right"
|
||||||
|
bwibar.ontop = true
|
||||||
|
rwibar.ontop = true
|
||||||
|
assert(bwibar.position == "right")
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
rwibar.position = "top"
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
bwibar.position = "top"
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
for _, w in ipairs {twibar, lwibar, rwibar, bwibar} do
|
||||||
|
w.position = "right"
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Test visibility
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
twibar.visible = false
|
||||||
|
rwibar.visible = false
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
twibar.visible = true
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
check_maximize()
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
require("_runner").run_steps(steps)
|
Loading…
Reference in New Issue