You are not logged in.

#1 2023-06-28 06:15:03

Stefan_xyz
Member
Registered: 2019-09-01
Posts: 104

i3wm | Open (child)Container in same workspace as originally started

So I multiple monitors and often I open a program on one workspace, switch to another and wait till the program opens (PyCharm, AndroidStudio, Discord take their time).
But either I switch workspace so fast that it opens the window currently used workspace instead of the one I opened it. The same happens when their "loading screen" (don't know what it's called) is finished and the main program is opened.

So if I open PyCharm in Workspace 2 and switch to Workspace 1 Pycharm should open in Workspace 2 but it "jumps" to Workspace 1.


Is there a possibility to fix this?


Note:
I have tried around with

no_focuse

and

 focus_on_window_activation 

but it didn't work.
I'm also aware that it's possible to force one program to one fixed workspace but I would like to do it dynamically for all programs.

Offline

#2 2023-07-20 10:20:29

anthony93
Member
Registered: 2021-07-31
Posts: 11

Re: i3wm | Open (child)Container in same workspace as originally started

This can be implemented quite easily using i3's IPC mechanism. The steps:

  1. Obtain a list of all available workspaces together with their state data at the time the application is launched (e.g: via a keybinding)

  2. Parse the output to obtain the name of the workspace that is active at the time the application is launched.

  3. Move the window to said workspace with i3-msg

Step 1 is easy.

 i3-msg -t get_workspaces 

That's all you need. Note that the output will be a raw string that needs to be parsed before the data can be extracted (Step 2). Do NOT use a shell script to do it; there are far superior tools (python, perl, etc) for this.
Off the top of my head, here's a simple python program that implements the feature you described:

# Script to launch pycharm (dependencies: wmctrl, awk)
import os
import subprocess
import json
import time

# Utility functions
def get_latest_window_class():
    pipe = os.popen("wmctrl -lx | awk '{print $3}'")
    return pipe.readlines()[-1].strip()

def get_window_count():
    pipe = os.popen("wmctrl -lx | wc -l")
    return int(pipe.read().strip())

initial_win_count = get_window_count()

# Get the name of the focused workspace
workspaces_raw_output = subprocess.run(["i3-msg", "-t", "get_workspaces"], capture_output=True).stdout.decode().strip()
workspace_list = json.loads(workspaces_raw_output)
focused_workspace = ""
for workspace in workspace_list:
    if workspace["focused"]:
        focused_workspace = workspace["name"]
        break

# Launch PyCharm (or any application, for that matter)
subprocess.Popen(["setsid", "pycharm"])

# Wait for the window to be drawn first before attempting to move it
while True:
    current_win_count = get_window_count()
    if current_win_count > initial_win_count: # new window is drawn
        if get_latest_window_class() == "PyCharm.PyCharm": # make sure that the newly drawn window is PyCharm
            break
    # For all other cases, wait
    time.sleep(0.05)   

# Use i3-msg to move the window to the workspace
os.system(f"i3-msg [class=PyCharm] move container to workspace {focused_workspace}")

After that, you just have to assign a keybinding to run this script

# Inside your i3 config
bindsym $mod+p exec --no-startup-id ~/launch_pycharm.py

Caveats:

  1. The program requires awk and wmctrl to work. Make sure you have them installed.

  2. This will only work if you launch the script using a keybinding; if you wish to implement this behavior for applications that are launched through dmenu/rofi,  you're going to have to modify the desktop files for those applications, which I don't recommend.

  3. I only guessed the WM_CLASS string used in the code; you have to verify it with xprop.

  4. The choice of 0.05-second wait time is entirely arbitrary. You should experiment with different values for the best effect.

  5. You may notice a flicker in current workspace before the window is moved to the desired workspace (though I'm not sure since I haven't tested the code).

I didn't have time to test the code, but it should work.

Good luck.

Last edited by anthony93 (2023-07-20 15:24:29)

Offline

#3 2023-07-20 12:46:05

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: i3wm | Open (child)Container in same workspace as originally started

I'm not sure why you think python is particularly good for this.  This does (about) the same in a shell script, but uses an exact pid match rather than relying on a match with the first class name (what if two windows open):

i3-msg -t get_workspaces | jq -r '.workspace_list|select(.focused=="true").name'

pycharm &
pid=$!

while ! wmctrl -lp | cut -d' ' -f3 | grep -q $pid; do sleep 0.1; done

i3-msg "[class=PyCharm] move container to workspace {focused_workspace}"

The jq string may need some adjustment - I don't have any of these tools installed for actual testing, but somthing very close to that should work.

i3 also has "marks" which should might be useful here, though I have no experience with them.  So the above could be simplified yet further to (but see the next comment, marks may not work for workspaces):

it-msg mark pycharm
pycharm &
pid=$!
while ! wmctrl -lp | cut -d' ' -f3 | grep -q $pid; do sleep 0.1; done
i3-msg '[class=PyCharm] move container to mark pycharm'
i3-msg 'unmark pycharm'

Last edited by Trilby (2023-07-20 13:39:20)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#4 2023-07-20 13:22:55

anthony93
Member
Registered: 2021-07-31
Posts: 11

Re: i3wm | Open (child)Container in same workspace as originally started

I'm not sure why you think python is particularly good for this

Probably because I'm running on fumes and not thinking straight. It could also be due to my ignorance of the command-line JSON parser, jq.

i3 also has "marks" which should be useful here, though I have no experience with them

I didn't know that marks can be set for workspaces in i3. I thought they only apply to windows and containers.

Regardless, your solution is indeed far superior.

Last edited by anthony93 (2023-07-20 13:23:45)

Offline

Board footer

Powered by FluxBB