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

a7b53d27b54c6c93f5819185be969512beb1c61f
[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.screen.focused().selected_tags
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
93     c.floating   = true
94     local s      = awful.screen.selected()
95     local mg     = s.geometry
96     local tag    = s.selected_tag
97     local mwfact = beautiful.master_width_factor or 0.5
98     local g      = {}
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
103
104     if c then c:geometry(g) end -- if c is still a valid object
105 end
106
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
111
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, '.*%) ', '')
115
116     -- Field number 17 now is the nice value.
117     fields = split(n, ' ')
118     return tonumber(fields[17])
119 end
120
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)
125     if n == 0
126     then
127         c.border_color = beautiful.border_focus
128     elseif n < 0
129     then
130         c.border_color = beautiful.border_focus_highprio
131     else
132         c.border_color = beautiful.border_focus_lowprio
133     end
134 end
135
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)
140     if n == 0
141     then
142         c.border_color = beautiful.border_normal
143     elseif n < 0
144     then
145         c.border_color = beautiful.border_normal_highprio
146     else
147         c.border_color = beautiful.border_normal_lowprio
148     end
149 end
150
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]
156
157    for i = 1, #s.tags do
158        awful.tag.viewidx(direction, s)
159        if #s.clients > 0 then
160            return
161        end
162    end
163 end
164
165 -- {{{ Dynamic tagging
166 --
167 -- Add a new tag
168 function util.add_tag()
169     awful.prompt.run {
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()
175         end
176     }
177 end
178
179 -- Rename current tag
180 function util.rename_tag()
181     awful.prompt.run {
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
187             if t then
188                 t.name = new_name
189             end
190         end
191     }
192 end
193
194 -- Move current 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)
201     else
202         awful.tag.move(idx + 1, tag)
203     end
204 end
205
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
211     t:delete()
212 end
213 -- }}}
214
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)
219 end
220
221 -- Check if an element exist on a table
222 function util.element_in_table(element, tbl)
223     for _, i in pairs(tbl) do
224         if i == element then
225             return true
226         end
227     end
228     return false
229 end
230
231 return setmetatable(util, { __index = wrequire })