summaryrefslogtreecommitdiff
path: root/teardrop.lua
blob: 75be2d39e62e152d7bf1b895ae122f7c5f0fcba2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
--------------------------------------------------------------------------
-- Drop-down applications manager for the awesome window manager
--------------------------------------------------------------------------
-- Author: Adrian C. <anrxc.sysphere.org>
-- Licensed under the WTFPL version 2
--   * http://sam.zoy.org/wtfpl/COPYING
--------------------------------------------------------------------------
-- To use this module add:
--     require("teardrop")
-- to the top of your rc.lua and call:
--     teardrop.toggle(prog, position, height, width, sticky, screen)
-- from a keybinding
--
-- Parameters:
--   prog     - Program to run, for example: "urxvt" or "gmrun"
--   position - Position, "bottom" to slide in from the bottom of the
--              screen, "center" when creating a scratchpad, by
--              default it drops down from the "top"
--   width    - Width, in absolute pixels when > 1 or a width percentage
--              when < 1, 0.9999 (100% of the screen) by default
--   height   - Height, in absolute pixels when > 1 or a height percentage
--              when < 1, 0.25 (25% of the screen) by default
--   sticky   - Sticky, if true, will make the client visible on all tags
--              (useful when creating a scratchpad), false by default
--   screen   - Screen (optional)
--------------------------------------------------------------------------

-- Grab environment
local pairs = pairs
local awful = require("awful")
local capi = {
    mouse = mouse,
    client = client,
    screen = screen
}


-- Teardrop: Drop-down applications manager for the awesome window manager
module("teardrop")


-- Application visibility toggle
local dropdown = {}
--
-- Create a new window for the drop-down application when it doesn't
-- exist, or toggle between hidden and visible states when it does.
function toggle(prog, position, width, height, sticky, screen)
    local position = position or "top"
    local width    = width    or 0.9999
    local height   = height   or 0.25
    local sticky   = sticky   or false
    local screen   = screen   or capi.mouse.screen

    if not dropdown[prog] then
        -- Create table
        dropdown[prog] = {}

        -- Add unmanage signal for teardrop programs
        capi.client.add_signal("unmanage", function (c)
            for scr, cl in pairs(dropdown[prog]) do
                if cl == c then
                    dropdown[prog][scr] = nil
                end
            end
        end)
    end

    if not dropdown[prog][screen] then
        spawnw = function (c)
            -- Store client
            dropdown[prog][screen] = c

            -- Teardrop clients are floaters
            awful.client.floating.set(c, true)

            -- Client geometry and placement
            local screengeom = capi.screen[screen].workarea

            if width  < 1 then width  = screengeom.width * width   end
            if height < 1 then height = screengeom.height * height end

            if position == "bottom" then
                posx = screengeom.x
                posy = screengeom.height + screengeom.y - height
            elseif position == "center" then
                posx = screengeom.x + (screengeom.width - width) / 2
                posy = screengeom.y + (screengeom.height - height) / 2
            else --  Top of the screen by default
                posx = screengeom.x
                posy = screengeom.y - screengeom.y
            end

            -- Client properties
            c:geometry({
                x = posx,      y = posy,
                width = width, height = height
            })
            --  * skip tasklist and always on top
            c.ontop = true
            c.above = true
            c.skip_taskbar = true
            --  * no titlebar and optional sticky
            if sticky     then c.sticky = true end
            if c.titlebar then
                awful.titlebar.remove(c)
            end

            -- Focus and raise
            c:raise()
            capi.client.focus = c

            -- Remove manage signal
            capi.client.remove_signal("manage", spawnw)
        end

        -- Add manage signal
        capi.client.add_signal("manage", spawnw)

        -- Spawn program
        awful.util.spawn(prog, false)
    else
        -- Get client
        c = dropdown[prog][screen]

        -- Hide when switching the workspace
        if c:isvisible() == false then
            c.hidden = true
            -- Switch the client to the current workspace
            awful.client.movetotag(awful.tag.selected(screen), c)
        end

        -- Focus and raise if hidden
        if c.hidden then
            -- Make sure a scratchpad is centered
            if position == "center" then
                awful.placement.centered(c)
            end
            c.hidden = false
            c:raise()
            capi.client.focus = c
        else -- Hide and detach tags if not
            c.hidden = true
            local tags = c:tags()
            for i, v in pairs(tags) do
                tags[i] = nil
            end
            c:tags(tags)
        end
    end
end