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

Updated calendar (markdown)
[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 function util.magnify_client(c)
78     if not awful.client.floating.get(c) then
79         awful.client.floating.set(c, true)
80
81         local mg = screen[mouse.screen].geometry
82         local tag = awful.tag.selected(mouse.screen)
83         local mwfact = awful.tag.getmwfact(tag)
84         local g = {}
85         g.width = math.sqrt(mwfact) * mg.width
86         g.height = math.sqrt(mwfact) * mg.height
87         g.x = mg.x + (mg.width - g.width) / 2
88         g.y = mg.y + (mg.height - g.height) / 2
89         c:geometry(g)
90     else
91         awful.client.floating.set(c, false)
92     end
93 end
94
95 -- Read the nice value of pid from /proc.
96 local function get_nice_value(pid)
97     local n = first_line('/proc/' .. pid .. '/stat')
98     if n == nil
99     then
100         -- This should not happen. But I don't want to crash, either.
101         return 0
102     end
103
104     -- Remove pid and tcomm. This is necessary because tcomm may contain
105     -- nasty stuff such as whitespace or additional parentheses...
106     n = string.gsub(n, '.*%) ', '')
107
108     -- Field number 17 now is the nice value.
109     fields = split(n, ' ')
110     return tonumber(fields[17])
111 end
112
113 -- To be used as a signal handler for "focus"
114 -- This requires beautiful.border_focus{,_highprio,_lowprio}.
115 function util.niceborder_focus(c)
116     local n = get_nice_value(c.pid)
117     if n == 0
118     then
119         c.border_color = beautiful.border_focus
120     elseif n < 0
121     then
122         c.border_color = beautiful.border_focus_highprio
123     else
124         c.border_color = beautiful.border_focus_lowprio
125     end
126 end
127
128 -- To be used as a signal handler for "unfocus"
129 -- This requires beautiful.border_normal{,_highprio,_lowprio}.
130 function util.niceborder_unfocus(c)
131     local n = get_nice_value(c.pid)
132     if n == 0
133     then
134         c.border_color = beautiful.border_normal
135     elseif n < 0
136     then
137         c.border_color = beautiful.border_normal_highprio
138     else
139         c.border_color = beautiful.border_normal_lowprio
140     end
141 end
142
143 -- Non-empty tag browsing
144 -- direction in {-1, 1} <-> {previous, next} non-empty tag
145 function util.tag_view_nonempty(direction, sc)
146    local s = sc or mouse.screen or 1
147    local scr = screen[s]
148
149    for i = 1, #tags[s] do
150        awful.tag.viewidx(direction,s)
151        if #awful.client.visible(s) > 0 then
152            return
153        end
154    end
155 end
156
157 -- {{{ Dynamic tagging
158 --
159 -- Add a new tag
160 function util.add_tag(mypromptbox)
161     awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget,
162     function(text)
163         if text:len() > 0 then
164             props = { selected = true }
165             tag = awful.tag.add(new_name, props)
166             tag.name = text
167             tag:emit_signal("property::name")
168         end
169     end)
170 end
171
172 -- Rename current tag
173 -- @author: minism
174 function util.rename_tag(mypromptbox)
175     local tag = awful.tag.selected(mouse.screen)
176     awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget,
177     function(text)
178         if text:len() > 0 then
179             tag.name = text
180             tag:emit_signal("property::name")
181         end
182     end)
183 end
184
185 -- Move current tag
186 -- pos in {-1, 1} <-> {previous, next} tag position
187 function util.move_tag(pos)
188     local tag = awful.tag.selected(mouse.screen)
189     local idx = awful.tag.getidx(tag)
190     if tonumber(pos) <= -1 then
191         awful.tag.move(idx - 1, tag)
192     else
193         awful.tag.move(idx + 1, tag)
194     end
195 end
196
197 -- Remove current tag (if empty)
198 -- Any rule set on the tag shall be broken
199 function util.remove_tag()
200     local tag = awful.tag.selected(mouse.screen)
201     local prevtag = awful.tag.gettags(mouse.screen)[awful.tag.getidx(tag) - 1]
202     awful.tag.delete(tag, prevtag)
203 end
204 --
205 -- }}}
206
207 -- On the fly useless gaps change
208 function util.useless_gaps_resize(thatmuch)
209     beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch
210     awful.layout.arrange(mouse.screen)
211 end
212
213 return setmetatable(util, { __index = wrequire })