-
Notifications
You must be signed in to change notification settings - Fork 598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rule source dependencies are not honored #2725
Comments
I took a quick look: Lines 301 to 308 in 0642d92
add_rule_source reverses the result of the topological sort. It repeatedly prepends (notice the argument 1 ) the next item to the list of rule sources. Thus, the effect of depends_on and precede are exactly reversed, I guess..?(What does this mean for the AwesomeWM-internal calls to add_rule_source ? Are the dependencies the wrong way around in here, too?)
|
Wait a second. I think everything is working as intended. Rule sources are not meant to actually apply anything, but to only collect the things that should be done. For example, the rule source for Lines 330 to 338 in 0642d92
Thus, code that runs later overwrites settings done by earlier rule sources. Thus, the later a rule source runs, the higher is its priority. @jcrd Does this make sense to you? @Elv13 My only question now is: Should the order of callbacks be reversed as well? So that callbacks which are appended to the Code: awful.rules.add_rule_source("source1", function (c, props, callback) table.insert(callback, function() print("in cb of source1") end) end)
awful.rules.add_rule_source("source2", function (c, props, callback) table.insert(callback, function() print("in cb of source2") end) end, {"source1"}) Output when a new client appears:
Expected output: I'm not sure. Is it the other way around or should rule source callbacks insert at the beginning? (which would lead to worse runtime due to having to shift all other callbacks back by one position; do we care?) |
This makes sense, but |
It is confusing though (apart from the callback order). As rules.lua states that --- The rule source for clients spawned by `awful.spawn.once` and `single_instance`.
--
-- **Has priority over:**
--
-- * `awful.rules`
--
-- **Depends on:**
--
-- * `awful.spawn`
--
-- @rulesources awful.spawn_once
rules.add_rule_source("awful.spawn_once", apply_singleton_rules, {"awful.spawn"}, {"awful.rules"}) but shouldn't that be rules.add_rule_source("awful.rules", apply_awful_rules, {"awful.spawn"}, {})
rules.add_rule_source("awful.spawn", apply_spawn_rules, {}, {"awful.rules"})
rules.add_rule_source("awful.spawn_once", apply_singleton_rules, {"awful.spawn"}, {"awful.rules"}) As awful.rules is overriding the spawn and spawn_once rules now (if |
I think the meaning of the terms is actually reversed, because the awful.spawn rules do run after awful.rules as they should. And when I reversed the arguments for my custom rule sources, the rules and callbacks started running in the right order. This explains why they never worked right. |
Based on this description of Lines 213 to 218 in 0642d92
Making awful.rules.add_rule_source("source1", function () print("source1") end)
awful.rules.add_rule_source("source2", function () print("source2") end, {"source1"})
awful.rules.add_rule_source("source3", function () print("source3") end, nil, {"source2"})
awful.rules.add_rule_source("source4", function () print("source4") end, {"source3"}) produces:
|
@jcrd Maybe you already know and I'm misunderstanding you, but just to clarify #2725 (comment): those functions given to Having the argument in After adding this to a default config and running in Xephyr awful.rules.add_rule_source("source1", function(c, props, callback)
print("applying source1")
gears.table.crush(props, { tag = "1" })
table.insert(callback, function() print("in cb of source1") end)
end)
awful.rules.add_rule_source("source3", function(c, props, callback)
print("applying source3")
gears.table.crush(props, { tag = "3" })
table.insert(callback, function() print("in cb of source3") end)
end, nil, {"source1"})
awful.rules.add_rule_source("source2", function(c, props, callback)
print("applying source2")
gears.table.crush(props, { tag = "2" })
table.insert(callback, function() print("in cb of source2") end)
end, {"source3"}, {"source1"})
awful.spawn(terminal) the output is
and the terminal ends up on tag 3. This seems to be the desired behavior, so I think the terms really are reversed. And maybe they should just be renamed |
Also, shouldn't it be easier to just add a table of rules as a rule source? As it stands now one has to copy the local function |
Testing the startup notifications rules awful.rules.rules = {
{ rule = { },
properties = { ...
tag = "4",
}
callback = function() print("in cb of awful.rules *") end,
... awful.rules.add_rule_source("source1", function(c, props, callback)
print("applying source1")
gears.table.crush(props, { tag = "1" })
table.insert(callback, function() print("in cb of source1") end)
end, nil, {"awful.rules"})
awful.rules.add_rule_source("source3", function(c, props, callback)
print("applying source3")
gears.table.crush(props, { tag = "3" })
table.insert(callback, function() print("in cb of source3") end)
end, {"awful.spawn"}, {"source1"})
awful.rules.add_rule_source("source2", function(c, props, callback)
print("applying source2")
gears.table.crush(props, { tag = "2" })
table.insert(callback, function() print("in cb of source2") end)
end, {"source3"}, {"source1"})
awful.spawn("arandr",
{ tag = "5" },
function() print("in cb of spawn") end
) shows that they work. Btw, would it be a good idea if the order arguments of Lines 260 to 262 in 0642d92
default to {"awful.spawn"} and {"awful.rules"} respectively so a rule source defined without them automatically get's put in between them? Which would probably be desirable for most users.
|
@warptozero Thanks for clarifying Still, the rule source callbacks themselves (given to |
Yes exactly, and that's why the meaning of |
As @psychon mentionned, the order is intentional. tl;dr, as already mentionned, the rules are applied only once after all rules sources are "consulted". This is also on purpose to avoid the case where extra code is called if a property is set multiple time. For example, changing the geometry will call a lot of code (the tiled layout, Plus, the property application order is itself very important. For example, setting the geometry before of after the titlebars have been added don't produce the same result. Same for the position and Because of those 2 fact, the rule sources are designed to modify a property table that is then applied. This means they have the "right" to overwrite what the other sources added to the table. So, because of that, the last one to be executed has the final say in what is and isn't in the property table. Because of that the execution order is from "fallback values" to "this has to be the absolute value". Anyhow, this pull request #2600 has more documentation about the rules. Some comments in @warptozero / @jcrd : May I ask how you (plan to?) use this API? I am very interested in these use cases since "soon" this API will also be available for the notifications and clipboard selection. It was originally mainly added to fix
I need to review this when I really have time, no in a drive-by comment. I was supposed to be "in vacation" since my last contract ended, but the word spread and now I am more booked than ever... I managed to get the notification view PR in "some commits still have luacheck problem but otherwise its done" state, but I doesn't look like I will have more time in the next few weeks. |
@Elv13 Thanks for the explanation even though you don't have a lot of time. I understand what you are saying, but I still think the terms have a reversed effect and meaning just by looking at the way Line 260 in 0642d92
rules.add_rule_source("awful.rules", apply_awful_rules, {"awful.spawn"}, {})
rules.add_rule_source("awful.spawn", apply_spawn_rules, {}, {"awful.rules"})
rules.add_rule_source("awful.spawn_once", apply_singleton_rules, {"awful.spawn"}, {"awful.rules"}) awful.rules.add_rule_source(
"tyrannical", apply_tyrannical_rules, {"snid", "awful.spawn"}, {"awful.rules"}
) But I might be wrong, so someone should try to falsify this #2725 (comment). (Btw, I edited out a mistake I made as not to confuse things further.)
Well I wrote a settings module that saves the state of it's properties to disk (serialized to a lua table) so for example widgets can change settings and they will be reserved on restart. Or the last selected tag, etc. It's also gears.object with signals and works really well. Naturally I also used it to store things like screen layout and tags with properties and client rules. These rules are then compiled to a rule table and were appended to awful.rules.rules (which worked but I thought there's an API so that's probably the right way to do it). So this part has actually grown out to be something like Tyrannical, which I didn't choose back then because it was way more then I needed. So I guess these are the same kind of problems you were trying to solve with that API. And I thought it would also make it easier to set priorities on individual rules and screens (by having differenent sources for each priority/screen), and make it easy to change the rules when a screen is added or removed. Somewhat tangential, but I think the biggest issue I have with awesome is that I always keep running into big or subtle problems with screens and rules (on what tag/screen clients are launched, especially after a screen is added/removed). This is probably because I'm hacking things that I don't understand completely, but these rule anomalies that I can't seem to track down are my main point of frustration with awesome. |
@Elv13 I'm using the API to implement generic single instance IDs in a custom |
Ah nice! This has been in my TODO list for years. Can you share this so I can use it in Tyrannical? AwesomeWM 4.3 have an half assed attempt done by reading /proc, but it has always been my intention to provide some LD_PRELOAD one too. |
I also think the name of the properties should be reversed. Another example from the docs is the workaround for startup ids which is not working as intended. It does set the startup_id but only after applying the rules so any rule using As the workaround in itself is tricky here is the minimal code to reproduce this. This sets the property but you have to reapply the rules to the client ( awful.rules.add_rule_source(
"snid", function(c) c.custom_property = "custom_property" end, {}, {"awful.spawn", "awful.rules"}
)
-- On awful.rules.rules
{ rule = { class = "CLIENT_CLASS", custom_property = "custom_property" },
properties = { floating = true }
}, function rules.add_rule_source(name, callback, depends_on, precede) Like this you would expect that the "snid", function(c) c.custom_property = "custom_property" end, {"awful.spawn", "awful.rules"}, {} |
Output of
awesome --version
:How to reproduce the issue:
Actual result:
"source2" is printed before "source1".
Expected result:
source2 should be run after its dependency, source1.
The text was updated successfully, but these errors were encountered: