Improved swallowing (#140)
* Make swallowing more robust Changed the flags for the pstree command so it is a single line with all ancestors. Removed usage of sed, grep and tr so the iopopen call should be faster. Find and match of parent pid in the ancestors string is done in lua so should be faster. * Improved swallow filter Now you cna filter window swallowing with 2 tables, one for clients that cannot be swallowed (dont_swallow_classname_list) and one for clients that cannot swallow their parents (cant_swallow_classname_list). * remove occurences of res var * renamed functions and theme vars more descriptive * updated module documentation * check functions combined, is_in_table 1 return * add old theme vars for compatibility * short swallow logic and robust filter assignment * ignore splash and dialog parents this prevents krita and similar missbehaving programs from swallowing their splash window. * consistent docs formatting * convert module to use an async function * removed undefined error() function call this was probably an error handling/logging on the code i used as template for the async function and it's callback. * deal with corner case: parent exits before client if the parent is destroyed "on background" then awesome will show a warning. * added meself to authors i don't see my additions as substantial enough to justify this but... ¯\_(ツ)_/¯
This commit is contained in:
parent
e0423796b0
commit
7542251b72
|
@ -7,3 +7,4 @@ The following developers have contributed major code to bling:
|
|||
* [HumblePresent](https://github.com/HumblePresent)
|
||||
* [Kasper24](https://github.com/Kasper24)
|
||||
* [undefinedDarkness](https://github.com/undefinedDarkness)
|
||||
* [eylles](https://github.com/eylles)
|
||||
|
|
|
@ -13,8 +13,9 @@ bling.module.window_swallowing.toggle() -- toggles window swallowing
|
|||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.dont_swallow_classname_list = {"firefox", "Gimp"} -- list of class names that should not be swallowed
|
||||
theme.dont_swallow_filter_activated = true -- whether the filter above should be active
|
||||
theme.parent_filter_list = {"firefox", "Gimp"} -- class names list of parents that should not be swallowed
|
||||
theme.child_filter_list = { "Dragon" } -- class names list that should not swallow their parents
|
||||
theme.swallowing_filter = true -- whether the filters above should be active
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
|
|
@ -11,53 +11,93 @@ local helpers = require(tostring(...):match(".*bling") .. ".helpers")
|
|||
local window_swallowing_activated = false
|
||||
|
||||
-- you might want to add or remove applications here
|
||||
local dont_swallow_classname_list = beautiful.dont_swallow_classname_list
|
||||
local parent_filter_list = beautiful.parent_filter_list
|
||||
or beautiful.dont_swallow_classname_list
|
||||
or { "firefox", "Gimp", "Google-chrome" }
|
||||
local activate_dont_swallow_filter = beautiful.dont_swallow_filter_activated
|
||||
or true
|
||||
local child_filter_list = beautiful.child_filter_list
|
||||
or beautiful.dont_swallow_classname_list or { }
|
||||
|
||||
-- checks if client classname matches with any entry of the dont-swallow-list
|
||||
local function check_if_swallow(c)
|
||||
if not activate_dont_swallow_filter then
|
||||
return true
|
||||
end
|
||||
for _, classname in ipairs(dont_swallow_classname_list) do
|
||||
if classname == c.class then
|
||||
return false
|
||||
-- for boolean values the or chain way to set the values breaks with 2 vars
|
||||
-- and always defaults to true so i had to do this to se the right value...
|
||||
local swallowing_filter = true
|
||||
local filter_vars = { beautiful.swallowing_filter, beautiful.dont_swallow_filter_activated }
|
||||
for _, var in pairs(filter_vars) do
|
||||
swallowing_filter = var
|
||||
end
|
||||
|
||||
-- check if element exist in table
|
||||
-- returns true if it is
|
||||
local function is_in_table(element, table)
|
||||
local res = false
|
||||
for _, value in pairs(table) do
|
||||
if element:match(value) then
|
||||
res = true
|
||||
break
|
||||
end
|
||||
end
|
||||
return true
|
||||
return res
|
||||
end
|
||||
|
||||
-- if the swallowing filter is active checks the child and parent classes
|
||||
-- against their filters
|
||||
local function check_swallow(parent, child)
|
||||
local res = true
|
||||
if swallowing_filter then
|
||||
local prnt = not is_in_table(parent, parent_filter_list)
|
||||
local chld = not is_in_table(child, child_filter_list)
|
||||
res = ( prnt and chld )
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- async function to get the parent's pid
|
||||
-- recieves a child process pid and a callback function
|
||||
-- parent_pid in format "init(1)---ancestorA(pidA)---ancestorB(pidB)...---process(pid)"
|
||||
function get_parent_pid(child_ppid, callback)
|
||||
local ppid_cmd = string.format("pstree -A -p -s %s", child_ppid)
|
||||
awful.spawn.easy_async(ppid_cmd, function(stdout, stderr, reason, exit_code)
|
||||
-- primitive error checking
|
||||
if stderr and stderr ~= "" then
|
||||
callback(stderr)
|
||||
return
|
||||
end
|
||||
local ppid = stdout
|
||||
callback(nil, ppid)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
-- the function that will be connected to / disconnected from the spawn client signal
|
||||
local function manage_clientspawn(c)
|
||||
-- get the last focused window to check if it is a parent window
|
||||
local parent_client = awful.client.focus.history.get(c.screen, 1)
|
||||
if not parent_client then
|
||||
return
|
||||
elseif parent_client.type == "dialog" or parent_client.type == "splash" then
|
||||
return
|
||||
end
|
||||
|
||||
-- io.popen is normally discouraged. Should probably be changed
|
||||
local handle = io.popen(
|
||||
[[pstree -T -p -a -s ]]
|
||||
.. tostring(c.pid)
|
||||
.. [[ | sed '2q;d' | grep -o '[0-9]*$' | tr -d '\n']]
|
||||
)
|
||||
local parent_pid = handle:read("*a")
|
||||
handle:close()
|
||||
|
||||
get_parent_pid(c.pid, function(err, ppid)
|
||||
if err then
|
||||
return
|
||||
end
|
||||
parent_pid = ppid
|
||||
if
|
||||
(tostring(parent_pid) == tostring(parent_client.pid))
|
||||
and check_if_swallow(c)
|
||||
-- will search for "(parent_client.pid)" inside the parent_pid string
|
||||
( tostring(parent_pid):find("("..tostring(parent_client.pid)..")") )
|
||||
and check_swallow(parent_client.class, c.class)
|
||||
then
|
||||
c:connect_signal("unmanage", function()
|
||||
helpers.client.turn_on(parent_client)
|
||||
helpers.client.sync(parent_client, c)
|
||||
if parent_client then
|
||||
helpers.client.turn_on(parent_client)
|
||||
helpers.client.sync(parent_client, c)
|
||||
end
|
||||
end)
|
||||
|
||||
helpers.client.sync(c, parent_client)
|
||||
helpers.client.turn_off(parent_client)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- without the following functions that module would be autoloaded by require("bling")
|
||||
|
|
Loading…
Reference in New Issue