mirror of
https://github.com/vincentbernat/i3wm-configuration.git
synced 2025-06-21 09:35:40 +02:00
140 lines
4.3 KiB
Lua
140 lines
4.3 KiB
Lua
-- Quake like console on top
|
|
-- Similar to:
|
|
-- http://git.sysphere.org/awesome-configs/tree/scratch/drop.lua
|
|
|
|
-- But uses a different implementation. The main difference is that we
|
|
-- are able to detect the Quake console from its name
|
|
-- (QuakeConsoleNeedsUniqueName by default).
|
|
|
|
-- If you have a rule like "awful.client.setslave" for your terminals,
|
|
-- ensure you use an exception for
|
|
-- QuakeConsoleNeedsUniqueName. Otherwise, you may run into problems
|
|
-- with focus.
|
|
|
|
local setmetatable = setmetatable
|
|
local string = string
|
|
local awful = require("awful")
|
|
local capi = { mouse = mouse,
|
|
screen = screen,
|
|
client = client,
|
|
timer = timer }
|
|
|
|
-- I use a namespace for my modules...
|
|
module("vbe/quake")
|
|
|
|
local QuakeConsole = {}
|
|
|
|
-- Display
|
|
function QuakeConsole:display()
|
|
-- First, we locate the terminal
|
|
local client = nil
|
|
local i = 0
|
|
for c in awful.client.cycle(function (c)
|
|
-- c.name may be changed!
|
|
return (c.instance == self.name or c.role == self.name)
|
|
end) do
|
|
client = c
|
|
client:tags({})
|
|
break
|
|
end
|
|
|
|
if not client and not self.visible then
|
|
-- The terminal is not here yet but we don't want it yet. Just do nothing.
|
|
return
|
|
end
|
|
|
|
if not client then
|
|
-- The client does not exist, we spawn it
|
|
awful.util.spawn(self.terminal .. " " .. string.format(self.argname, self.name))
|
|
return
|
|
end
|
|
|
|
-- Comptute size
|
|
local geom = capi.screen[capi.mouse.screen].workarea
|
|
local width, height = self.width, self.height
|
|
if width <= 1 then width = geom.width * width end
|
|
if height <= 1 then height = geom.height * height end
|
|
local x, y
|
|
if self.horiz == "left" then x = geom.x
|
|
elseif self.horiz == "right" then x = geom.width + geom.x - width
|
|
else x = geom.x + (geom.width - width)/2 end
|
|
if self.vert == "top" then y = geom.y
|
|
elseif self.vert == "bottom" then y = geom.height + geom.y - height
|
|
else y = geom.y + (geom.height - height)/2 end
|
|
|
|
-- Resize
|
|
awful.client.floating.set(client, true)
|
|
client.border_width = 0
|
|
client.size_hints_honor = false
|
|
client:geometry({ x = x, y = y, width = width, height = height })
|
|
|
|
-- Sticky and on top
|
|
client.ontop = true
|
|
client.above = true
|
|
client.skip_taskbar = true
|
|
client.sticky = true
|
|
|
|
-- This is not a normal window, don't apply any specific keyboard stuff
|
|
client:buttons({})
|
|
client:keys({})
|
|
|
|
-- Toggle display
|
|
if self.visible then
|
|
client.hidden = false
|
|
client:raise()
|
|
capi.client.focus = client
|
|
else
|
|
client.hidden = true
|
|
end
|
|
end
|
|
|
|
-- Create a console
|
|
function QuakeConsole:new(config)
|
|
-- The "console" object is just its configuration.
|
|
|
|
-- The application to be invoked is:
|
|
-- config.terminal .. " " .. string.format(config.argname, config.name)
|
|
config.terminal = config.terminal or "xterm" -- application to spawn
|
|
config.name = config.name or "QuakeConsoleNeedsUniqueName" -- window name
|
|
config.argname = config.argname or "-name %s" -- how to specify window name
|
|
|
|
-- If width or height <= 1 this is a proportion of the workspace
|
|
config.height = config.height or 0.25 -- height
|
|
config.width = config.width or 1 -- width
|
|
config.vert = config.vert or "top" -- top, bottom or center
|
|
config.horiz = config.horiz or "center" -- left, right or center
|
|
|
|
config.visible = config.visible or false -- Initially, not visible
|
|
|
|
local console = setmetatable(config, { __index = QuakeConsole })
|
|
capi.client.add_signal("manage",
|
|
function(c)
|
|
if (c.instance == console.name or c.role == console.name) then
|
|
console:display()
|
|
end
|
|
end)
|
|
capi.client.add_signal("unmanage",
|
|
function(c)
|
|
if (c.instance == console.name or c.role == console.name) then
|
|
console.visible = false
|
|
end
|
|
end)
|
|
|
|
-- "Reattach" currently running QuakeConsole. This is in case awesome is restarted.
|
|
local reattach = capi.timer { timeout = 0 }
|
|
reattach:add_signal("timeout",
|
|
function()
|
|
reattach:stop()
|
|
console:display()
|
|
end)
|
|
reattach:start()
|
|
return console
|
|
end
|
|
|
|
-- Toggle the console
|
|
function QuakeConsole:toggle()
|
|
self.visible = not self.visible
|
|
self:display()
|
|
end
|
|
|
|
setmetatable(_M, { __call = function(_, ...) return QuakeConsole:new(...) end })
|