massive update, probably broken
[dotfiles/.git] / .config / awesome / lain / util / init.lua
1 --[[
2
3      Lain
4      Layouts, widgets and utilities for Awesome WM
5
6      Utilities section
7
8      Licensed under GNU General Public License v2
9       * (c) 2013,      Luca CPZ
10       * (c) 2010-2012, Peter Hofmann
11
12 --]]
13
14 local awful        = require("awful")
15 local sqrt         = math.sqrt
16 local pairs        = pairs
17 local client       = client
18 local tonumber     = tonumber
19 local wrequire     = require("lain.helpers").wrequire
20 local setmetatable = setmetatable
21
22 -- Lain utilities submodule
23 -- lain.util
24 local util = { _NAME = "lain.util" }
25
26 -- Like awful.menu.clients, but only show clients of currently selected tags
27 function util.menu_clients_current_tags(menu, args)
28     -- List of currently selected tags.
29     local cls_tags = awful.screen.focused().selected_tags
30
31     if cls_tags == nil then return nil end
32
33     -- Final list of menu items.
34     local cls_t = {}
35
36     -- For each selected tag get all clients of that tag and add them to
37     -- the menu. A click on a menu item will raise that client.
38     for i = 1,#cls_tags do
39         local t   = cls_tags[i]
40         local cls = t:clients()
41
42         for k, c in pairs(cls) do
43             cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "",
44                                   function ()
45                                       c.minimized = false
46                                       client.focus = c
47                                       c:raise()
48                                   end,
49                                   c.icon }
50         end
51     end
52
53     -- No clients? Then quit.
54     if #cls_t <= 0 then return nil end
55
56     -- menu may contain some predefined values, otherwise start with a
57     -- fresh menu.
58     if not menu then menu = {} end
59
60     -- Set the list of items and show the menu.
61     menu.items = cls_t
62     local m = awful.menu(menu)
63     m:show(args)
64
65     return m
66 end
67
68 -- Magnify a client: set it to "float" and resize it.
69 function util.magnify_client(c, width_f, height_f)
70     if c and not c.floating then
71         util.magnified_client = c
72         util.mc(c, width_f, height_f)
73     else
74         util.magnified_client = nil
75         c.floating = false
76     end
77 end
78
79 -- https://github.com/lcpz/lain/issues/195
80 function util.mc(c, width_f, height_f)
81     c = c or util.magnified_client
82     if not c then return end
83
84     c.floating   = true
85     local s      = awful.screen.focused()
86     local mg     = s.workarea
87     local g      = {}
88     local mwfact = width_f or s.selected_tag.master_width_factor or 0.5
89     g.width      = sqrt(mwfact) * mg.width
90     g.height     = sqrt(height_f or mwfact) * mg.height
91     g.x          = mg.x + (mg.width - g.width) / 2
92     g.y          = mg.y + (mg.height - g.height) / 2
93
94     if c then c:geometry(g) end -- if c is still a valid object
95 end
96
97 -- Non-empty tag browsing
98 -- direction in {-1, 1} <-> {previous, next} non-empty tag
99 function util.tag_view_nonempty(direction, sc)
100    local s = sc or awful.screen.focused()
101
102    for i = 1, #s.tags do
103        awful.tag.viewidx(direction, s)
104        if #s.clients > 0 then
105            return
106        end
107    end
108 end
109
110 -- {{{ Dynamic tagging
111
112 -- Add a new tag
113 function util.add_tag(layout)
114     awful.prompt.run {
115         prompt       = "New tag name: ",
116         textbox      = awful.screen.focused().mypromptbox.widget,
117         exe_callback = function(name)
118             if not name or #name == 0 then return end
119             awful.tag.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }):view_only()
120         end
121     }
122 end
123
124 -- Rename current tag
125 function util.rename_tag()
126     awful.prompt.run {
127         prompt       = "Rename tag: ",
128         textbox      = awful.screen.focused().mypromptbox.widget,
129         exe_callback = function(new_name)
130             if not new_name or #new_name == 0 then return end
131             local t = awful.screen.focused().selected_tag
132             if t then
133                 t.name = new_name
134             end
135         end
136     }
137 end
138
139 -- Move current tag
140 -- pos in {-1, 1} <-> {previous, next} tag position
141 function util.move_tag(pos)
142     local tag = awful.screen.focused().selected_tag
143     if tonumber(pos) <= -1 then
144         awful.tag.move(tag.index - 1, tag)
145     else
146         awful.tag.move(tag.index + 1, tag)
147     end
148 end
149
150 -- Delete current tag
151 -- Any rule set on the tag shall be broken
152 function util.delete_tag()
153     local t = awful.screen.focused().selected_tag
154     if not t then return end
155     t:delete()
156 end
157
158 -- }}}
159
160 -- On the fly useless gaps change
161 function util.useless_gaps_resize(thatmuch, s, t)
162     local scr = s or awful.screen.focused()
163     local tag = t or scr.selected_tag
164     tag.gap = tag.gap + tonumber(thatmuch)
165     awful.layout.arrange(scr)
166 end
167
168 return setmetatable(util, { __index = wrequire })