]> git.madduck.net Git - etc/awesome.git/blob - util/init.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 branch 'master' of https://github.com/copycat-killer/lain
[etc/awesome.git] / util / init.lua
1
2 --[[
3                                                    
4      Lain                                          
5      Layouts, widgets and utilities for Awesome WM 
6                                                    
7      Utilities section                             
8                                                    
9      Licensed under GNU General Public License v2  
10       * (c) 2013,      Luke Bonham                 
11       * (c) 2010-2012, Peter Hofmann               
12                                                    
13 --]]
14
15 local awful        = require("awful")
16 local beautiful    = require("beautiful")
17 local math         = { sqrt = math.sqrt }
18 local mouse        = mouse
19 local pairs        = pairs
20 local string       = { gsub = string.gsub }
21 local client       = client
22 local screen       = screen
23 local tonumber     = tonumber
24
25 local wrequire     = require("lain.helpers").wrequire
26 local setmetatable = setmetatable
27
28 -- Lain utilities submodule
29 -- lain.util
30 local util = { _NAME = "lain.util" }
31
32 -- Like awful.menu.clients, but only show clients of currently selected
33 -- tags.
34 function util.menu_clients_current_tags(menu, args)
35     -- List of currently selected tags.
36     local cls_tags = awful.tag.selectedlist(mouse.screen)
37
38     -- Final list of menu items.
39     local cls_t = {}
40
41     if cls_tags == nil then return nil end
42
43     -- For each selected tag get all clients of that tag and add them to
44     -- the menu. A click on a menu item will raise that client.
45     for i = 1,#cls_tags
46     do
47         local t = cls_tags[i]
48         local cls = t:clients()
49
50         for k, c in pairs(cls)
51         do
52             cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "",
53                                   function ()
54                                       c.minimized = false
55                                       client.focus = c
56                                       c:raise()
57                                   end,
58                                   c.icon }
59         end
60     end
61
62     -- No clients? Then quit.
63     if #cls_t <= 0 then return nil end
64
65     -- menu may contain some predefined values, otherwise start with a
66     -- fresh menu.
67     if not menu then menu = {} end
68
69     -- Set the list of items and show the menu.
70     menu.items = cls_t
71     local m = awful.menu.new(menu)
72     m:show(args)
73     return m
74 end
75
76 -- Magnify a client: Set it to "float" and resize it.
77 local magnified_client = nil
78 function util.magnify_client(c)
79     if c and not awful.client.floating.get(c) then
80         util.mc(c)
81         magnified_client = c
82     else
83         awful.client.floating.set(c, false)
84         magnified_client = nil
85     end
86 end
87
88 -- https://github.com/copycat-killer/lain/issues/195
89 function util.mc(c)
90     c = c or magnified_client
91     if not c then return end
92     awful.client.floating.set(c, true)
93     local mg = screen[mouse.screen].geometry
94     local tag = awful.tag.selected(mouse.screen)
95     local mwfact = awful.tag.getmwfact(tag)
96     local g = {}
97     g.width = math.sqrt(mwfact) * mg.width
98     g.height = math.sqrt(mwfact) * mg.height
99     g.x = mg.x + (mg.width - g.width) / 2
100     g.y = mg.y + (mg.height - g.height) / 2
101     c:geometry(g)
102 end
103
104 -- Read the nice value of pid from /proc.
105 local function get_nice_value(pid)
106     local n = first_line('/proc/' .. pid .. '/stat')
107     if not n then return 0 end
108
109     -- Remove pid and tcomm. This is necessary because tcomm may contain
110     -- nasty stuff such as whitespace or additional parentheses...
111     n = string.gsub(n, '.*%) ', '')
112
113     -- Field number 17 now is the nice value.
114     fields = split(n, ' ')
115     return tonumber(fields[17])
116 end
117
118 -- To be used as a signal handler for "focus"
119 -- This requires beautiful.border_focus{,_highprio,_lowprio}.
120 function util.niceborder_focus(c)
121     local n = get_nice_value(c.pid)
122     if n == 0
123     then
124         c.border_color = beautiful.border_focus
125     elseif n < 0
126     then
127         c.border_color = beautiful.border_focus_highprio
128     else
129         c.border_color = beautiful.border_focus_lowprio
130     end
131 end
132
133 -- To be used as a signal handler for "unfocus"
134 -- This requires beautiful.border_normal{,_highprio,_lowprio}.
135 function util.niceborder_unfocus(c)
136     local n = get_nice_value(c.pid)
137     if n == 0
138     then
139         c.border_color = beautiful.border_normal
140     elseif n < 0
141     then
142         c.border_color = beautiful.border_normal_highprio
143     else
144         c.border_color = beautiful.border_normal_lowprio
145     end
146 end
147
148 -- Non-empty tag browsing
149 -- direction in {-1, 1} <-> {previous, next} non-empty tag
150 function util.tag_view_nonempty(direction, sc)
151    local s = sc or mouse.screen or 1
152    local scr = screen[s]
153
154    for i = 1, #awful.tag.gettags(s) do
155        awful.tag.viewidx(direction,s)
156        if #awful.client.visible(s) > 0 then
157            return
158        end
159    end
160 end
161
162 -- {{{ Dynamic tagging
163 --
164 -- Add a new tag
165 function util.add_tag(mypromptbox)
166     awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget,
167     function(text)
168         if text:len() > 0 then
169             props = { selected = true }
170             tag = awful.tag.add(new_name, props)
171             tag.name = text
172             tag:emit_signal("property::name")
173         end
174     end)
175 end
176
177 -- Rename current tag
178 -- @author: minism
179 function util.rename_tag(mypromptbox)
180     local tag = awful.tag.selected(mouse.screen)
181     awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget,
182     function(text)
183         if text:len() > 0 then
184             tag.name = text
185             tag:emit_signal("property::name")
186         end
187     end)
188 end
189
190 -- Move current tag
191 -- pos in {-1, 1} <-> {previous, next} tag position
192 function util.move_tag(pos)
193     local tag = awful.tag.selected(mouse.screen)
194     local idx = awful.tag.getidx(tag)
195     if tonumber(pos) <= -1 then
196         awful.tag.move(idx - 1, tag)
197     else
198         awful.tag.move(idx + 1, tag)
199     end
200 end
201
202 -- Remove current tag (if empty)
203 -- Any rule set on the tag shall be broken
204 function util.remove_tag()
205     local tag = awful.tag.selected(mouse.screen)
206     local prevtag = awful.tag.gettags(mouse.screen)[awful.tag.getidx(tag) - 1]
207     awful.tag.delete(tag, prevtag)
208 end
209 --
210 -- }}}
211
212 -- On the fly useless gaps change
213 function util.useless_gaps_resize(thatmuch)
214     beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch
215     awful.layout.arrange(mouse.screen)
216 end
217
218 -- On the fly global border change
219 function util.global_border_resize(thatmuch)
220     beautiful.global_border_width = tonumber(beautiful.global_border_width) + thatmuch
221     awful.layout.arrange(mouse.screen)
222 end
223
224 -- Check if an element exist on a table
225 function util.element_in_table(element, tbl)
226     for _, i in pairs(tbl) do
227         if i == element then
228             return true
229         end
230     end
231     return false
232 end
233
234 return setmetatable(util, { __index = wrequire })