From 606a995b90b682b0a9a88d55ecc675bb9ce39700 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sun, 26 Jun 2016 13:13:22 +0200 Subject: [PATCH] added quake --- util/quake.lua | 159 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 util/quake.lua diff --git a/util/quake.lua b/util/quake.lua new file mode 100644 index 0000000..9f703b0 --- /dev/null +++ b/util/quake.lua @@ -0,0 +1,159 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2016, Luke Bonham + +--]] + +local awful = require("awful") +local capi = { client = client, + mouse = mouse, + screen = screen, + timer = timer } +local string = string + +local pairs = pairs +local setmetatable = setmetatable +local tostring = tostring + +-- Quake-like Dropdown application spawn +-- Original version: https://awesomewm.org/wiki/Drop-down_terminal#Another_solution +local quake = {} + +-- If you have a rule like "awful.client.setslave" for your terminals, +-- ensure you use an exception for QuakeDD. Otherwise, you may +-- run into problems with focus. + +function quake:display() + -- First, we locate the client + local client = nil + local i = 0 + for c in awful.client.iterate(function (c) + -- c.name may be changed! + return c.instance == self.name + end, nil, self.screen) + do + i = i + 1 + if i == 1 then + client = c + else + -- Additional matching clients, let's remove the sticky bit + -- which may persist between awesome restarts. We don't close + -- them as they may be valuable. They will just turn into + -- normal clients. + c.sticky = false + c.ontop = false + c.above = false + end + end + + if not client and not self.visible then return end + + if not client then + -- The client does not exist, we spawn it + awful.util.spawn(self.app .. " " .. string.format(self.argname, self.name), + false, self.screen) + return + end + + -- Resize + awful.client.floating.set(client, true) + client.border_width = 0 + client.size_hints_honor = false + client:geometry(self.geometry) + + -- Not sticky and on top + client.ontop = true + client.above = true + client.skip_taskbar = true + client.sticky = false + + -- 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() + self.last_tag = tostring(awful.tag.selected(self.screen)) + client:tags({awful.tag.selected(self.screen)}) + capi.client.focus = client + else + client.hidden = true + local ctags = client:tags() + for i, t in pairs(ctags) do + ctags[i] = nil + end + client:tags(ctags) + end + + return client +end + +function quake:new(config) + local conf = config or {} + + conf.app = conf.app or "xterm" -- application to spawn + conf.name = conf.name or "QuakeDD" -- window name + conf.argname = conf.argname or "-name %s" -- how to specify window name + conf.visible = conf.visible or false -- initially not visible + conf.screen = conf.screen or capi.mouse.screen + + -- If width or height <= 1 this is a proportion of the workspace + wibox_height = conf.wibox_height or 18 -- statusbar weight + height = conf.height or 0.25 -- height + width = conf.width or 1 -- width + vert = conf.vert or "top" -- top, bottom or center + horiz = conf.horiz or "center" -- left, right or center + + -- Compute size + local geom = capi.screen[conf.screen].workarea + if width <= 1 then width = geom.width * width end + if height <= 1 then height = geom.height * height end + local x, y + if horiz == "left" then x = geom.x + elseif horiz == "right" then x = geom.width + geom.x - width + else x = geom.x + (geom.width - width)/2 end + if vert == "top" then y = geom.y + elseif vert == "bottom" then y = geom.height + geom.y - height + else y = geom.y + (geom.height - height)/2 end + conf.geometry = { x = x, y = y + wibox_height, width = width, height = height } + + local console = setmetatable(conf, { __index = quake }) + capi.client.connect_signal("manage", function(c) + if c.instance == console.name and c.screen == console.screen then + console:display() + end + end) + capi.client.connect_signal("unmanage", function(c) + if c.instance == console.name and c.screen == console.screen then + console.visible = false + end + end) + + -- "Reattach" currently running quake application. This is in case awesome is restarted. + local reattach = capi.timer { timeout = 0 } + reattach:connect_signal("timeout", function() + reattach:stop() + console:display() + end) + reattach:start() + + return console +end + +function quake:toggle() + current_tag = awful.tag.selected(self.screen) + if self.last_tag ~= tostring(current_tag) and self.visible then + awful.client.movetotag(current_tag, self:display()) + else + self.visible = not self.visible + self:display() + end +end + +setmetatable(quake, { __call = function(_, ...) return quake:new(...) end }) + +return quake -- 2.39.2