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.screen.focused().selected_tags
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
94 local s = awful.screen.selected()
96 local tag = s.selected_tag
97 local mwfact = beautiful.master_width_factor or 0.5
99 g.width = math.sqrt(mwfact) * mg.width
100 g.height = math.sqrt(mwfact) * mg.height
101 g.x = mg.x + (mg.width - g.width) / 2
102 g.y = mg.y + (mg.height - g.height) / 2
104 if c then c:geometry(g) end -- if c is still a valid object
107 -- Read the nice value of pid from /proc.
108 local function get_nice_value(pid)
109 local n = first_line('/proc/' .. pid .. '/stat')
110 if not n then return 0 end
112 -- Remove pid and tcomm. This is necessary because tcomm may contain
113 -- nasty stuff such as whitespace or additional parentheses...
114 n = string.gsub(n, '.*%) ', '')
116 -- Field number 17 now is the nice value.
117 fields = split(n, ' ')
118 return tonumber(fields[17])
121 -- To be used as a signal handler for "focus"
122 -- This requires beautiful.border_focus{,_highprio,_lowprio}.
123 function util.niceborder_focus(c)
124 local n = get_nice_value(c.pid)
127 c.border_color = beautiful.border_focus
130 c.border_color = beautiful.border_focus_highprio
132 c.border_color = beautiful.border_focus_lowprio
136 -- To be used as a signal handler for "unfocus"
137 -- This requires beautiful.border_normal{,_highprio,_lowprio}.
138 function util.niceborder_unfocus(c)
139 local n = get_nice_value(c.pid)
142 c.border_color = beautiful.border_normal
145 c.border_color = beautiful.border_normal_highprio
147 c.border_color = beautiful.border_normal_lowprio
151 -- Non-empty tag browsing
152 -- direction in {-1, 1} <-> {previous, next} non-empty tag
153 function util.tag_view_nonempty(direction, sc)
154 local s = sc or awful.screen.focused()
155 local scr = screen[s]
157 for i = 1, #s.tags do
158 awful.tag.viewidx(direction, s)
159 if #s.clients > 0 then
165 -- {{{ Dynamic tagging
168 function util.add_tag()
170 prompt = "New tag name: ",
171 textbox = awful.screen.focused().mypromptbox.widget,
172 exe_callback = function(name)
173 if not name or #name == 0 then return end
174 awful.tag.add(name, { screen = awful.screen.focused() }):view_only()
179 -- Rename current tag
180 function util.rename_tag()
182 prompt = "Rename tag: ",
183 textbox = awful.screen.focused().mypromptbox.widget,
184 exe_callback = function(new_name)
185 if not new_name or #new_name == 0 then return end
186 local t = awful.screen.focused().selected_tag
195 -- pos in {-1, 1} <-> {previous, next} tag position
196 function util.move_tag(pos)
197 local tag = awful.screen.focused().selected_tag
198 local idx = awful.tag.getidx(tag)
199 if tonumber(pos) <= -1 then
200 awful.tag.move(idx - 1, tag)
202 awful.tag.move(idx + 1, tag)
206 -- Delete current tag
207 -- Any rule set on the tag shall be broken
208 function util.delete_tag()
209 local t = awful.screen.focused().selected_tag
210 if not t then return end
215 -- On the fly useless gaps change
216 function util.useless_gaps_resize(thatmuch)
217 beautiful.useless_gap = tonumber(beautiful.useless_gap) + thatmuch
218 awful.layout.arrange(mouse.screen)
221 -- Check if an element exist on a table
222 function util.element_in_table(element, tbl)
223 for _, i in pairs(tbl) do
231 return setmetatable(util, { __index = wrequire })