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

Constant number of spaces, organized evenly across displays #365

Closed
aiguofer opened this issue Jan 8, 2020 · 8 comments
Closed

Constant number of spaces, organized evenly across displays #365

aiguofer opened this issue Jan 8, 2020 · 8 comments
Labels
question Request for information or help, not an issue

Comments

@aiguofer
Copy link

aiguofer commented Jan 8, 2020

Hey! first off, I want to thank you for all your work on this! Now that I have to use a Mac, your project has enabled me to at least come a bit closer to my Linux i3 setup.

One thing I'm stuck on is, I want to have 10 spaces, spread evenly among displays. For example, if use : to show expected setup:

1 display:
1:1, 2:1, 3:1 ...

2 displays:
1:1, 2:2, 3:1, 4:2 ...

3 displays:
1:1, 2:2, 3:3, 4:1 ...

I tried the following in my yabairc:

num_displays=$(yabai -m query --displays | jq '. | length')
for i in {1..10}; do
    echo "Moving space $i to display $(( $num_displays - $i % $num_displays ))"
    yabai -m space $i --display $(( $num_displays - $i % $num_displays ))
done

The echos seem to suggest it did the right thing:

$ yabai
....
Moving space 1 to display 1
acting space is already located on the given display.
Moving space 2 to display 2
Moving space 3 to display 1
acting space is already located on the given display.
Moving space 4 to display 2
Moving space 5 to display 1
Moving space 6 to display 2
acting space is already located on the given display.
Moving space 7 to display 1
Moving space 8 to display 2
acting space is already located on the given display.
Moving space 9 to display 1
Moving space 10 to display 2
acting space is already located on the given display.
yabai configuration loaded..

but the spaces don't seem to be correctly organized:

$ yabai -m query --spaces | jq '.[] | {index, display}'
{
  "index": 1,
  "display": 1
}
{
  "index": 2,
  "display": 1
}
{
  "index": 3,
  "display": 1
}
{
  "index": 4,
  "display": 1
}
{
  "index": 5,
  "display": 1
}
{
  "index": 6,
  "display": 1
}
{
  "index": 7,
  "display": 2
}
{
  "index": 8,
  "display": 2
}
{
  "index": 9,
  "display": 2
}
{
  "index": 10,
  "display": 2
}
@aiguofer
Copy link
Author

aiguofer commented Jan 8, 2020

Btw, the idea after I get this working is to put the "redistributing" code into a function and call that on a rule when the number of displays changes... but one step at a time.

@aiguofer
Copy link
Author

aiguofer commented Jan 8, 2020

After playing around with assigning labels, I see that the "right" thing is happening, and the issue is that the space indices are changing when spaces move.

Maybe I don't fully understand how Mac treats indices

@aiguofer
Copy link
Author

aiguofer commented Jan 8, 2020

After finding this SO answer and playing around a bit I think I figured it out. It looks like Mac will always assign spaces 1,2,3,4,5 to display 1 and 6,7,8,9,10 to display 2.

To work around this, I assigned labels "s{space_number}" to each space:

for i in {1..10}; do yabai -m space $i --label "s$i"; done

Then my keybindings to switch spaces look like this:

cmd - 1 : num_displays=$(yabai -m query --displays | jq '. | length') && \
space_display=$(( $num_displays - 1 % $num_displays )) && \
yabai -m space "s1" --display $space_display; yabai -m space --focus "s1"


cmd - 2 : num_displays=$(yabai -m query --displays | jq '. | length') && \
space_display=$(( $num_displays - 2 % $num_displays )) && \
yabai -m space "s2" --display $space_display; yabai -m space --focus "s2"
...

Do you see another possibly better way to do this?
Or can I create a function for that nasty mess to at least make my config cleaner? If so, where would I define the function to make sure skhd knows about it?

@dominiklohmann
Copy link
Collaborator

Some notes:

the issue is that the space indices are changing when spaces move.

These are just the indices as defined by Mission Control: contiguous across displays (in order), and starting at index 1.

There is no signal that notifies you when yabai notices that a space has been moved, created, or destroyed through any means that is not yabai itself, which makes it hard to automate this reliably.

Note that you always need to have at least one space per display with a desktop on it. Move and destroy operations on the last space with a desktop on a display fail with a non-zero exit-code, which you can check to make your script more robust.

Or can I create a function for that nasty mess to at least make my config cleaner? If so, where would I define the function to make sure skhd knows about it?

skhd runs through your non-interactive and non-login $SHELL. See the below image for what file to put such a function into (e.g., for zsh it's ~/.zshenv):

As an optimization, put it in yet another file and source that only when skhd is the parent process.

shell-startup-actual

Do you see another possibly better way to do this?

Yes, a rough idea for distributing the spaces evenly. I've bookmarked this and will get back to you when I've got time to figure that out completely.

@dominiklohmann dominiklohmann added the question Request for information or help, not an issue label Jan 8, 2020
@aiguofer
Copy link
Author

aiguofer commented Jan 8, 2020

Thanks for the thorough response!

These are just the indices as defined by Mission Control: contiguous across displays (in order), and starting at index 1.

There is no signal that notifies you when yabai notices that a space has been moved, created, or destroyed through any means that is not yabai itself, which makes it hard to automate this reliably.

Great, that makes sense. I think I can have something in the yabairc file that creates the spaces with labels, then destroys all spaces without labels, this should ensure that all existing spaces are created by yabai... That being said, it might not be necessary since I don't really use any spaces signals. As long as yabai can still move the spaces I should be good.

As an optimization, put it in yet another file and source that only when skhd is the parent process.

How would I go about doing that? I've been looking for how to source files from within skhd and can't find anything... I suppose I could do it in each command, but that still leads to a pretty ugly config file.

Yes, a rough idea for distributing the spaces evenly. I've bookmarked this and will get back to you when I've got time to figure that out completely.

Awesome, looking forward to it!

@aiguofer
Copy link
Author

aiguofer commented Jan 9, 2020

Well, I got to test the above today with 3 monitors.... and it failed miserably.

On every yabai restart it seemed to change which one is display 1, 2, and 3, making it difficult to be deterministic (maybe I could use labels there too, but not sure how). It also seemed to randomly crash, and couldn't quite pinpoint why.

@dominiklohmann
Copy link
Collaborator

As an optimization, put it in yet another file and source that only when skhd is the parent process.

How would I go about doing that? I've been looking for how to source files from within skhd and can't find anything... I suppose I could do it in each command, but that still leads to a pretty ugly config file.

Put the below in your ~/.zshenv (or equivalent file for your $SHELL). Everything in that if-block will be run only when skhd is the parent process.

if (( $PPID == $(ps aux | grep skhd | awk 'NR==1 { print $2 }') )); then
  terminal-notifier -message "from inside skhd"
fi

@aiguofer
Copy link
Author

In case anyone ends up here, I've written a Python script that allows me to basically re-configure the display indexing and how spaces are distributed among displays: https://github.com/aiguofer/dotfiles/blob/master/user/.local/bin/yabaictl

It could use some work, but it's in a "good enough for now" state. If you want to use this you'll need to change the hashbang at the top and update the setups with your own monitor UUIDs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Request for information or help, not an issue
Projects
None yet
Development

No branches or pull requests

3 participants