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.
5 Layouts, widgets and utilities for Awesome WM
9 Licensed under GNU General Public License v2
10 * (c) 2013, Luke Bonham
11 * (c) 2010-2012, Peter Hofmann
15 local awful = require("awful")
16 local beautiful = require("beautiful")
17 local math = { sqrt = math.sqrt }
20 local string = { gsub = string.gsub }
23 local tonumber = tonumber
25 local wrequire = require("lain.helpers").wrequire
26 local setmetatable = setmetatable
28 -- Lain utilities submodule
30 local util = { _NAME = "lain.util" }
32 -- Like awful.menu.clients, but only show clients of currently selected
34 function util.menu_clients_current_tags(menu, args)
35 -- List of currently selected tags.
36 local cls_tags = awful.tag.selectedlist(mouse.screen)
38 -- Final list of menu items.
41 if cls_tags == nil then return nil end
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.
48 local cls = t:clients()
50 for k, c in pairs(cls)
52 cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "",
62 -- No clients? Then quit.
63 if #cls_t <= 0 then return nil end
65 -- menu may contain some predefined values, otherwise start with a
67 if not menu then menu = {} end
69 -- Set the list of items and show the menu.
71 local m = awful.menu.new(menu)
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
83 awful.client.floating.set(c, false)
84 magnified_client = nil
88 -- https://github.com/copycat-killer/lain/issues/195
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)
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
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
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, '.*%) ', '')
113 -- Field number 17 now is the nice value.
114 fields = split(n, ' ')
115 return tonumber(fields[17])
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)
124 c.border_color = beautiful.border_focus
127 c.border_color = beautiful.border_focus_highprio
129 c.border_color = beautiful.border_focus_lowprio
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)
139 c.border_color = beautiful.border_normal
142 c.border_color = beautiful.border_normal_highprio
144 c.border_color = beautiful.border_normal_lowprio
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]
154 for i = 1, #awful.tag.gettags(s) do
155 awful.tag.viewidx(direction,s)
156 if #awful.client.visible(s) > 0 then
162 -- {{{ Dynamic tagging
165 function util.add_tag(mypromptbox)
166 awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget,
168 if text:len() > 0 then
169 props = { selected = true }
170 tag = awful.tag.add(new_name, props)
172 tag:emit_signal("property::name")
177 -- Rename current tag
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,
183 if text:len() > 0 then
185 tag:emit_signal("property::name")
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)
198 awful.tag.move(idx + 1, tag)
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)
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)
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)
224 -- Check if an element exist on a table
225 function util.element_in_table(element, tbl)
226 for _, i in pairs(tbl) do
234 return setmetatable(util, { __index = wrequire })