Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle scratchpad windows #35

Closed
eater opened this issue Oct 31, 2019 · 31 comments
Closed

Handle scratchpad windows #35

eater opened this issue Oct 31, 2019 · 31 comments
Labels
enhancement New feature or request

Comments

@eater
Copy link

eater commented Oct 31, 2019

It would be great to be able to treat all the running scratchpads as a workspace that can be saved and restored like the others. I often have a dozen of them going.

@eater eater added the enhancement New feature or request label Oct 31, 2019
@JonnyHaystack
Copy link
Owner

Thanks, I'll look into this. I don't use scratchpads myself so I hadn't really thought about it before.

@JonnyHaystack
Copy link
Owner

Okay so saving whatever's in the scratchpad is no problem, it should work exactly the same as with any other workspace. But restoring them is more of a challenge.

The issue is that as far as I know there is no way to actually switch to the scratchpad workspace. The restoring of programs and workspaces relies on you actually having that workspace open and focused.

So the best solution I can think of right now is to:

  1. Switch to a workspace with a unique name that wouldn't be in use
  2. Restore the scratchpad programs there in the normal way
  3. Move all of them to the scratchpad until there's no windows left on that workspace
  4. Finally, switch back to whichever workspace you were in before.

Does this sound like it would work for your use case?

@eater
Copy link
Author

eater commented Nov 1, 2019

That sounds like it would work perfectly, thanks! Or it might be fine to skip steps 1 and 4, just stay on the current workspace, create each window (with the correct geometry) and move it to the scratchpad?

I have config rules that already move some of the windows in question to the scratchpad, but I don't think there's any adverse or back-and-forth effect if you move a window to scratchpad twice.

@JonnyHaystack
Copy link
Owner

Actually it seems like i3-resurrect works fine with the scratchpad already. Try doing i3-resurrect save/restore -w __i3_scratch.

@eater
Copy link
Author

eater commented Nov 7, 2019

When I do that, it creates the two JSON files but each one is empty except for [].

@JonnyHaystack
Copy link
Owner

Oh, yes I see in the current version that is the case. I was testing on the development branch (next). It's because I've added support for floating windows, and all scratchpad windows are floating, so it would never have worked in 1.3.2.

Seeing as it works on the development branch, that's pretty much everything that I wanted to do for the next release, so expect 1.4.0 to drop soon.

@eater
Copy link
Author

eater commented Nov 7, 2019

Oddly, I just tested i3-resurrect save on a normal workspace and it does the same thing there. I have used it successfully recently though.

@eater
Copy link
Author

eater commented Nov 7, 2019

Just built the next branch and it also produces the 2-byte [] files.

@JonnyHaystack
Copy link
Owner

JonnyHaystack commented Nov 8, 2019

That sounds strange, can you give the output of i3-resurrect --version, i3 --version, and python --version? Also what is on those workspaces?

If you're running what's on the next branch then the layout file definitely shouldn't contain [], it should contain {}, even if it's a workspace that doesn't exist.

EDIT:
Bear in mind there have been some dependency changes since the last release, namely wmctrl is no longer used and xprop is required.

@eater
Copy link
Author

eater commented Nov 8, 2019

You're right, it's {} not [] -- when I saw that the new JSON files were 2 bytes I didn't bother to open them again. The workspace I'm testing has 6 tabbed windows, all instances of Evince document viewer.

$ i3-resurrect --version
i3-resurrect, version 1.3.2
$ i3 --version
i3 version 4.16.1 (2019-01-27) © 2009 Michael Stapelberg and contributors
$ python --version
Python 2.7.10
$ python3 --version  
Python 3.6.8

@JonnyHaystack
Copy link
Owner

JonnyHaystack commented Nov 8, 2019

And you get no errors on the command line when you run the command? Are you running it from the command line or through a keybinding? How did you install it? Also might be helpful to know what distro you're on.

Also please provide the full command you are using and the full path to the file you are checking the contents of afterwards.

It seems strange that this would happen when it works fine in the Travis build, and works for me locally, and works on a VM I tested it on.

@eater
Copy link
Author

eater commented Nov 8, 2019

Well, this morning I had a hardware crash and now after rebooting, saving scratchpads works better! It populates the JSON files fully.

Restoring is not working perfectly though. Two issues:

  • Google Chrome windows do not restore properly: https://i.imgur.com/3EV7l19.png
  • The restored windows are positioned way the heck off my monitors (I have dual monitors):
$ wmctrl -lG | grep "\-1"
0x04e00001  -1 -22663 7495 950  787  gen Signal
$ xrandr | grep " connected"   
DP1-2 connected 1050x1680+1920+0 left (normal left inverted right x axis y axis) 470mm x 300mm
DP2-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 470mm x 260mm

@JonnyHaystack
Copy link
Owner

Are these restoring issues only with the scratchpad? Also would be helpful to see the screenshot of the whole desktop, and maybe show what the actual name/class/title of the chrome window are.

@eater
Copy link
Author

eater commented Nov 8, 2019

Yes, only with scratchpad as far as I can tell, but I haven't done a lot of testing with other floating windows.

Here's a screenshot of the whole desktop: https://i.imgur.com/kujEzjc.png

According to xprop, when the Chrome window is correctly loaded:

WM_NAME(UTF8_STRING) = "InstaCalc Online Calculator"
WM_CLASS(STRING) = "instacalc.com", "Google-chrome"

@JonnyHaystack
Copy link
Owner

Okay so I've been testing with google chrome a bit just now and it mostly works. I found there was a problem where for some reason the Chrome process cmdline array has a bunch of empty strings and i3-resurrect wasn't handling those well so chrome didn't get launched. I've fixed that now and will push the changes in a bit.

Aside from that, if the restored program windows are not swallowed into the placeholders created on the scratchpad upon their initial creation, they will appear on the current workspace and not the scratchpad (because it is the placeholder containers that have the scratchpad_state property which causes them to appear on the scratchpad).

If this happens, you can move those windows to the scratchpad manually and run i3-resurrect restore -w __i3_scratch --layout-only.

I also notice that the window instance is different on your system. I am on Arch Linux and the instance name of the chrome window does not change depending on the page for me. This is what I get for the same page:

WM_CLASS(STRING) = "google-chrome", "Google-chrome"
WM_NAME(UTF8_STRING) = "InstaCalc Online Calculator - Google Chrome"

Because the instance name seems to change depending on the page you're on, this may be causing it to not be swallowed without triggering a deferred swallow (as I have just described how to do). I figure maybe for your scratchpad windows you don't need such precise layout restoring, and class + instance isn't really much better than just class. So you could just do i3-resurrect save -w __i3_scratch --swallow class to save it.

@eater
Copy link
Author

eater commented Nov 9, 2019

Pulled the latest from the next branch and tried with and without --swallow class but still can't get it to restore Chrome windows, and now it doesn't restore Signal either: https://i.imgur.com/JdhJoXH.png

@JonnyHaystack
Copy link
Owner

Are you sure the programs themselves are actually being started?

@eater
Copy link
Author

eater commented Nov 11, 2019

They're definitely not being started.

@JonnyHaystack
Copy link
Owner

So what's in the programs file?

@eater
Copy link
Author

eater commented Nov 12, 2019

Pasted below, and it looks like the ones that fail to launch are the ones with command line flags! I deleted --no-sandbox from the Signal command in the JSON file and tried again and that succeeded.

[
  {
    "command": [
      "/opt/Signal/signal-desktop --no-sandbox"
    ],
    "working_directory": "/home/eater"
  },
  {
    "command": [
      "/opt/Pulse SMS/pulse-sms"
    ],
    "working_directory": "/home/eater"
  },
  {
    "command": [
      "/opt/google/chrome/chrome --profile-directory=Default --app=http://instacalc.com"
    ],
    "working_directory": "/home/eater"
  },
  {
    "command": [
      "pavucontrol"
    ],
    "working_directory": "/home/eater"
  },
  {
    "command": [
      "pavucontrol"
    ],
    "working_directory": "/home/eater"
  }
]

@JonnyHaystack
Copy link
Owner

Oh did you edit the programs file manually? Here I explain what's going on here: #50 (comment)

@eater
Copy link
Author

eater commented Nov 12, 2019

No I didn't -- will I need to edit the JSON files every time I save a workspace? That sort of diminishes the convenience of i3-resurrect.

@JonnyHaystack
Copy link
Owner

No, you shouldn't have to. It's weird that it's saving multiple arguments as one... How exactly did you launch those programs the first time?

@eater
Copy link
Author

eater commented Nov 12, 2019

I use Rofi to call /usr/share/applications/signal-desktop.desktop which contains:

[Desktop Entry]
Name=Signal
Exec=/opt/Signal/signal-desktop --no-sandbox %U
Terminal=false
Type=Application
Icon=signal-desktop
StartupWMClass=Signal
Comment=Private messaging from your desktop
Categories=Network;InstantMessaging;Chat;

Similar for the Chrome apps.

@JonnyHaystack
Copy link
Owner

JonnyHaystack commented Nov 12, 2019

So far I'm unable to replicate this at all. I launch programs using rofi as well and the cmdline never has multiple arguments in one list element.

What distro are you using?

EDIT: also what's in your i3-resurrect config file?

@eater
Copy link
Author

eater commented Nov 12, 2019

Ubuntu 18.04. I just tried manually running /opt/Signal/signal-desktop --no-sandbox from the terminal and then a fresh i3-resurrect save -w __i3_scratch and the command is still all on one line.

The i3-resurrect config looks like this:

{
  "window_command_mappings": [
    {
      "class": "Gnome-terminal",
      "command": "gnome-terminal"
    }
  ],
  "window_swallow_criteria": {},
  "terminals": [
    "Gnome-terminal",
    "Alacritty"
  ]
}

@JonnyHaystack
Copy link
Owner

JonnyHaystack commented Nov 12, 2019

Ok looks like this was an upstream bug in psutil giampaolo/psutil#1179

They partially fixed it by checking if there was a null byte at the end of the cmdline file and if there is not they use space as the separator.

However it looks like some processes terminate the cmdline file with a null byte but use spaces as a separator, which is very annoying.. I shall probably create a workaround with shlex.split() or similar.

Do you think you could check the contents of the cmdline files for the processes you're having trouble with? You can do this like so:

  1. Find out the PID: xprop _NET_WM_PID and click on the window
  2. hexdump -C /proc/<pid>/cmdline

@eater
Copy link
Author

eater commented Nov 12, 2019

Interesting.

00000000  2f 6f 70 74 2f 53 69 67  6e 61 6c 2f 73 69 67 6e  |/opt/Signal/sign|
00000010  61 6c 2d 64 65 73 6b 74  6f 70 20 2d 2d 6e 6f 2d  |al-desktop --no-|
00000020  73 61 6e 64 62 6f 78 00                           |sandbox.|
00000028

@JonnyHaystack
Copy link
Owner

Yeah that's exactly it then, it's NUL terminated but uses space for separators, which I think means the process is modifying its own cmdline (by modifying argv or using setproctitle or similar, see https://stackoverflow.com/questions/1585989/how-to-parse-proc-pid-cmdline/1586001#1586001).

Not much point waiting for psutil to work around this so I'll work around it with shlex.split() for now.

@JonnyHaystack
Copy link
Owner

JonnyHaystack commented Nov 13, 2019

@eater I've made a fix and merged it into the next branch. Let me know if that works for you.

EDIT: Realised that patch introduced even more problems. Gonna have to think about this a bit more.

@JonnyHaystack
Copy link
Owner

Closing this as scratchpad windows are supported in the latest release and the issue you are having now is #55

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants