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)
|
||||
|
||||
-- Create the wibox
|
||||
mywibox[s] = awful.wibox({ position = "top", screen = s })
|
||||
mywibox[s] = awful.wibar({ position = "top", screen = s })
|
||||
|
||||
-- Add widgets to the wibox
|
||||
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 spawn = require("awful.spawn")
|
||||
local object = require("gears.object")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local ipairs = ipairs
|
||||
|
@ -197,7 +198,7 @@ function client.swap.bydirection(dir, c, stacked)
|
|||
for i,cl in ipairs(cltbl) do
|
||||
geomtbl[i] = cl:geometry()
|
||||
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 target then
|
||||
|
@ -693,6 +694,54 @@ function client.floating.delete(c)
|
|||
client.object.set_floating(c, nil)
|
||||
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.
|
||||
-- @function awful.client.restore
|
||||
-- @param s The screen to use.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
-- @release @AWESOME_VERSION@
|
||||
-- @submodule client
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
|
||||
local capi =
|
||||
{
|
||||
|
@ -168,7 +168,7 @@ function focus.bydirection(dir, c, stacked)
|
|||
geomtbl[i] = cl:geometry()
|
||||
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 target then
|
||||
|
@ -200,7 +200,7 @@ function focus.global_bydirection(dir, c, stacked)
|
|||
for i,cl in ipairs(cltbl) do
|
||||
geomtbl[i] = cl:geometry()
|
||||
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
|
||||
cltbl[target]:emit_signal("request::activate",
|
||||
|
|
|
@ -51,6 +51,7 @@ return
|
|||
remote = require("awful.remote");
|
||||
key = require("awful.key");
|
||||
button = require("awful.button");
|
||||
wibar = require("awful.wibar");
|
||||
wibox = require("awful.wibox");
|
||||
startup_notification = require("awful.startup_notification");
|
||||
tooltip = require("awful.tooltip");
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
-- Grab environment we need
|
||||
local layout = require("awful.layout")
|
||||
local aplace = require("awful.placement")
|
||||
local awibox = require("awful.wibox")
|
||||
local util = require("awful.util")
|
||||
local type = type
|
||||
local ipairs = ipairs
|
||||
|
@ -123,43 +122,31 @@ end
|
|||
|
||||
--- Move the wibox under the cursor.
|
||||
-- @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)
|
||||
w = w or mouse.wibox_under_pointer()
|
||||
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 = {
|
||||
x = w.x - capi.mouse.coords().x,
|
||||
y = w.y - capi.mouse.coords().y
|
||||
x = geo.x - coords.x,
|
||||
y = geo.y - coords.y,
|
||||
}
|
||||
|
||||
capi.mousegrabber.run(function (_mouse)
|
||||
local button_down = false
|
||||
if awibox.get_position(w) == "floating" then
|
||||
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")
|
||||
mouse.resize(w, "mouse.move", {
|
||||
placement = aplace.under_mouse,
|
||||
offset = offset
|
||||
})
|
||||
end
|
||||
|
||||
--- Get a client corner coordinates.
|
||||
|
@ -234,22 +221,11 @@ function mouse.resize_handler(c, context, hints)
|
|||
local lay = c.screen.selected_tag.layout
|
||||
|
||||
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 {
|
||||
x = hints.x + (offset.x or 0 ),
|
||||
y = hints.y + (offset.y or 0 ),
|
||||
width = hints.width + (offset.width or 0 ),
|
||||
height = hints.height + (offset.height or 0 ),
|
||||
x = hints.x,
|
||||
y = hints.y,
|
||||
width = hints.width,
|
||||
height = hints.height,
|
||||
}
|
||||
elseif lay.resize_handler then
|
||||
lay.resize_handler(c, context, hints)
|
||||
|
|
|
@ -51,6 +51,11 @@
|
|||
--
|
||||
-- **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*):
|
||||
--
|
||||
-- The offset(s) to apply to the new geometry.
|
||||
|
@ -88,6 +93,7 @@ local capi =
|
|||
local client = require("awful.client")
|
||||
local layout = require("awful.layout")
|
||||
local a_screen = require("awful.screen")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
local util = require("awful.util")
|
||||
local dpi = require("beautiful").xresources.apply_dpi
|
||||
|
||||
|
@ -96,6 +102,15 @@ local function get_screen(s)
|
|||
end
|
||||
|
||||
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.
|
||||
-- This also allow the functions to be aware they are being chained and act
|
||||
|
@ -123,7 +138,8 @@ local function compose(...)
|
|||
end
|
||||
end
|
||||
|
||||
local ret = wrap_client(function(d, args, ...)
|
||||
local ret
|
||||
ret = wrap_client(function(d, args, ...)
|
||||
local rets = {}
|
||||
local last_geo = nil
|
||||
|
||||
|
@ -134,13 +150,16 @@ local function compose(...)
|
|||
-- Only apply the geometry once, not once per chain node, to do this,
|
||||
-- Force the "pretend" argument and restore the original value for
|
||||
-- the last node.
|
||||
local pretend_real = args.pretend
|
||||
|
||||
args.pretend = true
|
||||
local attach_real = args.attach
|
||||
args.pretend = true
|
||||
args.attach = false
|
||||
args.offset = {}
|
||||
|
||||
for k, f in ipairs(queue) do
|
||||
if k == #queue then
|
||||
args.pretend = pretend_real or false
|
||||
-- Let them fallback to the parent table
|
||||
args.pretend = nil
|
||||
args.offset = nil
|
||||
end
|
||||
|
||||
local r = {f(d, args, ...)}
|
||||
|
@ -160,6 +179,11 @@ local function compose(...)
|
|||
end
|
||||
end
|
||||
|
||||
if attach_real then
|
||||
args.attach = true
|
||||
attach(d, ret, args)
|
||||
end
|
||||
|
||||
return last_geo, rets
|
||||
end, "compose")
|
||||
|
||||
|
@ -189,7 +213,7 @@ local placement_private = {}
|
|||
--
|
||||
-- (awful.placement.no_overlap + awful.placement.no_offscreen)(c)
|
||||
--
|
||||
local placement = setmetatable({}, {
|
||||
placement = setmetatable({}, {
|
||||
__index = placement_private,
|
||||
__newindex = function(_, k, f)
|
||||
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,
|
||||
}
|
||||
|
||||
-- Store function -> keys
|
||||
local reverse_align_map = {}
|
||||
|
||||
-- Some parameters to correctly compute the final size
|
||||
local resize_to_point_map = {
|
||||
-- Corners
|
||||
|
@ -259,39 +280,61 @@ local function store_geometry(d, reqtype)
|
|||
data[d][reqtype].screen = d.screen
|
||||
end
|
||||
|
||||
--- Get the margins and offset
|
||||
-- @tparam table args The arguments
|
||||
-- @treturn table The margins
|
||||
-- @treturn table The offsets
|
||||
local function get_decoration(args)
|
||||
local offset = args.offset
|
||||
|
||||
-- Offset are "blind" values added to the output
|
||||
offset = type(offset) == "number" and {
|
||||
x = offset,
|
||||
y = offset,
|
||||
width = 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
|
||||
|
||||
--- 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)
|
||||
if args.pretend or not new_geo then return nil end
|
||||
local function fix_new_geometry(new_geo, args, force)
|
||||
if (args.pretend and not force) or not new_geo then return nil end
|
||||
|
||||
local offset = args.offset or {}
|
||||
|
||||
if type(offset) == "number" then
|
||||
offset = {
|
||||
x = offset,
|
||||
y = offset,
|
||||
width = offset,
|
||||
height = offset,
|
||||
}
|
||||
end
|
||||
local m, offset = get_decoration(args)
|
||||
|
||||
return {
|
||||
x = new_geo.x and (new_geo.x + (offset.x or 0)),
|
||||
y = new_geo.y and (new_geo.y + (offset.y or 0)),
|
||||
width = new_geo.width and (new_geo.width + (offset.width or 0)),
|
||||
height = new_geo.height and (new_geo.height + (offset.height 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) + (m.top or 0) ),
|
||||
width = new_geo.width and math.max(
|
||||
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
|
||||
|
||||
--- Get the area covered by a drawin.
|
||||
-- Get the area covered by a drawin.
|
||||
-- @param d The drawin
|
||||
-- @tparam[opt=nil] table new_geo A new geometry
|
||||
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
|
||||
-- @tparam table args the method arguments
|
||||
-- @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
|
||||
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
|
||||
|
@ -316,7 +359,6 @@ end
|
|||
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
|
||||
-- @treturn table A table with *x*, *y*, *width* and *height*.
|
||||
local function geometry_common(obj, args, new_geo, ignore_border_width)
|
||||
|
||||
-- Store the current geometry in a singleton-memento
|
||||
if args.store_geometry and new_geo and args.context then
|
||||
store_geometry(obj, args.context)
|
||||
|
@ -338,16 +380,13 @@ local function geometry_common(obj, args, new_geo, ignore_border_width)
|
|||
|
||||
-- Apply the margins
|
||||
if args.margins then
|
||||
local delta = type(args.margins) == "table" and args.margins or {
|
||||
left = args.margins , right = args.margins,
|
||||
top = args.margins , bottom = args.margins
|
||||
}
|
||||
local delta = get_decoration(args)
|
||||
|
||||
return {
|
||||
x = dgeo.x + (delta.left or 0),
|
||||
y = dgeo.y + (delta.top or 0),
|
||||
width = dgeo.width - (delta.left or 0) - (delta.right or 0),
|
||||
height = dgeo.height - (delta.top or 0) - (delta.bottom or 0),
|
||||
x = dgeo.x - (delta.left or 0),
|
||||
y = dgeo.y - (delta.top or 0),
|
||||
width = dgeo.width + (delta.left or 0) + (delta.right or 0),
|
||||
height = dgeo.height + (delta.top or 0) + (delta.bottom or 0),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -367,12 +406,18 @@ end
|
|||
-- @tparam table args the method arguments
|
||||
-- @treturn table A table with *x*, *y*, *width* and *height*.
|
||||
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
|
||||
return args.bounding_rect
|
||||
elseif args.parent then
|
||||
return geometry_common(args.parent, args)
|
||||
return geometry_common(args.parent, {})
|
||||
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
|
||||
return geometry_common(capi.screen[capi.mouse.screen], args)
|
||||
end
|
||||
|
@ -405,7 +450,7 @@ local function move_into_geometry(source, target)
|
|||
end
|
||||
|
||||
-- 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 not d.visible then
|
||||
d:struts { left = 0, right = 0, bottom = 0, top = 0 }
|
||||
|
@ -420,16 +465,18 @@ local function wibox_update_strut(d, position)
|
|||
-- the workarea
|
||||
local struts = { left = 0, right = 0, bottom = 0, top = 0 }
|
||||
|
||||
local m = get_decoration(args)
|
||||
|
||||
if vertical then
|
||||
for _, v in ipairs {"right", "left"} do
|
||||
if (not position) or position:match(v) then
|
||||
struts[v] = geo.width
|
||||
struts[v] = geo.width + m[v]
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, v in ipairs {"top", "bottom"} do
|
||||
if (not position) or position:match(v) then
|
||||
struts[v] = geo.height
|
||||
struts[v] = geo.height + m[v]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -438,16 +485,18 @@ local function wibox_update_strut(d, position)
|
|||
d:struts(struts)
|
||||
end
|
||||
|
||||
--- Pin a drawable to a placement function.
|
||||
-- Pin a drawable to a placement function.
|
||||
-- Automatically update the position when the size change.
|
||||
-- All other arguments will be passed to the `position` function (if any)
|
||||
-- @tparam[opt=client.focus] drawable d A drawable (like `client`, `mouse`
|
||||
-- or `wibox`)
|
||||
-- @param position_f A position name (see `align`) or a position function
|
||||
-- @tparam[opt={}] table args Other arguments
|
||||
local function attach(d, position_f, args)
|
||||
attach = function(d, position_f, args)
|
||||
args = args or {}
|
||||
|
||||
if args.pretend then return end
|
||||
|
||||
if not args.attach then return end
|
||||
|
||||
-- Avoid a connection loop
|
||||
|
@ -462,110 +511,78 @@ local function attach(d, position_f, args)
|
|||
|
||||
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()
|
||||
position_f(d, args)
|
||||
end
|
||||
|
||||
d:connect_signal("property::width" , tracker)
|
||||
d:connect_signal("property::height", tracker)
|
||||
d:connect_signal("property::width" , tracker)
|
||||
d:connect_signal("property::height" , tracker)
|
||||
d:connect_signal("property::border_width", tracker)
|
||||
|
||||
tracker()
|
||||
local function tracker_struts()
|
||||
--TODO this is too fragile and doesn't work with all methods.
|
||||
wibox_update_strut(d, d.position or reverse_align_map[position_f], args)
|
||||
end
|
||||
|
||||
local parent = args.parent or d.screen
|
||||
|
||||
if args.update_workarea then
|
||||
local function tracker_struts()
|
||||
--TODO this is too fragile and doesn't work with all methods.
|
||||
wibox_update_strut(d, reverse_align_map[position_f])
|
||||
end
|
||||
|
||||
d:connect_signal("property::geometry" , tracker_struts)
|
||||
d:connect_signal("property::visible" , tracker_struts)
|
||||
capi.client.connect_signal("property::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
|
||||
|
||||
-- If there is a parent drawable, screen or mouse, also track it
|
||||
local parent = args.parent or d.screen
|
||||
if parent then
|
||||
args.parent:connect_signal("property::geometry" , tracker)
|
||||
parent:connect_signal("property::geometry" , tracker)
|
||||
end
|
||||
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
|
||||
-- Create a way to detach a placement function
|
||||
d:add_signal("property::detach_callback")
|
||||
function d.detach_callback()
|
||||
d:disconnect_signal("property::width" , tracker)
|
||||
d:disconnect_signal("property::height" , tracker)
|
||||
d:disconnect_signal("property::border_width", tracker)
|
||||
if parent then
|
||||
parent:disconnect_signal("property::geometry" , tracker)
|
||||
|
||||
--- Get the intersect area between a and b.
|
||||
-- @param a The area.
|
||||
-- @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
|
||||
if parent == d.screen then
|
||||
if args.honor_workarea then
|
||||
parent:disconnect_signal("property::workarea", tracker)
|
||||
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)
|
||||
})
|
||||
if args.honor_padding then
|
||||
parent:disconnect_signal("property::padding", tracker)
|
||||
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
|
||||
|
||||
-- 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 ngeo = placement_private.align(d, new_args)
|
||||
|
||||
return ngeo, corner
|
||||
return fix_new_geometry(ngeo, args, true), corner
|
||||
end
|
||||
|
||||
--- 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 }
|
||||
for _, cl in pairs(cls) do
|
||||
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
|
||||
|
||||
|
@ -751,7 +768,9 @@ function placement.under_mouse(d, args)
|
|||
ngeo.width = ngeo.width - 2*bw
|
||||
ngeo.height = ngeo.height - 2*bw
|
||||
|
||||
return ngeo
|
||||
geometry_common(d, args, ngeo)
|
||||
|
||||
return fix_new_geometry(ngeo, args, true)
|
||||
end
|
||||
|
||||
--- Place the client next to the mouse.
|
||||
|
@ -862,7 +881,7 @@ function placement.resize_to_mouse(d, args)
|
|||
|
||||
geometry_common(d, args, ngeo)
|
||||
|
||||
return ngeo
|
||||
return fix_new_geometry(ngeo, args, true)
|
||||
end
|
||||
|
||||
--- 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)
|
||||
|
||||
return ngeo
|
||||
return fix_new_geometry(ngeo, args, true)
|
||||
end
|
||||
|
||||
-- Add the alias functions
|
||||
|
@ -1002,7 +1021,7 @@ function placement.stretch(d, args)
|
|||
|
||||
attach(d, placement["stretch_"..args.direction], args)
|
||||
|
||||
return ngeo
|
||||
return fix_new_geometry(ngeo, args, true)
|
||||
end
|
||||
|
||||
-- Add the alias functions
|
||||
|
@ -1056,7 +1075,7 @@ function placement.maximize(d, args)
|
|||
|
||||
attach(d, placement.maximize, args)
|
||||
|
||||
return ngeo
|
||||
return fix_new_geometry(ngeo, args, true)
|
||||
end
|
||||
|
||||
-- Add the alias functions
|
||||
|
@ -1121,7 +1140,7 @@ function placement.scale(d, args)
|
|||
|
||||
attach(d, placement.maximize, args)
|
||||
|
||||
return ngeo
|
||||
return fix_new_geometry(ngeo, args, true)
|
||||
end
|
||||
|
||||
---@DOC_awful_placement_maximize_vertically_EXAMPLE@
|
||||
|
|
|
@ -16,6 +16,7 @@ local capi =
|
|||
}
|
||||
local util = require("awful.util")
|
||||
local object = require("gears.object")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
|
||||
local function get_screen(s)
|
||||
return s and capi.screen[s]
|
||||
|
@ -62,20 +63,7 @@ end
|
|||
-- @tparam number y Y coordinate of point
|
||||
-- @treturn number The squared distance of the screen to the provided point
|
||||
function screen.object.get_square_distance(self, x, y)
|
||||
self = get_screen(self)
|
||||
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
|
||||
return grect.get_square_distance(get_screen(self).geometry, x, y)
|
||||
end
|
||||
|
||||
---
|
||||
|
@ -83,20 +71,18 @@ end
|
|||
-- The number returned can be used as an index into the global
|
||||
-- `screen` table/object.
|
||||
-- @function awful.screen.getbycoord
|
||||
-- @param x The x coordinate
|
||||
-- @param y The y coordinate
|
||||
-- @tparam number x The x coordinate
|
||||
-- @tparam number y The y coordinate
|
||||
-- @treturn ?number The screen index
|
||||
function screen.getbycoord(x, y)
|
||||
local dist = math.huge
|
||||
local s = capi.screen.primary
|
||||
if s then
|
||||
dist = screen.object.get_square_distance(s, x, y)
|
||||
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
|
||||
local s, sgeos = capi.screen.primary, {}
|
||||
|
||||
for scr in capi.screen do
|
||||
sgeos[scr] = scr.geometry
|
||||
end
|
||||
|
||||
s = grect.get_closest_by_coord(sgeos, x, y) or s
|
||||
|
||||
return s and s.index
|
||||
end
|
||||
|
||||
|
@ -151,7 +137,7 @@ function screen.focus_bydirection(dir, _screen)
|
|||
for s in capi.screen do
|
||||
geomtbl[s] = capi.screen[s].geometry
|
||||
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
|
||||
return screen.focus(target)
|
||||
end
|
||||
|
|
|
@ -20,6 +20,7 @@ local type = type
|
|||
local rtable = table
|
||||
local string = string
|
||||
local lgi = require("lgi")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
local Gio = require("lgi").Gio
|
||||
local Pango = lgi.Pango
|
||||
local capi =
|
||||
|
@ -301,76 +302,18 @@ function util.subsets(set)
|
|||
return ret
|
||||
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.
|
||||
-- @deprecated awful.util.get_rectangle_in_direction
|
||||
-- @param dir The direction, can be either "up", "down", "left" or "right".
|
||||
-- @param recttbl A table of rectangle specifications.
|
||||
-- @param cur The current rectangle.
|
||||
-- @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)
|
||||
local dist, dist_min
|
||||
local target = nil
|
||||
util.deprecate("gears.geometry.rectangle.get_in_direction")
|
||||
|
||||
-- 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
|
||||
return grect.get_in_direction(dir, recttbl, cur)
|
||||
end
|
||||
|
||||
--- 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 allows you to easily create wibox and attach them to the edge of
|
||||
-- a screen.
|
||||
--- This module is deprecated and has been renamed `awful.wibar`
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
||||
-- @copyright 2016 Emmanuel Lepage Vallee
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @module awful.wibox
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
local wibar = require("awful.wibar")
|
||||
|
||||
-- Grab environment we need
|
||||
local capi =
|
||||
{
|
||||
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 call(_,...)
|
||||
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||
|
||||
local function get_screen(s)
|
||||
return s and capi.screen[s]
|
||||
return wibar(...)
|
||||
end
|
||||
|
||||
local awfulwibox = { mt = {} }
|
||||
local function index(_, k)
|
||||
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||
|
||||
--- Array of table with wiboxes inside.
|
||||
-- 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"
|
||||
return wibar[k]
|
||||
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 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
|
||||
local function newindex(_, k, v)
|
||||
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||
|
||||
-- The "length" of a wibox is always chosen to be the optimal size
|
||||
-- (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
|
||||
|
||||
for _, wprop in ipairs(wiboxes) do
|
||||
if wprop.wibox == wb then
|
||||
wprop.position = position
|
||||
break
|
||||
end
|
||||
end
|
||||
wibar[k] = v
|
||||
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)
|
||||
return setmetatable({}, {__call = call, __index = index, __newindex = newindex})
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
---------------------------------------------------------------------------
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local capi = { screen = screen }
|
||||
local capi = { screen = screen, tag = tag }
|
||||
local layout = require("awful.layout")
|
||||
local tooltip = require("awful.tooltip")
|
||||
local tag = require("awful.tag")
|
||||
local beautiful = require("beautiful")
|
||||
local imagebox = require("wibox.widget.imagebox")
|
||||
|
||||
|
@ -48,8 +47,8 @@ function layoutbox.new(screen)
|
|||
-- Do we already have the update callbacks registered?
|
||||
if boxes == nil then
|
||||
boxes = setmetatable({}, { __mode = "kv" })
|
||||
tag.attached_connect_signal(nil, "property::selected", update_from_tag)
|
||||
tag.attached_connect_signal(nil, "property::layout", update_from_tag)
|
||||
capi.tag.connect_signal("property::selected", update_from_tag)
|
||||
capi.tag.connect_signal("property::layout", update_from_tag)
|
||||
layoutbox.boxes = boxes
|
||||
end
|
||||
|
||||
|
@ -60,7 +59,7 @@ function layoutbox.new(screen)
|
|||
w._layoutbox_tooltip = tooltip({ objects = {w}, delay_show = 1 })
|
||||
|
||||
update(w, screen)
|
||||
boxes[screen] = w
|
||||
boxes[screen] = setmetatable({}, {__index = w, __newindex = w})
|
||||
end
|
||||
|
||||
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");
|
||||
shape = require("gears.shape");
|
||||
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
|
||||
|
|
|
@ -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 surface = require("gears.surface")
|
||||
local timer = require("gears.timer")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
local matrix = require("gears.matrix")
|
||||
local hierarchy = require("wibox.hierarchy")
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
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
|
||||
-- possible), so that our draw and fit caches can work efficiently.
|
||||
local function get_widget_context(self)
|
||||
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 dpi = beautiful.xresources.get_dpi(s)
|
||||
if (not context) or context.screen ~= s or context.dpi ~= dpi then
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
local capi = {
|
||||
drawin = drawin,
|
||||
root = root,
|
||||
awesome = awesome
|
||||
awesome = awesome,
|
||||
screen = screen
|
||||
}
|
||||
local setmetatable = setmetatable
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local object = require("gears.object")
|
||||
local grect = require("gears.geometry").rectangle
|
||||
local beautiful = require("beautiful")
|
||||
local base = require("wibox.widget.base")
|
||||
|
||||
|
@ -26,234 +28,57 @@ wibox.widget = require("wibox.widget")
|
|||
wibox.drawable = require("wibox.drawable")
|
||||
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)
|
||||
self._drawable:set_widget(widget)
|
||||
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
|
||||
|
||||
--- 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)
|
||||
self._drawable:set_bg(c)
|
||||
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, ...)
|
||||
self._drawable:set_bgimage(image, ...)
|
||||
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)
|
||||
self._drawable:set_fg(c)
|
||||
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)
|
||||
return self._drawable:find_widgets(x, y)
|
||||
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
|
||||
wibox[k] = function(self, ...)
|
||||
return self.drawin[k](self.drawin, ...)
|
||||
|
@ -297,6 +122,7 @@ local function setup_signals(_wibox)
|
|||
end
|
||||
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
local ret = object()
|
||||
local w = capi.drawin(args)
|
||||
|
||||
|
@ -339,10 +165,24 @@ local function new(args)
|
|||
-- Make sure the wibox is drawn at least once
|
||||
ret.draw()
|
||||
|
||||
-- Redirect all non-existing indexes to the "real" drawin
|
||||
-- If a value is not found, look in the drawin
|
||||
setmetatable(ret, {
|
||||
__index = w,
|
||||
__newindex = w
|
||||
__index = function(self, k)
|
||||
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
|
||||
|
|
|
@ -3423,21 +3423,12 @@ client_class_setup(lua_State *L)
|
|||
signal_add(&client_class.signals, "property::transient_for");
|
||||
signal_add(&client_class.signals, "property::type");
|
||||
signal_add(&client_class.signals, "property::urgent");
|
||||
/**
|
||||
* @signal property::width
|
||||
*/
|
||||
signal_add(&client_class.signals, "property::width");
|
||||
/**
|
||||
* @signal property::window
|
||||
*/
|
||||
signal_add(&client_class.signals, "property::window");
|
||||
/**
|
||||
* @signal property::x
|
||||
*/
|
||||
signal_add(&client_class.signals, "property::x");
|
||||
/**
|
||||
* @signal property::y
|
||||
*/
|
||||
signal_add(&client_class.signals, "property::y");
|
||||
/** When a client should get activated (focused and/or raised).
|
||||
*
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
* It is also possible loop over all current screens using:
|
||||
*
|
||||
* for s, screen do
|
||||
* for s in screen do
|
||||
* -- do something
|
||||
* end
|
||||
*
|
||||
|
@ -117,7 +117,7 @@
|
|||
* The screen workarea.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.y += top;
|
||||
area.width -= left + right;
|
||||
area.height -= top + bottom;
|
||||
area.width -= MIN(area.width, left + right);
|
||||
area.height -= MIN(area.height, top + bottom);
|
||||
|
||||
if (AREA_EQUAL(area, screen->workarea))
|
||||
return;
|
||||
|
|
|
@ -6,3 +6,6 @@ mouse.coords {x= 50, y=50} --DOC_HIDE
|
|||
mouse.push_history() --DOC_HIDE
|
||||
|
||||
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 = ...
|
||||
|
||||
-- Set the global shims
|
||||
-- luacheck: globals awesome client tag drawin
|
||||
-- luacheck: globals awesome client tag drawin screen
|
||||
awesome = require( "awesome" )
|
||||
client = require( "client" )
|
||||
tag = require( "tag" )
|
||||
drawin = require( "drawin" )
|
||||
screen = require( "screen" )
|
||||
|
||||
-- Force luacheck to be silent about setting those as unused globals
|
||||
assert(awesome and client and tag)
|
||||
|
|
|
@ -4,6 +4,7 @@ local mouse = mouse
|
|||
local class = tag
|
||||
local obj = class({})
|
||||
local handler = require("gears.object.properties")
|
||||
local wibox = require("wibox")
|
||||
|
||||
awesome.connect_signal("debug::index::miss", error)
|
||||
awesome.connect_signal("debug::newindex::miss", error)
|
||||
|
@ -35,4 +36,8 @@ assert(obj.key == 1337)
|
|||
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 })
|
||||
|
|
|
@ -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