Initial commit before publication.
[berthome:berthome.git] / scratch / pad.lua
1 ---------------------------------------------------------------
2 -- Basic scratchpad manager for the awesome window manager
3 ---------------------------------------------------------------
4 -- Coded by: * Adrian C. (anrxc) <anrxc@sysphere.org>
5 -- Licensed under the WTFPL version 2
6 --   * http://sam.zoy.org/wtfpl/COPYING
7 ---------------------------------------------------------------
8 -- To use this module add:
9 --     require("scratch")
10 -- to the top of your rc.lua, and call:
11 --     scratch.pad.set(c, width, height, sticky, screen)
12 -- from a clientkeys binding, and:
13 --     scratch.pad.toggle(screen)
14 -- from a globalkeys binding.
15 --
16 -- Parameters:
17 --     c      - Client to scratch or un-scratch
18 --     width  - Width in absolute pixels, or width percentage
19 --              when <= 1 (0.50 (50% of the screen) by default)
20 --     height - Height in absolute pixels, or height percentage
21 --              when <= 1 (0.50 (50% of the screen) by default)
22 --     sticky - Visible on all tags, false by default
23 --     screen - Screen (optional), mouse.screen by default
24 ---------------------------------------------------------------
25
26 -- Grab environment
27 local awful = require("awful")
28 local capi = {
29     mouse = mouse,
30     client = client,
31     screen = screen
32 }
33
34 -- Scratchpad: basic scratchpad manager for the awesome window manager
35 module("scratch.pad")
36
37 local scratchpad = {}
38
39 -- Toggle a set of properties on a client.
40 local function toggleprop(c, prop)
41     c.ontop  = prop.ontop  or false
42     c.above  = prop.above  or false
43     c.hidden = prop.hidden or false
44     c.sticky = prop.stick  or false
45     c.skip_taskbar = prop.task or false
46 end
47
48 -- Scratch the focused client, or un-scratch and tile it. If another
49 -- client is already scratched, replace it with the focused client.
50 function set(c, width, height, sticky, screen)
51     width  = width  or 0.50
52     height = height or 0.50
53     sticky = sticky or false
54     screen = screen or capi.mouse.screen
55
56     local function setscratch(c)
57         -- Scratchpad is floating and has no titlebar
58         awful.client.floating.set(c, true); awful.titlebar.remove(c)
59
60         -- Scratchpad client properties
61         toggleprop(c, {ontop=true, above=true, task=true, stick=sticky})
62
63         -- Scratchpad geometry and placement
64         local screengeom = capi.screen[screen].workarea
65         if width  <= 1 then width  = screengeom.width  * width  end
66         if height <= 1 then height = screengeom.height * height end
67
68         c:geometry({ -- Scratchpad is always centered on screen
69             x = screengeom.x + (screengeom.width  - width)  / 2,
70             y = screengeom.y + (screengeom.height - height) / 2,
71             width = width,      height = height
72         })
73
74         -- Scratchpad should not loose focus
75         c:raise(); capi.client.focus = c
76     end
77
78     -- Prepare a table for storing clients,
79     if not scratchpad.pad then scratchpad.pad = {}
80         -- add unmanage signal for scratchpad clients
81         capi.client.add_signal("unmanage", function (c)
82             if scratchpad.pad[screen] == c then
83                 scratchpad.pad[screen] = nil
84             end
85         end)
86     end
87
88     -- If the scratcphad is emtpy, store the client,
89     if not scratchpad.pad[screen] then
90         scratchpad.pad[screen] = c
91         -- then apply geometry and properties
92         setscratch(c)
93     else -- If a client is already scratched,
94         local oc = scratchpad.pad[screen]
95         -- unscratch, and compare it with the focused client
96         awful.client.floating.toggle(oc); toggleprop(oc, {})
97         -- If it matches clear the table, if not replace it
98         if   oc == c then scratchpad.pad[screen] =     nil
99         else scratchpad.pad[screen] = c; setscratch(c) end
100     end
101 end
102
103 -- Move the scratchpad to the current workspace, focus and raise it
104 -- when it's hidden, or hide it when it's visible.
105 function toggle(screen)
106     screen = screen or capi.mouse.screen
107
108     -- Check if we have a client on storage,
109     if scratchpad.pad and
110        scratchpad.pad[screen] ~= nil
111     then -- and get it out, to play
112         local c = scratchpad.pad[screen]
113
114         -- If it's visible on another tag hide it,
115         if c:isvisible() == false then c.hidden = true
116             -- and move it to the current worskpace
117             awful.client.movetotag(awful.tag.selected(screen), c)
118         end
119
120         -- Focus and raise if it's hidden,
121         if c.hidden then
122             awful.placement.centered(c)
123             c.hidden = false
124             c:raise(); capi.client.focus = c
125         else -- hide it if it's not
126             c.hidden = true
127         end
128     end
129 end