diff --git a/AUTHORS.md b/AUTHORS.md index d9c6d2d..471cad5 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -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) diff --git a/docs/module/swal.md b/docs/module/swal.md index ae339fc..0b3fed6 100644 --- a/docs/module/swal.md +++ b/docs/module/swal.md @@ -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 diff --git a/module/window_swallowing.lua b/module/window_swallowing.lua index 368541b..60950aa 100644 --- a/module/window_swallowing.lua +++ b/module/window_swallowing.lua @@ -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")