]> git.madduck.net Git - etc/awesome.git/blob - util/quake.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge pull request #216 from groundflyer/memwidget
[etc/awesome.git] / util / quake.lua
1
2 --[[
3                                                    
4      Licensed under GNU General Public License v2  
5       * (c) 2016, Luke Bonham                      
6                                                    
7 --]]
8
9 local awful  = require("awful")
10 local capi   = { client = client,
11                  mouse  = mouse,
12                  screen = screen,
13                  timer  = timer }
14 local string = string
15
16 local pairs        = pairs
17 local setmetatable = setmetatable
18 local tostring     = tostring
19
20 -- Quake-like Dropdown application spawn
21 -- Original version: https://awesomewm.org/wiki/Drop-down_terminal#Another_solution
22 local quake = {}
23
24 -- If you have a rule like "awful.client.setslave" for your terminals,
25 -- ensure you use an exception for QuakeDD. Otherwise, you may
26 -- run into problems with focus.
27
28 function quake:display()
29    -- First, we locate the client
30    local client = nil
31    local i = 0
32    for c in awful.client.iterate(function (c)
33        -- c.name may be changed!
34                          return c.instance == self.name
35    end, nil, self.screen)
36    do
37        i = i + 1
38        if i == 1 then
39            client = c
40        else
41            -- Additional matching clients, let's remove the sticky bit
42            -- which may persist between awesome restarts. We don't close
43            -- them as they may be valuable. They will just turn into
44            -- normal clients.
45            c.sticky = false
46            c.ontop = false
47            c.above = false
48        end
49    end
50
51    if not client and not self.visible then return end
52
53    if not client then
54       -- The client does not exist, we spawn it
55       awful.util.spawn(self.app .. " " .. string.format(self.argname, self.name),
56       false, self.screen)
57       return
58    end
59
60    -- Resize
61    awful.client.floating.set(client, true)
62    client.border_width = 0
63    client.size_hints_honor = false
64    client:geometry(self.geometry)
65
66    -- Not sticky and on top
67    client.ontop = true
68    client.above = true
69    client.skip_taskbar = true
70    client.sticky = false
71
72    -- Toggle display
73    if self.visible then
74        client.hidden = false
75        client:raise()
76        self.last_tag = tostring(awful.tag.selected(self.screen))
77        client:tags({awful.tag.selected(self.screen)})
78        capi.client.focus = client
79    else
80        client.hidden = true
81        local ctags = client:tags()
82        for i, t in pairs(ctags) do
83            ctags[i] = nil
84        end
85        client:tags(ctags)
86    end
87
88    return client
89 end
90
91 function quake:new(config)
92    local conf = config or {}
93
94    conf.app     = conf.app     or "xterm"    -- application to spawn
95    conf.name    = conf.name    or "QuakeDD"  -- window name
96    conf.argname = conf.argname or "-name %s" -- how to specify window name
97    conf.visible = conf.visible or false      -- initially not visible
98    conf.screen  = conf.screen  or capi.mouse.screen
99
100    -- If width or height <= 1 this is a proportion of the workspace
101    wibox_height = conf.wibox_height or 18       -- statusbar weight
102    height       = conf.height       or 0.25         -- height
103    width        = conf.width        or 1              -- width
104    vert         = conf.vert         or "top"      -- top, bottom or center
105    horiz        = conf.horiz        or "center" -- left, right or center
106
107    -- Compute size
108    local geom = capi.screen[conf.screen].workarea
109    if width  <= 1 then width = geom.width * width end
110    if height <= 1 then height = geom.height * height end
111    local x, y
112    if     horiz == "left"  then x = geom.x
113    elseif horiz == "right" then x = geom.width + geom.x - width
114    else   x = geom.x + (geom.width - width)/2 end
115    if     vert == "top"    then y = geom.y
116    elseif vert == "bottom" then y = geom.height + geom.y - height
117    else   y = geom.y + (geom.height - height)/2 end
118    conf.geometry = { x = x, y = y + wibox_height, width = width, height = height }
119
120    local console = setmetatable(conf, { __index = quake })
121    capi.client.connect_signal("manage", function(c)
122        if c.instance == console.name and c.screen == console.screen then
123            console:display()
124                          end
125    end)
126    capi.client.connect_signal("unmanage", function(c)
127        if c.instance == console.name and c.screen == console.screen then
128            console.visible = false
129                    end
130                 end)
131
132    -- "Reattach" currently running quake application. This is in case awesome is restarted.
133    local reattach = capi.timer { timeout = 0 }
134    reattach:connect_signal("timeout", function()
135        reattach:stop()
136                          console:display()
137    end)
138    reattach:start()
139
140    return console
141 end
142
143 function quake:toggle()
144     current_tag = awful.tag.selected(self.screen)
145     if self.last_tag ~= tostring(current_tag) and self.visible then
146         awful.client.movetotag(current_tag, self:display())
147     else
148         self.visible = not self.visible
149         self:display()
150     end
151 end
152
153 setmetatable(quake, { __call = function(_, ...) return quake:new(...) end })
154
155 return quake