Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Improved swallowing #140

Merged
merged 14 commits into from
Jan 4, 2022
Merged

Improved swallowing #140

merged 14 commits into from
Jan 4, 2022

Conversation

eylles
Copy link
Contributor

@eylles eylles commented Nov 9, 2021

This is an incremental improvement of the swallowing module, so far what has been done:

  • 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.
  • Rework the don't swallow filter and add table for clients that cannot swallow their parent.

What i still plan to do:

  • Rework the don't swallow filter and add table for clients that cannot swallow their parent. done
  • Add persistent properties so parent clients can be restored after awesome restarts can't decide on the better way to implement this so won't do it in this PR

altho i still have those plans the changes could be added to a later PR, also i have a prototype for removing iopopen altogether and instead use an async function but i'm still new to async functions specially in lua so that specific prototype may still have jank in it.

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.
@eylles eylles requested a review from Nooo37 as a code owner November 9, 2021 01:07
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).
@eylles eylles mentioned this pull request Nov 10, 2021
@eylles
Copy link
Contributor Author

eylles commented Nov 10, 2021

@Nooo37 any feedback before i edit the documentation ?

Copy link
Member

@Nooo37 Nooo37 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to work fine. Can you just explain why we need a cant_swallow_classname_list list? What happened to Yad without that list for you?

module/window_swallowing.lua Outdated Show resolved Hide resolved
@eylles
Copy link
Contributor Author

eylles commented Nov 14, 2021

ah perhaps yad was not the best program to put there, really the one i had problems was dragon but didn't put it in the list since there's no fixed class name for dragon as that is modified at compiletime and every distro i've seen sets a different name.

the addition of a secondary list for one adds flexibility but also takes care of some edge cases with programs like libreoffice that for some reason despite being added to the filter all their dialogs would swallow them (this was aggravated with the modification to the method to search the parent pid) but new windows with different documents would not.

also as mentioned on the commit message (altho not specified) we get more fine grained control as one list checks agaisnt the class of the current client and the other list checks against the class of the parent , so you can have clients that can't swallow their parent and parents that don't get swallowed (but they themselves can still swallow their parent).

Copy link

@Aire-One Aire-One left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about using the swallow module in my config. Since this is a new PR on this module, I thought I could take a look at it.

Feel free to dismiss any comment I made. They are mostly programming good practice and shouldn't alter the current implementation.

module/window_swallowing.lua Show resolved Hide resolved
end

-- checks if client classname can be swallowed
local function check_if_swallow(class)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function can be shortened to :

local function check_if_swallow(class)
    return not (activate_dont_swallow_filter or gears.table.hasitem(dont_swallow_classname_list, class))

(A quick note btw : as a good practice, you should only use positive name for boolean values, it makes this kind of check easier to read (maybe ignore_shallow or filter_shallow are better names))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i didn't change the original names but i'm awful at naming so having this feedback is invaluable, may go for filter_swallow

module/window_swallowing.lua Outdated Show resolved Hide resolved
@Aire-One
Copy link

also as mentioned on the commit message (altho not specified) we get more fine grained control as one list checks agaisnt the class of the current client and the other list checks against the class of the parent , so you can have clients that can't swallow their parent and parents that don't get swallowed (but they themselves can still swallow their parent).

I feel like cant_swallow_classname_list/dont_swallow_classname_list doesn't seem like describing this behavior. (and I wasn't sure of that either without the explanation)

Is it possible to change these names? Something like ignore_shallow_children for parents that don't shallow and ignore_shallow for client that demand to not be shallowed?

@eylles
Copy link
Contributor Author

eylles commented Nov 14, 2021

yeh i will change the names, i'm not the best at naming things so i just went with whatever name in hopes someone may come with something better

@eylles
Copy link
Contributor Author

eylles commented Nov 16, 2021

made the names more descriptive and proceeded to update the docs, i hope everything is readable and clear.
@Nooo37 please comment on anything else that should be changed.

@eylles eylles requested a review from Nooo37 November 16, 2021 18:03
Copy link

@Aire-One Aire-One left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As usual, feel free to dismiss my comments 😃

module/window_swallowing.lua Outdated Show resolved Hide resolved
Comment on lines 34 to 40
local function check_swallow(class, list)
if not swallowing_filter then
return true
else
return not is_in_table(class, list)
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit :

if X return true else return Y -> return X or Y

local function check_swallow(class, list)
    return (not swallowing_filter) or (not is_in_table(class, list))
end

Lua stops testing value as soon as it found a trusty value. It means that whenever (not swallowing_filter) is true, (not is_in_table(class, list)) will not be executed.

It can be tested with something like this :

function Y() print('hello') return true end 

-- X or Y
true or Y() -- true
false or Y() -- hello true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm trying to do this but can't get it to work

    if
        -- will search for "(parent_client.pid)" inside the parent_pid string
        ( tostring(parent_pid):find("("..tostring(parent_client.pid)..")") )
        and ( (not swallowing_filter)
        and ( (not is_in_table(parent_client.class, parent_filter_list))
        or (not is_in_table(c.class, child_filter_list)) ) )
    then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

making the logic of this has been a headache so i tought of this

swallow filter { if active check the lists }
parent check func { returns true if parent isn't in list }
child check func { returns true if child isn't in list }
swallow parent func { if true will swallow window }

x a b out
swallow filter parent check child check swallow parent
F F F T
F F T T
F T F T
F T T T
T F F F
T F T F
T T F F
T T T T

the case where the swallow filter is active and both the child and parent are in the lists should not even happen to begin with...

so to shorten this thing so far what i'm thinking is to have 1 function (or perhaps adding another if statement) that checks the var for the filter and if the filter is on then it bothers checking the classes against the corresponding list, so the function would recieve 2 inputs which will be the classes of the parent and children, at least that is the best idea i had.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

figured something out but is far from the elegance of a chain of pure and,or, not operators and parens.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the truth table. Yeah, you're probably right to make a separated function. It makes the code more readable.

@gokulswam gokulswam requested a review from Nooo37 December 2, 2021 20:05
@eylles
Copy link
Contributor Author

eylles commented Dec 9, 2021

i've been doing some testing and some programs like krita have their splash screens be a parent process of the program window, so i will have to add a check to always ignore splash parents.

@eylles
Copy link
Contributor Author

eylles commented Dec 17, 2021

shortened the logic of the checks for the classes to swallow and made the assignment of the swallowing filter more robust, will proceed into trying to make this async and dunno if trying to also tackle the problem of splash parents in this PR

this prevents krita and similar missbehaving programs from swallowing their
splash window.
@eylles
Copy link
Contributor Author

eylles commented Dec 17, 2021

okay all left is making this async...
ezgif-1-c726a2e4ac90

@eylles
Copy link
Contributor Author

eylles commented Dec 17, 2021

aaaaaaaaaaaaaaaand i'm done with this for the time being, next thing to implement would be persistance of the parent child relation of clients between restarts of awesomewm but i'm not doing that on this PR.

@eylles
Copy link
Contributor Author

eylles commented Dec 17, 2021

@Nooo37 @Aire-One

or { "firefox", "Gimp", "Google-chrome" }
local child_filter_list = beautiful.child_filter_list
or { }
or beautiful.dont_swallow_classname_list or { }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought I have reading this : There is a corner case where the user can require the module before calling beautiful.init. In this situation, the user defined lists in their theme will be ignored because these variables here are global to the module and initialized only here, at the module first load.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is a corner case with all of bling and the docs specify requiring bling after beautiful.init

https://blingcorp.github.io/bling/#/?id=installation

end
return res

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the function returns false when window_swallowing_activated is false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from what i can tell no, since window_swallowing_activated = false means that the swallowing function will be disconected from all clients.

105 local function start()
106     client.connect_signal("manage", manage_clientspawn)
107     window_swallowing_activated = true
108 end
109
110 local function stop()
111     client.disconnect_signal("manage", manage_clientspawn)
112     window_swallowing_activated = false
113 end
114
115 local function toggle()
116     if window_swallowing_activated then
117         stop()
118     else
119         start()
120     end
121 end

however if you meant the boolean value of swallowing_filter then reffering back to the truth table the output value of this function should only be false when the filter is active and either parent or child is in any of the filtering lists.

Copy link

@Aire-One Aire-One Dec 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. I have forgotten the use of this variable and thought it has what the user change to activate the module... My bad.

Comment on lines +59 to +60
elseif parent_client.type == "dialog" or parent_client.type == "splash" then
return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned earlier some programs with splash windows can have the splash window as parent process of the main window, and in the case of krita it's splash wrongfully has the dialog type, now if krita is the only program that has that bug i don't know, will have to keep checking the window type of programs with splash windows to be sure.

module/window_swallowing.lua Outdated Show resolved Hide resolved
this was probably an error handling/logging on the code i used as template for
the async function and it's callback.
if the parent is destroyed "on background" then awesome will show a warning.
Copy link

@Aire-One Aire-One left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been playing with this for a bit over a week now. I think it worked good!

Maybe the filter list can be improved, but that's a taste question and can be done by the user.

i don't see my additions as substantial enough to justify this but... ¯\_(ツ)_/¯
@eylles
Copy link
Contributor Author

eylles commented Jan 3, 2022

@Nooo37 feel free to squash the commits.

@Nooo37 Nooo37 merged commit 7542251 into BlingCorp:master Jan 4, 2022
@kodesoul
Copy link

kodesoul commented Jan 6, 2022

Hello ! this script is just what I was l looking for @eylles . Brilliant work ! Quick question, is there a reason why _client.turn_off() and _client.turn_on() don't set the c.hidden property instead ? Are there any issues with how awesome handles client properties ?

@Nooo37
Copy link
Member

Nooo37 commented Jan 8, 2022

@princebett When I wrote client.turn_on/off I didn't even consider that tbh. Might be worth to take a look on that, have you tried doing that? It's only a couple of lines to change. The scratchpad module uses the same helpers and got a issue due to that so that module might also profit from a change.

@eylles
Copy link
Contributor Author

eylles commented Jan 8, 2022

I have been working into other stuff but will take a look into the helpers, do some tests and maybe open the PR later today, i do not use bling's scratchpad module so no idea what the effect will be there.

@eylles
Copy link
Contributor Author

eylles commented Jan 10, 2022

@Nooo37 opened the PR to change the helpers, can you give it a look? #150

@kodesoul
Copy link

@princebett When I wrote client.turn_on/off I didn't even consider that tbh. Might be worth to take a look on that, have you tried doing that? It's only a couple of lines to change. The scratchpad module uses the same helpers and got a issue due to that so that module might also profit from a change.

I have been using it for the last few days and the behavior has not changed, so I guess it works fine.

@eylles
Copy link
Contributor Author

eylles commented Jan 10, 2022

@princebett can you give a test to #150 an report back there if there's any important behaviour change in any of the modules you use?

@kodesoul
Copy link

So far so good. I currently only use it for scratchpads and window swallowing and no problems so far. I'll report back in a few days.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants