commit
d0fcf9b369
|
@ -35,8 +35,8 @@ local function draw_mouse(x, y)
|
|||
end
|
||||
|
||||
-- Print an outline for the screens
|
||||
if not screen.no_outline then
|
||||
for _, s in ipairs(screen) do
|
||||
if not rawget(screen, "no_outline") then
|
||||
for s in screen do
|
||||
cr:save()
|
||||
-- Draw the screen outline
|
||||
cr:set_source(color("#00000044"))
|
||||
|
|
|
@ -75,6 +75,10 @@ function awesome.pixbuf_to_surface(_, path)
|
|||
return awesome.load_image(path)
|
||||
end
|
||||
|
||||
function awesome.xrdb_get_value()
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Always show deprecated messages
|
||||
awesome.version = "v9999"
|
||||
|
||||
|
|
|
@ -22,6 +22,45 @@ local function titlebar_meta(c)
|
|||
end
|
||||
end
|
||||
|
||||
local properties = {}
|
||||
|
||||
-- Emit the request::geometry signal to make immobilized and awful.ewmh work.
|
||||
for _, prop in ipairs {
|
||||
"maximized", "maximized_horizontal", "maximized_vertical", "fullscreen" } do
|
||||
properties["get_"..prop] = function(self)
|
||||
return self.data[prop] or false
|
||||
end
|
||||
|
||||
properties["set_"..prop] = function(self, value)
|
||||
self.data[prop] = value or false
|
||||
|
||||
if value then
|
||||
self:emit_signal("request::geometry", prop, nil)
|
||||
end
|
||||
|
||||
self:emit_signal("property::"..prop, value)
|
||||
end
|
||||
end
|
||||
|
||||
function properties.get_screen(self)
|
||||
return self.data.screen or screen[1]
|
||||
end
|
||||
|
||||
function properties.set_screen(self, s)
|
||||
s = screen[s]
|
||||
self.data.screen = s
|
||||
|
||||
if self.x < s.geometry.x or self.x > s.geometry.x+s.geometry.width then
|
||||
self:geometry { x = s.geometry.x }
|
||||
end
|
||||
|
||||
if self.y < s.geometry.y or self.y > s.geometry.y+s.geometry.height then
|
||||
self:geometry { y = s.geometry.y }
|
||||
end
|
||||
|
||||
self:emit_signal("property::screen")
|
||||
end
|
||||
|
||||
-- Create fake clients to move around
|
||||
function client.gen_fake(args)
|
||||
local ret = gears_obj()
|
||||
|
@ -34,6 +73,7 @@ function client.gen_fake(args)
|
|||
ret.border_width = 1
|
||||
ret.icon_sizes = {{16,16}}
|
||||
ret.name = "Example Client"
|
||||
ret.data._struts = { top = 0, right = 0, left = 0, bottom = 0 }
|
||||
|
||||
-- This is a hack because there's a `:is_transient_for(c2)` method
|
||||
-- and a `transient_for` property. It will cause a stack overflow
|
||||
|
@ -49,6 +89,7 @@ function client.gen_fake(args)
|
|||
-- Tests should always set a geometry, but just in case
|
||||
for _, v in ipairs{"x","y","width","height"} do
|
||||
ret[v] = ret[v] or 1
|
||||
assert((not args[v]) or ret[v] == args[v])
|
||||
end
|
||||
|
||||
-- Emulate capi.client.geometry
|
||||
|
@ -89,6 +130,10 @@ function client.gen_fake(args)
|
|||
return nil
|
||||
end
|
||||
|
||||
function ret:set_xproperty(prop, value)
|
||||
ret[prop] = value
|
||||
end
|
||||
|
||||
function ret:get_icon(_)
|
||||
return require("beautiful").awesome_icon
|
||||
end
|
||||
|
@ -101,6 +146,32 @@ function client.gen_fake(args)
|
|||
--TODO
|
||||
end
|
||||
|
||||
function ret:apply_size_hints(w, h)
|
||||
return w or ret.width, h or ret.height
|
||||
end
|
||||
|
||||
function ret:kill()
|
||||
local old_tags = ret:tags() or {}
|
||||
|
||||
for k, c in ipairs(clients) do
|
||||
if c == ret then
|
||||
ret:emit_signal("unmanaged", c)
|
||||
ret.valid = false
|
||||
table.remove(clients, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
ret._tags = {}
|
||||
|
||||
for _, t in ipairs(old_tags) do
|
||||
ret:emit_signal("untagged", t)
|
||||
t:emit_signal("property::tags")
|
||||
end
|
||||
|
||||
assert(not ret.valid)
|
||||
end
|
||||
|
||||
titlebar_meta(ret)
|
||||
|
||||
function ret:tags(new) --FIXME
|
||||
|
@ -121,14 +192,55 @@ function client.gen_fake(args)
|
|||
return {}
|
||||
end
|
||||
|
||||
function ret:struts(new)
|
||||
for k, v in pairs(new or {}) do
|
||||
ret.data._struts[k] = v
|
||||
end
|
||||
|
||||
return ret.data._struts
|
||||
end
|
||||
|
||||
function ret:struts(new)
|
||||
for k, v in pairs(new or {}) do
|
||||
ret.data._struts[k] = v
|
||||
end
|
||||
|
||||
return ret.data._struts
|
||||
end
|
||||
|
||||
-- Set a dummy one for now since set_screen will corrupt it.
|
||||
ret._old_geo = {}
|
||||
|
||||
-- Set the screen attributes.
|
||||
local s = args.screen
|
||||
|
||||
-- Pick the screen from the geometry.
|
||||
if not s then
|
||||
for s2 in screen do
|
||||
local geo = s2.geometry
|
||||
if geo.x >= ret.x and geo.y >= ret.y and ret.x < geo.x+geo.width
|
||||
and ret.y < geo.y+geo.height then
|
||||
s = s2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This will happen if the screen coords are not {0,0} and the client had
|
||||
-- an unspecified position.
|
||||
s = s or screen[1]
|
||||
|
||||
properties.set_screen(ret, s)
|
||||
|
||||
-- Set the geometry *again* because the screen possibly overwrote it.
|
||||
for _, v in ipairs{"x","y","width","height"} do
|
||||
ret[v] = args[v] or ret[v]
|
||||
end
|
||||
|
||||
-- Record the geometry
|
||||
ret._old_geo = {}
|
||||
push_geometry(ret)
|
||||
ret._old_geo[1]._hide = args.hide_first
|
||||
|
||||
-- Set the attributes
|
||||
ret.screen = args.screen or screen[1]
|
||||
|
||||
-- Good enough for the geometry and border
|
||||
ret.drawin = ret
|
||||
ret.drawable = ret
|
||||
|
@ -138,10 +250,6 @@ function client.gen_fake(args)
|
|||
ret.below = false
|
||||
ret.above = false
|
||||
ret.sticky = false
|
||||
ret.maximized = false
|
||||
ret.fullscreen = false
|
||||
ret.maximized_vertical = false
|
||||
ret.maximized_horizontal = false
|
||||
|
||||
-- Add to the client list
|
||||
table.insert(clients, ret)
|
||||
|
@ -149,8 +257,21 @@ function client.gen_fake(args)
|
|||
client.focus = ret
|
||||
|
||||
setmetatable(ret, {
|
||||
__index = function(...) return meta.__index(...) end,
|
||||
__newindex = function(...) return meta.__newindex(...) end
|
||||
__index = function(self, key)
|
||||
if properties["get_"..key] then
|
||||
return properties["get_"..key](self)
|
||||
end
|
||||
|
||||
return meta.__index(self, key)
|
||||
end,
|
||||
__newindex = function(self, key, value)
|
||||
|
||||
if properties["set_"..key] then
|
||||
return properties["set_"..key](self, value)
|
||||
end
|
||||
|
||||
return meta.__newindex(self, key, value)
|
||||
end
|
||||
})
|
||||
|
||||
client.emit_signal("manage", ret)
|
||||
|
|
|
@ -35,11 +35,20 @@ local function new_drawin(_, args)
|
|||
ret.data.drawable.surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
|
||||
ret.data.drawable.geometry = ret.geometry
|
||||
ret.data.drawable.refresh = function() end
|
||||
ret.data._struts = { top = 0, right = 0, left = 0, bottom = 0 }
|
||||
|
||||
for _, k in pairs{ "buttons", "struts", "get_xproperty", "set_xproperty" } do
|
||||
for _, k in pairs{ "buttons", "get_xproperty", "set_xproperty" } do
|
||||
ret[k] = function() end
|
||||
end
|
||||
|
||||
function ret:struts(new)
|
||||
for k, v in pairs(new or {}) do
|
||||
ret.data._struts[k] = v
|
||||
end
|
||||
|
||||
return ret.data._struts
|
||||
end
|
||||
|
||||
local md = setmetatable(ret, {
|
||||
__index = function(...) return meta.__index(...) end,
|
||||
__newindex = function(...) return meta.__newindex(...) end
|
||||
|
|
|
@ -53,20 +53,42 @@ function mouse.push_history()
|
|||
mouse.history = {}
|
||||
end
|
||||
|
||||
local forced_screen = nil
|
||||
|
||||
return setmetatable(mouse, {
|
||||
__index = function(self, key)
|
||||
if key == "screen" then
|
||||
return screen[1]
|
||||
if forced_screen and screen._deleted[forced_screen] then
|
||||
forced_screen = nil
|
||||
end
|
||||
|
||||
for s in screen do
|
||||
if coords.x > s.geometry.x and coords.x < s.geometry.x +s.geometry.width
|
||||
and coords.y > s.geometry.y and coords.y < s.geometry.y +s.geometry.height then
|
||||
return s
|
||||
end
|
||||
end
|
||||
|
||||
-- Using capi.mouse.screen is *not* supported when there is zero
|
||||
-- screen. Nearly all the code uses `mouse.screen` as its ultimate
|
||||
-- fallback. Having no screens is tolerated during early
|
||||
-- initialization and that's it.
|
||||
return screen.count() > 0 and screen[1] or assert(
|
||||
false, "Calling `mouse.screen` without screens isn't supported"
|
||||
)
|
||||
end
|
||||
local h = rawget(mouse,"_i_handler")
|
||||
if h then
|
||||
return h(self, key)
|
||||
end
|
||||
end,
|
||||
__newindex = function(...)
|
||||
__newindex = function(_, k, v)
|
||||
local h = rawget(mouse,"_ni_handler")
|
||||
if h then
|
||||
h(...)
|
||||
if k == "screen" then
|
||||
-- This will assert if the screen is invalid
|
||||
forced_screen = v and screen[v] or nil
|
||||
elseif h then
|
||||
h(_, k, v)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
|
|
@ -8,12 +8,22 @@ function root:tags()
|
|||
return root._tags
|
||||
end
|
||||
|
||||
function root:size() --TODO use the screens
|
||||
return 0, 0
|
||||
function root.size()
|
||||
local geo = {x1 = math.huge, y1 = math.huge, x2 = 0, y2 = 0}
|
||||
|
||||
for s in screen do
|
||||
geo.x1 = math.min( geo.x1, s.geometry.x )
|
||||
geo.y1 = math.min( geo.y1, s.geometry.y )
|
||||
geo.x2 = math.max( geo.x2, s.geometry.x+s.geometry.width )
|
||||
geo.y2 = math.max( geo.y2, s.geometry.y+s.geometry.height )
|
||||
end
|
||||
|
||||
return math.max(0, geo.x2-geo.x1), math.max(0, geo.y2 - geo.y1)
|
||||
end
|
||||
|
||||
function root:size_mm()
|
||||
return 0, 0
|
||||
function root.size_mm()
|
||||
local w, h = root.size()
|
||||
return (w/96)*25.4, (h/96)*25.4
|
||||
end
|
||||
|
||||
function root.cursor() end
|
||||
|
|
|
@ -1,7 +1,31 @@
|
|||
local gears_obj = require("gears.object")
|
||||
local gears_tab = require("gears.table")
|
||||
|
||||
local screen, meta = awesome._shim_fake_class()
|
||||
screen._count = 0
|
||||
screen._count, screen._deleted = 0, {}
|
||||
|
||||
local function compute_workarea(s)
|
||||
local struts = {top=0,bottom=0,left=0,right=0}
|
||||
|
||||
for _, c in ipairs(drawin.get()) do
|
||||
for k,v in pairs(struts) do
|
||||
struts[k] = v + (c:struts()[k] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
for _, c in ipairs(client.get()) do
|
||||
for k,v in pairs(struts) do
|
||||
struts[k] = v + (c:struts()[k] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
x = s.geometry.x + struts.left,
|
||||
y = s.geometry.y + struts.top ,
|
||||
width = s.geometry.width - struts.left - struts.right ,
|
||||
height = s.geometry.height - struts.top - struts.bottom,
|
||||
}
|
||||
end
|
||||
|
||||
local function create_screen(args)
|
||||
local s = gears_obj()
|
||||
|
@ -19,7 +43,7 @@ local function create_screen(args)
|
|||
}
|
||||
|
||||
function s._resize(args2)
|
||||
local old = s.geometry
|
||||
local old = gears_tab.clone(s.geometry)
|
||||
geo.x = args2.x or geo.x
|
||||
geo.y = args2.y or geo.y
|
||||
geo.width = args2.width or geo.width
|
||||
|
@ -27,39 +51,71 @@ local function create_screen(args)
|
|||
s:emit_signal("property::geometry", old)
|
||||
end
|
||||
|
||||
s.outputs = { ["LVDS1"] = {
|
||||
mm_width = 0,
|
||||
mm_height = 0,
|
||||
function s.fake_resize(self, x, y, width, height)
|
||||
self._resize {
|
||||
x=x,y=y,width=width,height=height
|
||||
}
|
||||
end
|
||||
|
||||
function s:fake_remove()
|
||||
local i = s.index
|
||||
table.remove(screen, i)
|
||||
screen._deleted[s] = true
|
||||
s:emit_signal("removed")
|
||||
screen[screen[i]] = nil
|
||||
s.valid = false
|
||||
end
|
||||
|
||||
function s:swap(other_s)
|
||||
local s1geo = gears_tab.clone(s.geometry)
|
||||
local s2geo = gears_tab.clone(other_s.geometry)
|
||||
|
||||
s:fake_resize(
|
||||
s2geo.x, s2geo.y, s2geo.width, s2geo.height
|
||||
)
|
||||
other_s:fake_resize(
|
||||
s1geo.x, s1geo.y, s1geo.width, s1geo.height
|
||||
)
|
||||
|
||||
s:emit_signal("swapped",other_s)
|
||||
other_s:emit_signal("swapped",s)
|
||||
end
|
||||
|
||||
s.outputs = { LVDS1 ={
|
||||
name = "LVDS1",
|
||||
mm_width = (geo.width /96)*25.4,
|
||||
mm_height = (geo.height/96)*25.4,
|
||||
}}
|
||||
|
||||
local wa = args.workarea_sides or 10
|
||||
|
||||
-- This will happen if `clear()` is called
|
||||
if mouse and not mouse.screen then
|
||||
mouse.screen = s
|
||||
end
|
||||
|
||||
return setmetatable(s,{ __index = function(_, key)
|
||||
if key == "geometry" then
|
||||
return {
|
||||
x = geo.x or 0,
|
||||
y = geo.y or 0,
|
||||
width = geo.width ,
|
||||
height = geo.height,
|
||||
}
|
||||
elseif key == "workarea" then
|
||||
return {
|
||||
x = (geo.x or 0) + wa ,
|
||||
y = (geo.y or 0) + wa ,
|
||||
width = geo.width - 2*wa,
|
||||
height = geo.height - 2*wa,
|
||||
}
|
||||
else
|
||||
return meta.__index(_, key)
|
||||
end
|
||||
end,
|
||||
__newindex = function(...) return meta.__newindex(...) end
|
||||
})
|
||||
assert(s.valid)
|
||||
|
||||
if key == "geometry" then
|
||||
return {
|
||||
x = geo.x or 0,
|
||||
y = geo.y or 0,
|
||||
width = geo.width ,
|
||||
height = geo.height,
|
||||
}
|
||||
elseif key == "workarea" then
|
||||
if screen._track_workarea then
|
||||
return compute_workarea(s)
|
||||
else
|
||||
return {
|
||||
x = (geo.x or 0) + wa ,
|
||||
y = (geo.y or 0) + wa ,
|
||||
width = geo.width - 2*wa,
|
||||
height = geo.height - 2*wa,
|
||||
}
|
||||
end
|
||||
else
|
||||
return meta.__index(_, key)
|
||||
end
|
||||
end,
|
||||
__newindex = function(...) assert(s.valid); return meta.__newindex(...) end
|
||||
})
|
||||
end
|
||||
|
||||
local screens = {}
|
||||
|
@ -74,11 +130,13 @@ function screen._add_screen(args)
|
|||
screen[#screen+1] = s
|
||||
screen[s] = s
|
||||
screen._count = screen._count + 1
|
||||
|
||||
return s
|
||||
end
|
||||
|
||||
function screen._get_extents()
|
||||
local xmax, ymax
|
||||
for _, v in ipairs(screen) do
|
||||
for v in screen do
|
||||
if not xmax or v.geometry.x+v.geometry.width > xmax.geometry.x+xmax.geometry.width then
|
||||
xmax = v
|
||||
end
|
||||
|
@ -90,8 +148,47 @@ function screen._get_extents()
|
|||
return xmax.geometry.x+xmax.geometry.width, ymax.geometry.y+ymax.geometry.height
|
||||
end
|
||||
|
||||
-- The way the `screen` module is used to store both number and object is
|
||||
-- problematic since it can cause invalid screens to be "resurrected".
|
||||
local function catch_invalid(_, s)
|
||||
-- The CAPI implementation allows `nil`
|
||||
if s == nil then return end
|
||||
|
||||
-- Try to get the screens by output name.
|
||||
if type(s) == "string" then
|
||||
for s2 in screen do
|
||||
for out in pairs(s2.outputs or {}) do
|
||||
if out == s then
|
||||
return s2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assert(screen ~= s, "Some code tried (and failed) to shadow the global `screen`")
|
||||
|
||||
-- Valid numbers wont get this far.
|
||||
assert(type(s) == "table", "Expected a table, but got a "..type(s))
|
||||
|
||||
if type(s) == "number" then return end
|
||||
|
||||
assert(s.geometry, "The object is not a screen")
|
||||
assert(s.outputs, "The object is not a screen")
|
||||
|
||||
assert((not screen._deleted[s]) or (not s.valid), "The shims are broken")
|
||||
|
||||
assert(not screen._deleted[s], "The screen "..tostring(s).."has been deleted")
|
||||
|
||||
-- Other errors. If someone place an object in the `screen` module, it wont
|
||||
-- get this far. So the remaining cases are probably bugs.
|
||||
assert(false)
|
||||
end
|
||||
|
||||
function screen._clear()
|
||||
assert(#screen == screen._count)
|
||||
for i=1, #screen do
|
||||
screen._deleted[screen[i]] = true
|
||||
screen[i].valid = false
|
||||
screen[screen[i]] = nil
|
||||
screen[i] = nil
|
||||
end
|
||||
|
@ -126,11 +223,21 @@ local function iter_scr(_, _, s)
|
|||
|
||||
local i = s.index
|
||||
|
||||
if i + 1 < #screen then
|
||||
if i < #screen then
|
||||
return screen[i+1], i+1
|
||||
end
|
||||
end
|
||||
|
||||
function screen._areas()
|
||||
return {}
|
||||
end
|
||||
|
||||
function screen.fake_add(x,y,width,height)
|
||||
return screen._add_screen {
|
||||
x=x,y=y,width=width,height=height
|
||||
}
|
||||
end
|
||||
|
||||
screen._add_screen {width=320, height=240}
|
||||
|
||||
screen._grid_vertical_margin = 10
|
||||
|
@ -138,12 +245,15 @@ screen._grid_horizontal_margin = 10
|
|||
|
||||
screen.primary = screen[1]
|
||||
|
||||
screen._track_workarea = false
|
||||
|
||||
function screen.count()
|
||||
return screen._count
|
||||
end
|
||||
|
||||
return setmetatable(screen, {
|
||||
__call = iter_scr
|
||||
__call = iter_scr,
|
||||
__index = catch_invalid
|
||||
})
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -16,15 +16,19 @@ local function new_tag(_, args)
|
|||
awesome._forward_class(ret, tag)
|
||||
|
||||
ret.data = {}
|
||||
ret.name = args.name or "test"
|
||||
ret.name = tostring(args.name) or "test"
|
||||
ret.activated = true
|
||||
ret.selected = not has_selected_tag(args.screen)
|
||||
|
||||
function ret:clients(_) --TODO handle new
|
||||
local list = {}
|
||||
for _, c in ipairs(client.get()) do
|
||||
if c.screen == (ret.screen or screen[1]) then
|
||||
table.insert(list, c)
|
||||
if #c:tags() > 0 then
|
||||
for _, t in ipairs(c:tags()) do
|
||||
if t == ret then
|
||||
table.insert(list, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue