river
river copied to clipboard
[feature request] swallowing
it would be great if it is possible to enable swallowing for certain programs, i.e. the place of the terminal running a program gets replaced with the program while it is running and after that the terminal is returned there again. This would be useful e.g. for pdf, image or video viewers.
We could simply hide the blocked terminal window or sent it to a scratchpad and unhide it when the graphical program exits. See i3-swallow and bspswallow.
As demonstrated by the i3 and bspwm examples, this behavior could be achieved through a simple script if we make the necessary hooks/commands available (see also #52). Lets use this issue to figure out what those necessary hooks/commands would be.
Well this could be done even now but the important thing is that e.g. the image viewer has the same position (and size for floating windows) as the terminal it replaces and when it is closed the terminal also gets the same back again. I don't think that is possible currently.
xdotool windowunmap
and respectively xdotool windowmap
can hide/unhide a window, but we probably still need a command to do it since you can give it no position and size
Also, a hook for the closure of a window will be required.
And last, you need to be able to get the position in stack/position of a floating window and if applicable the size of a window.
I think if you have those, it should be possible to do this with a script.
hooks/commands
Wouldn't it also be possible to use the events in the respective wayland protocols?
For everything that is river specific we could add events to river-status-unstable-v1.xml
.
A wayland client could then listen to these events and do whatever it should do.
@r4pr0n that xdotool windowunmap
approach is insanely hacky, even for X. It is basically overriding the window management without properly communicating with the WM/Compositor, which is fragile and could easily break. It would be a shame to 1:1 port that to river. Complex features like this need first-class support or they won't work correctly. (sorry for late reply)
Wouldn't it also be possible to use the events in the respective wayland protocols?
I think this may be the better approach.
Although we may need to consider whom we are targeting. The average user probably can't write an arbitrary Wayland client to react to events. So maybe we'd need river-event
, which listens to the events and spits them to stdout
so people can script it easiely.
Feel free to propose changes and additions in #140
You can get swallowing on any wayland compositor using cage Just change your binding to something like this:
riverctl map normal $mod Return spawn 'cage st'
Also, it looks like this doesn't break transparency in the terminal window.
Another suggestion for how this may work (for tiling windows that is) is to give riverctl the option to
- Get the stack position of a certain window
- Spawn a program in a certain stack position Then, a script can be written that
- saves the stack position and tag of the terminal in a variable
- moves the terminal to some other tag/scratchpad
- spawns the new program (media viewer, file manager etc) in the stack position saved before
- when this process exists, move the terminal back onto the tag and put it in the proper place in the stack
I know window swallowing as two windows opened as one container with halfs of both windows, see this gif from Awesome, it's harder to do and I don't think it's possible without modification in source code with current state of river.
Edit: here is source and more info how it works. In this case awesome provide different library for each part of window manager, like window management, decorations etc. I think it's possible to create library in high level scripting language like lua tby using river protocols from Zig/C/Ruat backend which somehow would add this behaviour without editing river source.
I know window swallowing as two windows opened as one container with halfs of both windows, see this gif from Awesome, it's harder to do and I don't think it's possible without modification in source code with current state of river.
Edit: here is source and more info how it works. In this case awesome provide different library for each part of window manager, like window management, decorations etc. I think it's possible to create library in high level scripting language like lua tby using river protocols from Zig/C/Ruat backend which somehow would add this behaviour without editing river source.
Perhaps we should define then what exactly this issue requests. I understand swallowing to be the effect that when a gui window is opened from a terminal, the gui window takes the terminal's position until it exists making the terminal is visible again. This is the dwm implementation which I believe to be the first (don't quote me on that) https://dwm.suckless.org/patches/swallow/ "Clients marked with isterminal in config.h swallow a window opened by any child process, e.g. running xclock in a terminal. Closing the xclock window restores the terminal window in the current position."
Perhaps we should define then what exactly this issue requests. I understand swallowing to be the effect that when a gui window is opened from a terminal, the gui window takes the terminal's position until it exists making the terminal is visible again. This is the dwm implementation which I believe to be the first (don't quote me on that) https://dwm.suckless.org/patches/swallow/ "Clients marked with isterminal in config.h swallow a window opened by any child process, e.g. running xclock in a terminal. Closing the xclock window restores the terminal window in the current position."
This can be achieved by spawning your terminal inside Cage instance, this concept came from Plan 9 and it's "implemented" in wio compositor, wio just spawns new instance of cage with your terminal then when you upen any other app it's opened on top of terminal until you close it.
To do that in river you will have to edit tiling protocols or get some top level(?) stuff to get info abour positon and geometry of current client to force river to store freshly opened view on top of terminal.
It's easier to just use cage, every window in this compositor is running as full screen and they are just stacking on top of previous one without any control over them. You could create keybind to spawn prefered terminal enulator and run any app from it, then you can conttol size and tile cage itself. Thats not lightweight way to do this but implementing this in river itself would be a lot of work and some clients e.g from xwayland would be problematic because some of them are spawned as floating by default if client doesn't implement some Xorg specific properties like spotify.
Perhaps we should define then what exactly this issue requests. I understand swallowing to be the effect that when a gui window is opened from a terminal, the gui window takes the terminal's position until it exists making the terminal is visible again. This is the dwm implementation which I believe to be the first (don't quote me on that) https://dwm.suckless.org/patches/swallow/ "Clients marked with isterminal in config.h swallow a window opened by any child process, e.g. running xclock in a terminal. Closing the xclock window restores the terminal window in the current position."
This can be achieved by spawning your terminal inside Cage instance, this concept came from Plan 9 and it's "implemented" in wio compositor, wio just spawns new instance of cage with your terminal then when you upen any other app it's opened on top of terminal until you close it.
To do that in river you will have to edit tiling protocols or get some top level(?) stuff to get info abour positon and geometry of current client to force river to store freshly opened view on top of terminal.
It's easier to just use cage, every window in this compositor is running as full screen and they are just stacking on top of previous one without any control over them. You could create keybind to spawn prefered terminal enulator and run any app from it, then you can conttol size and tile cage itself. Thats not lightweight way to do this but implementing this in river itself would be a lot of work and some clients e.g from xwayland would be problematic because some of them are spawned as floating by default if client doesn't implement some Xorg specific properties like spotify.
True, but using cage for this seems.. convoluted. Swallowing is in fact a vary simple feature and spawning an entirely new compositor (with all the overhead and other issues that come along with it) seems to be a bit overkill. I am open to other opinions of course, especially as cage, wlroots and river continue to age and evolve.
For clarity, I have tried to use cage to achieve window swallowing only to find it could not make proper use of my gpu. I reported this to the cage team and it seems to be a problem specific to my laptop (a pinebook pro). However, this is why I feel that using cage as a solution is like using a rifle to shoot a fly.
Swallowing is in fact a vary simple feature [...]
Nope, it really is not. It may seem simple from the perspective of a user, but if you want to implement it into a compositor cleanly, you'll face lots of problems and complexity.
For example, how do you know which windows should be "swallowed"? That would require knowing from which window a new window is spawned from, which is not as trivial as just looking at child processes. This could theoretically be solved with a custom protocol extension, but you'd never get enough clients to support it.
Another suggestion for how this may work (for tiling windows that is) is to give riverctl the option to [...]
Can't say I like this idea. That kind of hack is how you might do it on X, but on Wayland we have different standards w.r.t. to quality, so this just does not sit right with me. This kind of feature would need a proper implementation to not be a hacky mess.
Anyway, I think neither implementing it directly or allowing the amount of scriptability to allow that kind of hack are in scope right now. So IMO this issue should just be closed.
Nope, it really is not. It may seem simple from the perspective of a user, but if you want to implement it into a compositor cleanly, you'll face lots of problems and complexity.
Okay you make fair points. I called the feature "simple" because the dwm implementation is quite simple and the patch quite small. What I mean is that we "shouldn't" need to nest an entire compositor (qua cage) inside of river to get this to work.
For example, how do you know which windows should be "swallowed"?
This is absolutely a fair point and one I had not though of yet though I think it may be solvable without a custom protocol. Admittedly though that would place the solution in the realm of hacks and tricks which we may not desire.
I am not opposed to hacks, but it is up to the river devs and maintainers what standard of quality they wish to set. I don't wish to come in and appear to be lecturing everybody on how to do things better :)
Nesting few instances of cage in river doesn't use more than 130mb ram where river takes 65mb, and few instances of cage the rest from 130mb. Xorg compared to river takes 120mb+, awesome 350mb and picom 180mb+, so you can see how lightweight is just getting swallowing by nesting terminal in cage.
Using cage is a more hacky solution than implementing those functions in riverctl imo. I'm currently using sway, where I use i3-swallow. I think the workflow where you type i3-swallow and then a command is great, but the function of it is very bad. In DWM, however, the swallow functionality is very good. The window coordinates are right whether it is a floating window or not, the stack position is correct and so on.
But using a whole new compositor for each terminal is firstly inefficient, it causes problems with input settings and also, you cannot just run some applications in swallow (e.g. swallow sxiv when run from the terminal, but don't do the same with firefox) with a builtin functionality or one via the solution by @user18130814200115-2 would allow all of these usecases.
The suggested solution of using cage to implement terminal swallowing isn't working well for me. There is a big performance hit when using cage like this. E.g. running cage -d alacritty
, the cursor lags when performing any kind of repetitive action (movement, delete, backspace). IMO river should implement this functionality, similar to dwm.
Hey, before posting yet another "I also want this feature" comment, please make sure to ...
- ... read all previous comments, especially those explaining why this proposed feature isn't actually possible to implement correctly.
- ... understand that +1 comments don't add anything to the discussions and decrease the signal to noise ratio.
- ... just use one of the emoji-reaction-things instead to "voice" your support of this feature request. They are just as visible.
Kind regards.
Yes, we are aware that this is a popular feature people want and we also know that cage isn't an ideal solution.
@Leon-Plickat For clarity- your objection to implementing swallowing the 'simple' way is this:
For example, how do you know which windows should be "swallowed"? That would require knowing from which window a new window is spawned from, which is not as trivial as just looking at child processes.
Do I understand that correctly? If a user runs a program in a terminal that is set to swallow- why would it not be a child process?
I want this feature enough that I will dig in to the implementation details to see if I can make it work.
A PID <-> Wayland window
connection is not something you can do correctly.
Also, what if your terminal uses a client server model, like foot has? The new window is not a child of another wayland client, so this would immediately fall apart. And also let's not forget that one wayland client can spawn multiple windows. Which of those will be swallowed? Or in case of the parent, which is the swallower?
This needs proper protocol support, or it won't ever be more than a barely working hack.
Now, actually we have something new and fancy now that may make this possible: The xdg-activation protocol. It could be used to make river aware of one client launching another, so you could actually now implement swallowing in a non-hacky fashion I guess, however client support is pretty limited, so it would not work with very many windows really. Also I am pretty certain it would not get merged based on rivers current plan w.r.t. what is planned.