I3: How to start a program with long startup time on a specified workspace

i3window-managementworkspacesx11

Is it possible in my i3 startup file to specifically configure a desktop on which to start a program, but only starting it there once without assigning that program to the desktop in general.

I am aware that a solution exists which involves changing to another workspace, but this leaves me with a major issue:
As soon as I have a program with a 'non-instant' startup time, that program will appear on the last workspace that I switch to and not on the workspace where I want it to be.

In specific, this my current startup file where I did a workaround involving the assignment of atom (which is the program bothering me atm) to workspace 9, which is ok for now but is undesirable in the long run:

assign [class="Atom"] $workspace9
exec atom

exec --no-startup-id i3-msg 'workspace $workspace9; exec 
/usr/bin/urxvt'
#exec --no-startup-id i3-msg 'workspace $workspace9; exec /usr/bin/atom'
exec --no-startup-id i3-msg 'workspace $workspace1; exec /usr/bin/urxvt'

I would like to get the commented call for atom to execute in the desired way and ditch the assignment method alltogether.

I don't actually think that it is of relevance but just in case: I run Manjaro-Linux, which is based on Arch.

Edit: The following snippet of code works, but still leaves this question open, as it restricts me to open up atom at last and starting my session on that desktop:

#assign [class="Atom"] $workspace9
#exec atom

exec --no-startup-id i3-msg 'workspace $workspace9; exec 
/usr/bin/urxvt'
exec --no-startup-id i3-msg 'workspace $workspace1; exec /usr/bin/urxvt'
exec --no-startup-id i3-msg 'workspace $workspace9; exec /usr/bin/atom'

This also has the significant drawback that it does not allow for multiple programs starting on different workspaces, if they show the same behavior as atom does.

Best Answer

Wait until the window appears and then send it to the original workspace:

#!/bin/bash

activeworkspace=$(i3-msg -t get_workspaces | jq -c '.[] | select(.focused) | .name' --raw-output)
atom &
windowname=atom
xprop -spy -root _NET_ACTIVE_WINDOW | \
  while read line ; do 
      if xprop WM_CLASS -id ${line##* } | grep -q $windowname ; then
          i3-msg move "[con_id=\"${line##* }\"]" $activeworkspace
          exit
      fi
  done
  • At first get the active workspace, use jq as an example
  • run your program in the background: atom &
  • Use xprop -spy to 'Examine window properties forever, looking for property change events.'
  • Act on all new active windows with while read line
  • Get WM_CLASS of them with xprop WM_CLASS, extract the windowid with bash ${line##* }
  • Filter with grep $windowname
  • Move the window to the original workspace with i3-msg move ..

You should stay on the active workspace and a window on this workspace should get focused.

It doesn't work when you have multiple atom windows which get focused between the start and the move of a new atom window. In this case you would have to look for the NET_WM_PID atom instead of WM_CLASS.

Related Question