infokiller / i3-workspace-groups

Manage i3wm workspaces in groups
MIT License
222 stars 15 forks source link

Document client/server mode #52

Open infokiller opened 2 years ago

orhun commented 10 months ago

Latency is a big problem that prevents me from using i3-workspace-groups so it would be nice to finally document this feature and add instructions about how to enable it 🐻

infokiller commented 10 months ago

Hey @orhun sorry for the delay. I will do a release to Pypi later this week and add better instructions, but just to get you going (if you're ok with installing directly from source), you need to do two things:

  1. Run the server using i3-workspace-groups --log-level=info server (the --log-level is there for you to spot any issues, but is not really required). You need to keep it running in the background (I use a systemd user service, but you can do it however you want).
  2. Change every execution of i3-workspace-groups to i3-workspace-groups-client, for example in your i3/sway config you can use set $exec_i3_groups exec --no-startup-id i3-workspace-groups-client.
orhun commented 9 months ago

Hey, just tried this and there is a noticeable speed difference! Nice.

Can you share your systemd unit and save me from writing one from scratch?

Also, it would be nice to finalize this feature and have a new release. I had to install the -git version of this project to make it work.

infokiller commented 9 months ago

Hey @orhun my apologies for not doing the release yet and adding docs yet, hopefully it will actually happen this week. You can use the following systemd unit (save it in .config/systemd/user/i3-workspace-groups-server.service):

[Unit]
Description=i3 workspace groups server
# Makes sure that this unit is stopped when the graphical session is terminated.
# https://www.freedesktop.org/software/systemd/man/systemd.special.html#graphical-session.target
BindsTo=graphical-session.target
After=graphical-session.target

[Service]
Type=simple
Restart=on-failure
RestartSec=5
# Wait for i3 socket to be available.
# NOTE: this may no longer be needed since i3 4.20 supports systemd notify.
ExecStartPre=bash -c 'while true; do i3-msg nop &> /dev/null && break; sleep 1; done'
ExecStart=i3-workspace-groups --log-level info server

The unit file I'm using is in my dotfiles repo, but it's slightly different because runs the code from source, and also has a complex systemd setup where i3 itself also runs as a unit.

You can then activate the server from your i3 config, for example using exec --no-startup-id systemctl --user start i3-workspace-groups-server.

Please let me know if that works.

orhun commented 9 months ago

Unfortunately the systemd service did not work for me.

I'm getting:

Jan 06 16:10:17 thinkpad systemd[1709]: Starting i3 workspace groups server...
Jan 06 16:11:47 thinkpad systemd[1709]: i3-workspace-groups-server.service: start-pre operation timed out. Terminating.
Jan 06 16:11:47 thinkpad systemd[1709]: i3-workspace-groups-server.service: Control process exited, code=killed, status=15/TERM
Jan 06 16:11:47 thinkpad systemd[1709]: i3-workspace-groups-server.service: Failed with result 'timeout'.
Jan 06 16:11:47 thinkpad systemd[1709]: Failed to start i3 workspace groups server.

It is due to:

ExecStartPre=bash -c 'while true; do i3-msg nop &> /dev/null && break; sleep 1; done'

I am able to run i3-msg just fine:

$ i3-msg
[]

So I'm thinking it is because the systemd unit cannot access i3 or something.

When I remove this pre-start condition, I get:

Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]: Traceback (most recent call last):
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:   File "/usr/bin/i3-workspace-groups", line 445, in <module>
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:     main()
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:   File "/usr/bin/i3-workspace-groups", line 435, in main
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:     i3_connection = i3ipc.Connection()
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:                     ^^^^^^^^^^^^^^^^^^
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:   File "/usr/lib/python3.11/site-packages/i3ipc/connection.py", line 68, in __init__
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]:     raise Exception('Failed to retrieve the i3 or sway IPC socket path')
Jan 06 16:14:22 thinkpad i3-workspace-groups[2415226]: Exception: Failed to retrieve the i3 or sway IPC socket path
Jan 06 16:14:22 thinkpad systemd[1709]: i3-workspace-groups-server.service: Main process exited, code=exited, status=1/FAILURE
Jan 06 16:14:22 thinkpad systemd[1709]: i3-workspace-groups-server.service: Failed with result 'exit-code'.
Jan 06 16:14:27 thinkpad systemd[1709]: i3-workspace-groups-server.service: Scheduled restart job, restart counter is at 1.

Which I think corrects my theory.

orhun commented 9 months ago

I managed to start the server via:

$ systemctl --user import-environment DISPLAY XAUTHORITY

$ systemctl --user start i3-workspace-groups-server

But it is not working correctly, I get new workspaces (after 10th one) instead of a separate group.

infokiller commented 9 months ago

@orhun sorry for the issues, indeed I forgot to add that for importing relevant environment variables, I have a separate service file which automatically runs (because of WantedBy=basic.target). You can try to add this service, maybe there are other environment variables missing (I believe you need XDG_RUNTIME_DIR set properly so that it can find the i3 socket). Another thing you can do is run systemctl --user show-environment to see the current environment in the user service manager, and verify the variables are there. Lastly, you can try to run the service ephemerally and interactively from a terminal, which makes debugging easier. For example, run systemd-run --user --pty --wait i3-workspace-groups --log-level info server and see if there are any obvious issues that come up.

infokiller commented 9 months ago

But it is not working correctly, I get new workspaces (after 10th one) instead of a separate group.

@orhun can you please clarify this? If you run i3-workspace-groups-client --log-level=info list-groups, what is the output? To switch to a new group from the CLI, you can similarly run i3-workspace-groups-client --log-level=info switch-active-group test-group.

infokiller commented 9 months ago

@orhun I uploaded a preview version to pypi, so you can install it without cloning the repo: pip install 'i3-workspace-groups==0.4.7a12'

orhun commented 9 months ago

I gave up on systemd and put i3-workspace-groups server on my X11 startup. Everything works fine except:

infokiller commented 9 months ago

@orhun another option you have, in case it helps, is to start it from your i3 config (using exec ...). When you say 2 TTY sessions, are they both graphical? The issue with the "11" workspace is strange- feel free to open a bug and we can troubleshoot.

And is latency good enough now?

orhun commented 9 months ago

When you say 2 TTY sessions, are they both graphical?

Yes, both running i3 under Xorg.

The issue with the "11" workspace is strange- feel free to open a bug and we can troubleshoot.

Thank you! 🙏🏼

And is latency good enough now?

Yes! It is not even noticeable 🚀

orhun commented 9 months ago

Another thing that I realized is the previous workspace is not restored when I switch between groups. For example:

infokiller commented 9 months ago

@orhun thanks for the feedback, great to hear that latency is now good enough! If you're up to troubleshooting the issue with workspace 11, here's what you can do: when you are on group "second", switch back to "default" by using the following command in a terminal: i3-workspace-groups --log-level=debug switch-active-group ''", then paste the output here. BTW, how do you normally switch between groups?

infokiller commented 9 months ago

@orhun regarding multiple TTYs, each running i3wm/sway, it's supported, but you need to make sure that:

  1. Each i3-workspace-groups server is running with a different socket, which you can specify by using the --server-addr param to i3-workspace-groups server. It currently defaults to ${XDG_RUNTIME_DIR}/i3-workspace-groups.sock, but I guess it may make more sense to use something that depends on DISPLAY, which will make it work automatically when using multiple X11 servers.
  2. The socket path is exported in the env var I3_WORKSPACE_GROUPS_SOCKET when calling i3-workspace-groups-client
infokiller commented 9 months ago

@orhun regarding multiple TTYs, each running i3wm/sway, it's supported, but you need to make sure that:

  1. Each i3-workspace-groups server is running with a different socket, which you can specify by using the --server-addr param to i3-workspace-groups server. It currently defaults to ${XDG_RUNTIME_DIR}/i3-workspace-groups.sock, but I guess it may make more sense to use something that depends on DISPLAY, which will make it work automatically when using multiple X11 servers.
  2. The socket path is exported in the env var I3_WORKSPACE_GROUPS_SOCKET when calling i3-workspace-groups-client

@orhun update: I just pre-released a version to pypi that uses DISPLAY for the socket, which should make it work for your use case. To install it: pip install 'i3-workspace-groups==0.4.7a14'

orhun commented 9 months ago

I just tried the latest git version and it worked for both ttys! Also, for some reason 11th workspace issue is gone for me as well. It's all good now, thanks!

orhun commented 9 months ago

Here is how I integrated i3-workspace-groups: https://github.com/orhun/dotfiles/commit/6abd4261bb939b9309d71cfe52b6438ad566327b

infokiller commented 9 months ago

I just tried the latest git version and it worked for both ttys! Also, for some reason 11th workspace issue is gone for me as well. It's all good now, thanks!

Great, if the issue is back, let me know and we can troubleshoot.