]> 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:

9a6d18275ca18e9dd2d6892f5de6dcd83e1e42e4
[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     if c then c:geometry(g) end -- if c is still a valid object
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()
166     awful.prompt.run {
167         prompt       = "New tag name: ",
168         textbox      = awful.screen.focused().mypromptbox.widget,
169         exe_callback = function(name)
170             if not name or #name == 0 then return end
171             awful.tag.add(name, { screen = awful.screen.focused() }):view_only()
172         end
173     }
174 end
175
176 -- Rename current tag
177 function util.rename_tag()
178     awful.prompt.run {
179         prompt       = "Rename tag: ",
180         textbox      = awful.screen.focused().mypromptbox.widget,
181         exe_callback = function(new_name)
182             if not new_name or #new_name == 0 then return end
183             local t = awful.screen.focused().selected_tag
184             if t then
185                 t.name = new_name
186             end
187         end
188     }
189 end
190
191 -- Move current tag
192 -- pos in {-1, 1} <-> {previous, next} tag position
193 function util.move_tag(pos)
194     local tag = awful.tag.selected(mouse.screen)
195     local idx = awful.tag.getidx(tag)
196     if tonumber(pos) <= -1 then
197         awful.tag.move(idx - 1, tag)
198     else
199         awful.tag.move(idx + 1, tag)
200     end
201 end
202
203 -- Delete current tag
204 -- Any rule set on the tag shall be broken
205 function util.delete_tag()
206     local t = awful.screen.focused().selected_tag
207     if not t then return end
208     t:delete()
209 end
210 -- }}}
211
212 -- On the fly useless gaps change
213 function util.useless_gaps_resize(thatmuch)
214     beautiful.useless_gap = tonumber(beautiful.useless_gap) + thatmuch
215     awful.layout.arrange(mouse.screen)
216 end
217
218 -- Check if an element exist on a table
219 function util.element_in_table(element, tbl)
220     for _, i in pairs(tbl) do
221         if i == element then
222             return true
223         end
224     end
225     return false
226 end
227
228 return setmetatable(util, { __index = wrequire })