Actualizacion maquina principal
[dotfiles/.git] / .config / awesome / lain / util / quake.lua
diff --git a/.config/awesome/lain/util/quake.lua b/.config/awesome/lain/util/quake.lua
new file mode 100644 (file)
index 0000000..01891b0
--- /dev/null
@@ -0,0 +1,168 @@
+--[[
+
+     Licensed under GNU General Public License v2
+      * (c) 2016, Luca CPZ
+      * (c) 2015, unknown
+
+--]]
+
+local awful        = require("awful")
+local capi         = { client = client }
+local math         = math
+local string       = string
+local pairs        = pairs
+local screen       = screen
+local setmetatable = setmetatable
+
+-- Quake-like Dropdown application spawn
+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()
+    if self.followtag then self.screen = awful.screen.focused() end
+
+    -- 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)
+    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
+        cmd = string.format("%s %s %s", self.app,
+              string.format(self.argname, self.name), self.extra)
+        awful.spawn(cmd, { tag = self.screen.selected_tag })
+        return
+    end
+
+    -- Set geometry
+    client.floating = true
+    client.border_width = self.border
+    client.size_hints_honor = false
+    client:geometry(self.geometry[self.screen.index] or self:compute_size())
+
+    -- Set not sticky and on top
+    client.sticky = false
+    client.ontop = true
+    client.above = true
+    client.skip_taskbar = true
+
+    -- Additional user settings
+    if self.settings then self.settings(client) end
+
+    -- Toggle display
+    if self.visible then
+        client.hidden = false
+        client:raise()
+        self.last_tag = self.screen.selected_tag
+        client:tags({self.screen.selected_tag})
+        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:compute_size()
+    -- skip if we already have a geometry for this screen
+    if not self.geometry[self.screen.index] then
+        local geom
+        if not self.overlap then
+            geom = screen[self.screen.index].workarea
+        else
+            geom = screen[self.screen.index].geometry
+        end
+        local width, height = self.width, self.height
+        if width  <= 1 then width = math.floor(geom.width * width) - 2 * self.border end
+        if height <= 1 then height = math.floor(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
+        self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height }
+    end
+    return self.geometry[self.screen.index]
+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.extra      = conf.extra     or ""         -- extra arguments
+    conf.border     = conf.border    or 1          -- client border width
+    conf.visible    = conf.visible   or false      -- initially not visible
+    conf.followtag  = conf.followtag or false      -- spawn on currently focused screen
+    conf.overlap    = conf.overlap   or false      -- overlap wibox
+    conf.screen     = conf.screen    or awful.screen.focused()
+    conf.settings   = conf.settings
+
+    -- If width or height <= 1 this is a proportion of the workspace
+    conf.height     = conf.height    or 0.25       -- height
+    conf.width      = conf.width     or 1          -- width
+    conf.vert       = conf.vert      or "top"      -- top, bottom or center
+    conf.horiz      = conf.horiz     or "left"     -- left, right or center
+    conf.geometry   = {}                           -- internal use
+
+    local dropdown = setmetatable(conf, { __index = quake })
+
+    capi.client.connect_signal("manage", function(c)
+        if c.instance == dropdown.name and c.screen == dropdown.screen then
+            dropdown:display()
+        end
+    end)
+    capi.client.connect_signal("unmanage", function(c)
+        if c.instance == dropdown.name and c.screen == dropdown.screen then
+            dropdown.visible = false
+        end
+     end)
+
+    return dropdown
+end
+
+function quake:toggle()
+     if self.followtag then self.screen = awful.screen.focused() end
+     local current_tag = self.screen.selected_tag
+     if current_tag and self.last_tag ~= current_tag and self.visible then
+         local c=self:display()
+         if c then
+            c:move_to_tag(current_tag)
+        end
+     else
+         self.visible = not self.visible
+         self:display()
+     end
+end
+
+return setmetatable(quake, { __call = function(_, ...) return quake:new(...) end })