i3 fails to consistently execute last order in command chain (ipc)

asked Aug 3 '14

hbaughman gravatar image

updated Aug 5 '14

I am making a ruby script to vertically swap pairs of screens on my 2x2 grid of monitors. The actual flipping works perfectly, but I am having difficulty consistently restoring focus to the original workspace.

My script works by building a single large command that switches to each workspace and moves it to a screen. An example command might be:

workspace w:ff; move workspace to xinerama-2; workspace p:ref; move workspace to xinerama-3; workspace a:dl; move workspace to xinerama-3; workspace p:shop; move workspace to xinerama-3; workspace p:bet; move workspace to xinerama-3; workspace a:mail; move workspace to xinerama-3; workspace a:music; move workspace to xinerama-3; workspace p:fun; move workspace to xinerama-1; workspace a:file; move workspace to xinerama-1; workspace w:ref; move workspace to xinerama-1; workspace 4; move workspace to xinerama-0; workspace w:chr; move workspace to xinerama-3; workspace w:sub; move workspace to xinerama-2

To this I append a command to focus the originally focused workspace (which I saved earlier). I have tried this by focusing the workspace itself (i.e., workspace w:chr) as well as focusing the output that it will be on when the script resolves (i.e., focus output xinerama-2). I then pass the whole command at once to i3 through i3ipc-glib (care of a ruby gem gir_ffi).

A minority of the time, the last command does not execute (or I think more likely, doesn't execute in order). In such cases, I believe it usually (always?) winds up focusing the output with the fewest workspaces. It also seems like the problem is more likely to occur when there is a greater disparity between the number of workspaces on the most and least populated outputs.

This problem persists even when I move the final focusing command into its own call to i3.

@i3.command giant_flip_command
@i3.command "workspace w:chr"

I have been able to kludge a solution by making the script sleep 0.2 between these two commands. But this causes a distracting jump in the cursor.

How can I make i3 return focus to the original workspace at the end of my script?

EDIT: Unfortunately the script it is hard-coded for 4 screens in a 2x2 grid using xinerama. If that doesn't scare you off it's on my github. Just comment out lines 24 and 25 (the kludge) and run if from the command line. It only happens sometimes so, try for i in {1..10}; do ruby ./flip_screens.rb; sleep 1; done.

EDIT 2: To see the problem on your machine:

  1. Populate your first screen with workspaces 1-5 (they all must contain a client so they don't auto-close) and put workspace 6 on your second screen.
  2. Add this to your config file replacing first_output_name and second_output_name with your output names (e.g., DVI-I-1 and DVI-I-2)

    set $screen0 first_output_name
    set $screen1 second_output_name
    
    bindsym $mod+z workspace 1; move workspace to $screen1; workspace 2; move workspace to $screen1; workspace 3; move workspace to $screen1; workspace 4 ...
(more)

Comments

Could you provide an example of the failure that works with a default i3 config?

joepd gravatar imagejoepd (Aug 3 '14)edit

@joepd Are you asking for the script? If so, I edited the post to include it. The script isn't very portable, at the moment, it is hard-coded for 4 screens in a 2x2 grid using xinerama.

hbaughman gravatar imagehbaughman (Aug 3 '14)edit

Using "mark" maybe?

zolar gravatar imagezolar (Aug 3 '14)edit

No, I was attempting to ask for a concise, reproducable test case. A polite yet unclear way of saying: "TLDR" ;)

joepd gravatar imagejoepd (Aug 4 '14)edit

@joepd I added a test case that will hopefully work on your machine.

hbaughman gravatar imagehbaughman (Aug 5 '14)edit