fogine / i3-workscreen

In i3wm compatible manner - dynamically re-configures your (multi)-monitor setup on the fly when you hotplug/unplug display cabel(s)
MIT License
38 stars 4 forks source link

Don't create an empty workspace #9

Open antoyo opened 2 years ago

antoyo commented 2 years ago

Hi. I really like this tool, thanks for making it.

I do have a minor annoyance with it though: the monitor that did not have focus will have a new empty workspace created. For instance, if monitor HDMI-1 had workspaces 1 and 3 and monitor DVI-D-1 has workspace 2 and the focus is on workspace 3 and I unplug HDMI-1 and plug it back, I will end up with a new workspace 10 on DVI-D-1 which is empty. If the focus was on workspace 2 (or any monitor that stays connected), no new workspace will be created.

Here's my config:

{
    "outputs": [
        {
            "name": "HDMI-1",
            "xrandr": ["--primary"],
            "workspaces": [ "1", "3", "5", "7", "9" ]
        },
        {
            "name": "DVI-D-1",
            "xrandr": ["--right-of", "HDMI-1"],
            "workspaces": [ "2", "4", "6", "8", "10" ]
        }
    ]
}

I had a similar issue before using this tool, so maybe it's not caused by this tool.

Have you noticed this issue? Is this normal?

Thanks for your help!

fogine commented 2 years ago

Looking at the code now. Its trying to focus the workspace which is lost (workspace 3 in your case) which is not possible so i3wm automatically creates a new workspace instead.. I could focus first existing workspace instead when the focused workspace is lost due to unplugged output.. The fix would not create a new empty workspace. Its not possible to regain focus of previously lost workspace (in your case workspace 3)

antoyo commented 2 years ago

Focusing an existing workspace would be better indeed. I'm not sure I understand why the workspace is lost, though. What do you mean by "lost workspace"? The workspace still exists. Thanks!

fogine commented 2 years ago

please try the new 1.0.1 release, it should be fixed.

fogine commented 2 years ago

fyi, I recreated the issue you described. I implemented a fix which makes sure active workspaces dont change on other display outputs on unplug event..

antoyo commented 2 years ago

Thanks for looking into this. Unfortunately, the problem is worse now: I get an empty workspace on both monitors. Plus, this issue now arises whether the focused workspace is on monitor HDMI or DVI.

Just to make sure you understand the issue: it's creating the empty workspace when I plug back the second monitor.

fogine commented 2 years ago

@antoyo could you test whether the issue still persists for the following git branch? https://github.com/fogine/i3-workscreen/tree/%239-fix-second-take

antoyo commented 2 years ago

I'm still having some issues with that branch. This version will create an empty workspace when unplugging a monitor (no matter which workspace is focused). The original version (1.0) would instead create an empty workspace when plugging the monitor.

fogine commented 2 years ago

Hm, thats weird. If you unplug the monitor, you have single active display, right? In that case active workspace should be the same as it was before you unplug the monitor.. Could you post the output of the following commands, before and after you connect/disconnect additional monitor?

xrandr

i3-save-tree --output HDMI-1

i3-save-tree --output DVI-D-1

antoyo commented 2 years ago

There you go: dvi_after_disconnect.txt dvi_before_disconnect.txt hdmi_after_disconnect.txt hdmi_before_disconnect.txt xrandr_after_disconnect.txt xrandr_before_disconnect.txt

I wonder if having the disconnected monitor being the primary one would cause an issue.

fogine commented 2 years ago

I would expect this file dvi_after_disconnect.txt to contain:

{                                                                               
    // workspace with 0 children                                                
    "border": "pixel",                                                          
    "floating": "auto_off",                                                     
    "fullscreen_mode": 1,                                                       
    "layout": "splith",                                                                                                                                         
    "marks": [],                                                                
    "percent": null,                                                            
    "type": "workspace"                                                         
}        

aka. empty workspace (newly created workspace after monitor is disconnected) but I see two workspaces with apps in them... but thats maybe because you switched to some other workspace to run i3-save-tree command and the newly created workspace got removed?

Also whats the behavior you are striving for with your json configuration? It seems like DVI-D-1 is primary monitor and you connect/disconnect HDMI-1 to it?

With the following configuration:

{
    "outputs": [
        {
            "name": "DVI-D-1",
            "xrandr": ["--right-of", "HDMI-1"],
             "workspaces": [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ]

        },
        {
            "name": "HDMI-1",
            "xrandr": ["--primary"],
            "workspaces": [ "1", "3", "5", "7", "9" ]
        }
    ]
}

when only dvi-d-1 is connected all workspaces will be assigned to it and when you connect hdmi-1, hdmi will have "odd" workspaces and dvi-d-1 will have "even" workspaces..

antoyo commented 2 years ago

You're right, I do have the following for DVI after disconnect if I run the command "correctly":

{
    // workspace with 0 children
    "border": "normal",
    "floating": "auto_off",
    "fullscreen_mode": 1,
    "layout": "splith",
    "marks": [],
    "percent": null,
    "type": "workspace"
}

Yeah, I haven't checked that part, but I would like DVI to only become the primary when it's the only monitor connected.

My setup is having a laptop and a desktop both connected to the HDMI monitor.

fogine commented 2 years ago

In the new branch I cannot recreate the behavior you described (no new workspace is created when I unplug one of the two monitors). Could you also post the output of i3-msg -t get_workspaces | python -m json.tool from the new empty workspace when you unplug the HDMI, the output should contain workspace number of the new workspace, I'm curious if the workspace number is always the same or its random, can you try it couple of times?

Yeah, I haven't checked that part, but I would like DVI to only become the primary when it's the only monitor connected.

I dont understand... What do you mean? I think the config I posted would make DVI primary only when its the only monitor connected just like you want..

fogine commented 2 years ago

Also can you try to temporarily disable the udev rule and after you unplug the hdmi, run i3-workscreen manually from terminal. Is behavior the same?

antoyo commented 2 years ago

In the new branch I cannot recreate the behavior you described (no new workspace is created when I unplug one of the two monitors). Could you also post the output of i3-msg -t get_workspaces | python -m json.tool from the new empty workspace when you unplug the HDMI, the output should contain workspace number of the new workspace, I'm curious if the workspace number is always the same or its random, can you try it couple of times?

Here's the output:

[
    {
        "id": 94405355920528,
        "num": 1,
        "name": "1",
        "visible": false,
        "focused": false,
        "rect": {
            "x": 0,
            "y": 48,
            "width": 1920,
            "height": 1032
        },
        "output": "DVI-D-1",
        "urgent": false
    },
    {
        "id": 94405356028848,
        "num": 2,
        "name": "2",
        "visible": false,
        "focused": false,
        "rect": {
            "x": 0,
            "y": 48,
            "width": 1920,
            "height": 1032
        },
        "output": "DVI-D-1",
        "urgent": false
    },
    {
        "id": 94405356089840,
        "num": 10,
        "name": "10",
        "visible": true,
        "focused": true,
        "rect": {
            "x": 0,
            "y": 24,
            "width": 1920,
            "height": 1056
        },
        "output": "DVI-D-1",
        "urgent": false
    }
]

It is always workspace 10 that is created. The funny thing is that if workspace 10 already exists, no empty workspace will be created.

Yeah, I haven't checked that part, but I would like DVI to only become the primary when it's the only monitor connected.

I dont understand... What do you mean? I think the config I posted would make DVI primary only when its the only monitor connected just like you want..

Well, the file xrandr_after_disconnect.txt shows that the disconnected HDMI is the primary monitor. It's not always an issue, but it seems to be on my laptop where I lose the system tray because the only active monitor is not the primary one.

Also can you try to temporarily disable the udev rule and after you unplug the hdmi, run i3-workscreen manually from terminal. Is behavior the same?

Yes, same behavior when ran manually.

Thanks for your help!

fogine commented 2 years ago

Ok, I cant recreate it on my machine. Could you apply the following patch, run i3-command manually after you disconnect the monitor and post the output? This should tell me whether i3-workscreen is activelly trying to swtich to workspace 10 after you unplug hdmi or there is some other unknown issue.

diff --git a/i3workscreen/i3workscreen.py b/i3workscreen/i3workscreen.py
index 3ba9699..e8f46ec 100644
--- a/i3workscreen/i3workscreen.py
+++ b/i3workscreen/i3workscreen.py
@@ -272,6 +272,10 @@ def main():
     i3.command(i3cmd)

     activeWorkspaces = getWorkspaceWithWindowPerOutput()
+    print('========ACTIVE WORKSPACES====')
+    print(activeWorkspaces)
+    print('========VISIBLE WORKSPACES====')
+    print(visibleWorkspaces)

     for output in connectedOutputs:
         # output does not have any workspace
@@ -288,10 +292,14 @@ def main():
         # if the workspace should be in the current output
         # set it as the active workspace
         if visibleWorkspace in outputConf['workspaces']:
+            print('========SWITCHING TO PREVISOUSLY VISIBLE WORKSPACE====')
+            print(visibleWorkspace)
             i3.command('workspace {0}'.format(visibleWorkspace))
         #else set as the active workspace first workspace which belongs to the output
         #and has any window in it
         else:
+            print('========SWITCHING TO ACTIVE WORKSPACE====')
+            print(activeWorkspace)
             i3.command('workspace {0}'.format(activeWorkspace))

     i3.command('workspace {0}'.format(focusedWorkspace))
antoyo commented 2 years ago

Here's the output:

========ACTIVE WORKSPACES====
{'DVI-D-1': '1'}
========VISIBLE WORKSPACES====
{'DVI-D-1': '2', 'HDMI-1': '1'}
========SWITCHING TO PREVISOUSLY VISIBLE WORKSPACE====
2

It doesn't seem to mention a workspace 10…

fogine commented 2 years ago

Hm, ok last debug patch, then I'm out of ideas:

diff --git a/i3workscreen/i3workscreen.py b/i3workscreen/i3workscreen.py
index 3ba9699..542b38a 100644
--- a/i3workscreen/i3workscreen.py
+++ b/i3workscreen/i3workscreen.py
@@ -294,6 +294,9 @@ def main():
         else:
             i3.command('workspace {0}'.format(activeWorkspace))

+    print('========FOCUSING WORKSPACE====')
+    print(isFocusedWorkspaceLost)
+    print(focusedWorkspace)
     i3.command('workspace {0}'.format(focusedWorkspace))

apply it on top of the previous debug messages please..

antoyo commented 2 years ago

It says:

========ACTIVE WORKSPACES====
{'DVI-D-1': '1'}
========VISIBLE WORKSPACES====
{'DVI-D-1': '2', 'HDMI-1': '1'}
========SWITCHING TO PREVISOUSLY VISIBLE WORKSPACE====
2
========FOCUSING WORKSPACE====
2

Removing the following line seems to fix my issue:

i3.command('workspace {0}'.format(focusedWorkspace))

Any reason why you need to focus the workspace?

fogine commented 2 years ago

After unplug/plug event I have to reassign all workspaces to their correct display outputs and at the end it tries to set focus back where it's been. Without it you would have to manually refocus eg. your workspace with text editor to continue work..

Weird that it causes issues for you. It seems like the workspace 2 doesnt exists after you unplug the monitor? That would explain why i3wm always switches to workspace 10

vanarok commented 2 years ago
{
    "disableEmptyOutputs": false,
    "outputs": [
        {
            "name": "eDP1",
            "workspaces": [ "1", "2", "3", "4", "5", "6", "7", "8" ]
        },
        {
            "name": "HDMI1",             
            "xrandr": ["--above", "eDP1"],
            "workspaces": [ "1", "2", "3", "4" ]
        }
    ]
}

5,6,7,8 spaces are moved to hdmi1 if they are empty and are not moved if they have windows in them when i3-workspace is activated