Skip to content
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

Tiling rules should be able to target roles/subroles #152

Closed
axxag opened this issue Jul 23, 2019 · 15 comments
Closed

Tiling rules should be able to target roles/subroles #152

axxag opened this issue Jul 23, 2019 · 15 comments

Comments

@axxag
Copy link

axxag commented Jul 23, 2019

Use case-

I have a dual-monitor setup, with a tiling rule for Firefox like
yabai -m rule --add app="^Firefox$" display=1

If I need to move a Firefox window to display 2, any child windows with app: "Firefox" (like the right click dialog which has subrole: "AXUnknown") still adhere to the above rule and remain locked to display 1. You can easily reproduce this by:

  1. Add the above rule to .yabairc
  2. Open Firefox
  3. Move Firefox to screen 2
  4. Right click somewhere in Firefox and observe the dialog is still spawned on screen 1

This would be solvable if I could exclude subroles of "AXUnknown", or include only subroles of "AXStandardWindow" in the tiling rule. Being able to target roles/subroles would have other benefits as well, and would make the rules system more flexible overall.

@dominiklohmann
Copy link
Collaborator

@alexxgent As a workaround, you can always use signals for now. The window_created signal carries the newly created windows wid, which you can use as a selector for window queries. The downside to this is that signals are run asynchronously, which means that the window will be tiled on the space it spawns on before getting moved.

# /usr/bin/env sh

# save as some executable file (chmod +x /path/to/this/script)
# then plug into signal using:
#    yabai -m signal --add event=window_created action="/path/to/this/script"

# the window_created signal carries process id and window id as arguments
pid=$1
wid=$2

# check if window is a non-AXUnknown FireFox window
if yabai -m query --windows --window $wid \
    | jq -re '.app == "FireFox" and .subrole != "AXUnknown"'
then
    # send window to display 1
    yabai -m window $wid --display 1
fi

Generally speaking...

See #120 (comment) for a related discussion.

It's even worse with Chrome which always has an invisible subrole=AXUnknown window open for whatever reason and makes me question (again) whether subrole=AXUnknown should just be excluded by default for everything.

Obviously some applications will cause trouble here. Some Emacs distributions set role=AXTextField and subrole=AXUnknown for their main window.1

So what about a config setting that makes yabai consider non-standard roles/subroles for a given application? Some sort of whitelist should do.

1 From the tips and tricks section of the wiki:

Emacs is not a well-behaved citizen of macOS. Try using → emacs-mac from the Homebrew tap → emacsmacport and add the following line to your configuration file to get yabai to recognize Emacs.

(menu-bar-mode t)

@goranmoomin
Copy link

Some Emacs distributions set role=AXTextField and subrole=AXUnknown for their main window.

AFAIK, the main window of Emacs is role=AXTextField; subrole=AXStandardWindow while the popups are role=AXTextField; subrole=AXUnknown.
If this feature is implemented, it will help all Emacs users greatly.

@koekeishiya koekeishiya added the enhancement New feature or request label Jul 24, 2019
@axxag
Copy link
Author

axxag commented Jul 24, 2019

@dominiklohmann thanks for the workaround, it works like a charm (other than the async tiling as you mentioned). I think a white/blacklist would be ok as well, but would still be a bit less flexible than directly targeting rules to roles & subroles. Is there a reason we wouldn't want to go down that path? If not, I'll take a stab at a PR when I get some time.

@dominiklohmann
Copy link
Collaborator

Is there a reason we wouldn't want to go down that path

Yes. It unnecessarily complicates what's presented to the user and an easy-to-use command line interface is one of the key features of yabai.

Queries are already quite complicated when you need to filter for rules manually, because you cannot act on most of these windows anyways (and wouldn't want to). Almost all of the queries I write for multiple windows are passed through jq with the filter map(select(.subrole != "AXUnknown")) as a first step.

A good middle ground would maybe be to allow rules like you said, and if a role or subrole is given that yabai does not handle by default, it also shows the affected windows in query results and draws inactive borders on them (see #120). Then if a user wanted to restore the old behaviour, they could create a rule that matches all windows whose subrole=AXUnknown.

@axxag
Copy link
Author

axxag commented Jul 24, 2019

I don't agree that adding two more parameters to rules would make them unnecessarily complicated-
yabai -m rule --add app="^Firefox$" subrole="^AXStandardWindow$" display=1

The window role/subrole is clearly presented alongside the app name & title in the query interface, so it's intuitive that you'd be able to use these fields to target your rules as well.

{
	"id":18967,
	"pid":10296,
	"app":"Firefox",
	"title":"",
	"frame":{
		"x":10.0000,
		"y":50.0000,
		"w":1705.0000,
		"h":1380.0000
	},
	"level":0,
	"role":"AXWindow",
	"subrole":"AXStandardWindow",
	"movable":1,
	"resizable":1,
	"display":1,
	"space":1,
	"visible":1,
	"focused":0,
	"split":"none",
	"floating":0,
	"sticky":0,
	"border":0,
	"zoom-parent":0,
	"zoom-fullscreen":0,
	"native-fullscreen":0
}

On top of that, there will always be edge cases like emacs which every user may want to deal with differently, giving them access to role/subroles is a clean and straightforward way to do so.

Either way, I've got it working locally and created a PR - #155 .

@dominiklohmann
Copy link
Collaborator

I don't agree that adding two more parameters to rules would make them unnecessarily complicated

That's not what I mean. I think your approach is flawed because it's basically a blacklist for something that affects so few applications that a whitelist would be preferable, because less users would need to use them.

Rules should not act on windows whose subrole=AXUnknown at all—unless specified through whatever syntax. And that syntax could even be a rule. The same should apply to queries and inactive window borders.

Compare:

# blacklist approach -- need to filter by subrole for almost all rules

yabai -m rule --add app="^FireFox$" subrole="^(?!AXUnknown)$" display=1
yabai -m rule --add app="^Google Chrome$" subrole="^(?!AXUnknown)$" space=2

# whitelist approach -- simpler syntax for almost all rules

yabai -m rule --add app="^FireFox$" display=1
yabai -m rule --add app="^Google Chrome$" space=2
# the below rule has no effect but tells yabai to operate on matching windows
yabai -m rule --add app="^Emacs$" role="^AXTextField$" subrole="^AXStandardWindow$"

I'm not against role and subrole specifiers in rules—I just don't want them to be mandatory for writing correct rules.

@axxag
Copy link
Author

axxag commented Jul 24, 2019

Ah, okay, we're on the same page then. The PR I added uses the whitelist approach- you don't need to specify role/subrole for each rule, but you can optionally use them to pinpoint your target if desired.

@dominiklohmann
Copy link
Collaborator

It's not quite the same thing. Take a look at your original rule:

yabai -m rule --add app="^Firefox$" display=1

With your PR, this still does not work. That's why your PR requires blacklisting roles that you do not want to act on.

Instead, all weird roles and subroles like AXUnknown should be excluded by default from rules, signals, queries and inactive window borders, and only be whitelisted when a matching rule exists.

@axxag
Copy link
Author

axxag commented Jul 24, 2019

There are two separate issues at play:

  1. Rules should be able to target any role/subrole if desired
  2. Something needs to be done about the AXUnknown subroles

The PR I pushed tackles 1, which temporarily gives us an escape hatch for 2, but will also allow for further customization down the line.

2 will need to be dealt with separately, though I don't have enough understanding of how AXUnknown manifests to give an opinion on how.

@dominiklohmann
Copy link
Collaborator

  1. Rules should be able to target any role/subrole if desired
  2. Something needs to be done about the AXUnknown subroles

I think fixing 1 without fixing 2 is just a bandaid. It requires users to change their configuration to fix an issue that really should not exist at all. What do you do when 2 is fixed separately? Tell users to change their configuration back to how it was before 1 was fixed?

@axxag
Copy link
Author

axxag commented Jul 24, 2019

All of the solutions we currently have to prevent this behavior are bandaids, like the signal workaround you posted earlier. Once we completely fix 2, that sort of thing will need to be reverted anyway. So we can either:

  1. Suggest the signal workaround until someone pushes a PR for 2, then push 1 afterwards.
  2. Push 1 and provide an admittedly better (non-async) workaround with rules, then push 2 when it's ready

Personally I think 2 is a better option.

@koekeishiya koekeishiya removed the enhancement New feature or request label Jul 28, 2019
@koekeishiya
Copy link
Owner

I think ignoring all windows of subrole AXUnknown is the correct solution for now. I don't think the user should have to care about the AXRole, and I'd like to wait and see if there is a real need for this before actually implementing it. See #164

@ai212983
Copy link

ai212983 commented Aug 9, 2019

Hello guys. I'd still liked to have roles/subroles support.

There's another popover-like window roles besides AXPopover, like AXSheet. This case is not covered now, and it drives me bonkers, because confirmation dialogs in Path Finder are implemented with AXSheet. Right now they are jumping all over my screen.

I think current solution with ignoring some specific roles/subroles (AXPopover, AXUnknown, whatever) is very opinionated and inflexible.

upd: Possible workaround: #194

@dominiklohmann
Copy link
Collaborator

@ai212983 windows with a role of AXSheet that have a parent window are already floating. You can verify this by opening the file save/open or print sheet on any app.

I just downloaded a trial version of Path Finder for testing and it misbehaves in so many different ways, it might just be the application that takes Emacs place as the worst citizen of macOS. Accessibility Inspector tells you that Path Finder mislabels windows roles and subroles and spawns quite a few invisible windows. The proper action here is to just not let yabai manage Path Finder and to write rules based on titles, because there is no way to consistently get this to work using roles and subroles.

@ai212983
Copy link

ai212983 commented Aug 9, 2019

@dominiklohmann Yeah, it's quite messy :)
Actually workaround from #194 works fine. I think signals/events are providing enough flexibility. I guess rules are meant mostly for simple cases.

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

No branches or pull requests

5 participants