]> 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 pull request #3 from janx/master
[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
42     then
43         return nil
44     end
45
46     -- For each selected tag get all clients of that tag and add them to
47     -- the menu. A click on a menu item will raise that client.
48     for i = 1,#cls_tags
49     do
50         local t = cls_tags[i]
51         local cls = t:clients()
52
53         for k, c in pairs(cls)
54         do
55             cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "",
56                                   function ()
57                                       c.minimized = false
58                                       client.focus = c
59                                       c:raise()
60                                   end,
61                                   c.icon }
62         end
63     end
64
65     -- No clients? Then quit.
66     if #cls_t <= 0
67     then
68         return nil
69     end
70
71     -- menu may contain some predefined values, otherwise start with a
72     -- fresh menu.
73     if not menu
74     then
75         menu = {}
76     end
77
78     -- Set the list of items and show the menu.
79     menu.items = cls_t
80     local m = awful.menu.new(menu)
81     m:show(args)
82     return m
83 end
84
85 -- Magnify a client: Set it to "float" and resize it.
86 function util.magnify_client(c)
87     if not awful.client.floating.get(c) then
88         awful.client.floating.set(c, true)
89
90         local mg = screen[mouse.screen].geometry
91         local tag = awful.tag.selected(mouse.screen)
92         local mwfact = awful.tag.getmwfact(tag)
93         local g = {}
94         g.width = math.sqrt(mwfact) * mg.width
95         g.height = math.sqrt(mwfact) * mg.height
96         g.x = mg.x + (mg.width - g.width) / 2
97         g.y = mg.y + (mg.height - g.height) / 2
98         c:geometry(g)
99     else
100         awful.client.floating.set(c, false)
101     end
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 n == nil
108     then
109         -- This should not happen. But I don't want to crash, either.
110         return 0
111     end
112
113     -- Remove pid and tcomm. This is necessary because tcomm may contain
114     -- nasty stuff such as whitespace or additional parentheses...
115     n = string.gsub(n, '.*%) ', '')
116
117     -- Field number 17 now is the nice value.
118     fields = split(n, ' ')
119     return tonumber(fields[17])
120 end
121
122 -- To be used as a signal handler for "focus"
123 -- This requires beautiful.border_focus{,_highprio,_lowprio}.
124 function util.niceborder_focus(c)
125     local n = get_nice_value(c.pid)
126     if n == 0
127     then
128         c.border_color = beautiful.border_focus
129     elseif n < 0
130     then
131         c.border_color = beautiful.border_focus_highprio
132     else
133         c.border_color = beautiful.border_focus_lowprio
134     end
135 end
136
137 -- To be used as a signal handler for "unfocus"
138 -- This requires beautiful.border_normal{,_highprio,_lowprio}.
139 function util.niceborder_unfocus(c)
140     local n = get_nice_value(c.pid)
141     if n == 0
142     then
143         c.border_color = beautiful.border_normal
144     elseif n < 0
145     then
146         c.border_color = beautiful.border_normal_highprio
147     else
148         c.border_color = beautiful.border_normal_lowprio
149     end
150 end
151
152 -- Non-empty tag browsing
153 -- direction in {-1, 1} <-> {previous, next} non-empty tag
154 function util.tag_view_nonempty(direction, sc)
155    local s = sc or mouse.screen or 1
156    local scr = screen[s]
157
158    for i = 1, #tags[s] do
159        awful.tag.viewidx(direction,s)
160        if #awful.client.visible(s) > 0 then
161            return
162        end
163    end
164 end
165
166 -- {{{ Dynamic tagging
167 --
168 -- Add a new tag
169 function util.add_tag(mypromptbox)
170     awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget,
171     function(text)
172         if text:len() > 0 then
173             props = { selected = true }
174             tag = awful.tag.add(new_name, props)
175             tag.name = text
176             tag:emit_signal("property::name")
177         end
178     end)
179 end
180
181 -- Rename current tag
182 -- @author: minism
183 function util.rename_tag(mypromptbox)
184     local tag = awful.tag.selected(mouse.screen)
185     awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget,
186     function(text)
187         if text:len() > 0 then
188             tag.name = text
189             tag:emit_signal("property::name")
190         end
191     end)
192 end
193
194 -- Delete current tag (if empty)
195 -- Any rule set on the tag shall be broken
196 function util.remove_tag()
197     local tag = awful.tag.selected(mouse.screen)
198     local prevtag = awful.tag.gettags(mouse.screen)[awful.tag.getidx(tag) - 1]
199     awful.tag.delete(tag, prevtag)
200 end
201 --
202 -- }}}
203
204 -- On the fly useless gaps change
205 function util.useless_gaps_resize(thatmuch)
206     beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch
207     awful.layout.arrange(mouse.screen)
208 end
209
210 return setmetatable(util, { __index = wrequire })