xmonad-contrib
xmonad-contrib copied to clipboard
Previously floating fullscreen windows tiles after leaving fullscreen
Problem Description
When opening a floating window, entering fullscreen with fullscreenEventHook and leaving fullscreen the window tiles instead of floating again.
Configuration File
Please include the smallest configuration file that reproduces the problem you are experiencing:
module Main (main) where
import XMonad
import XMonad.Hooks.EwmhDesktops
import qualified XMonad.StackSet as W
import qualified Data.Map as M
main :: IO ()
main = xmonad def {
handleEventHook = fullscreenEventHook,
mouseBindings = myMouseBindings
}
myMouseBindings :: XConfig l -> M.Map (KeyMask, Button) (Window -> X())
myMouseBindings (XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm, button1), (\w -> focus w >> mouseMoveWindow w
>> windows W.shiftMaster))
, ((modm, button2), (\w -> focus w >> windows W.shiftMaster))
, ((modm, button3), (\w -> focus w >> mouseResizeWindow w
>> windows W.shiftMaster))
]
Checklist
-
[x] I've read CONTRIBUTING.md
-
[ ] I tested my configuration with xmonad-testing
This is due to this line simply sinking the window when fullscreen is removed; I guess the stackset could have changed in the meantime and for tiled windows trying to restore some sort of "previous position" is practically impossible.
I wonder if it's worth making an exception for floating windows here; what do other people think?
simply sinking the window trying to restore some sort of "previous position" is practically impossible
If the stackset doesn't change, then "simply sinking the window" does restore its original position. When I fullscreen a tiled window and then unfullscreen it, everything is back to where it was. If the window is moved in between, then the stackset is changed and when it sinks, it sinks into the master position or something, but I'd argue that stackset changing during fullscreen isn't all that likely.
But floats… everything related to floats in xmonad is quite a hack, and fullscreening/maximization is a hack on top of a hack. :-( There's X.L.Fullscreen and X.L.Maximize, but they probably don't work with floats either. I wish floats weren't handled by the core at all but needed a layout modified instead, then we'd just slap the Fullscreen layout mod on top of the floating modified and everything would just work. With things as they are now, we can sure save the original float position in some extensible state in EwmhDesktops, but then any manual fullscreening or moving will result in weirdness as that will bypass this EwmhDesktops state tracking. (And I'm saying this as someone who would actually love to have this fixed, including being able to manually fullscreen floating windows and then have them go back to where they were.)
That being said, maybe it's still worth it? A simple extensible state with M.Map Window RationalRect
for saving the original floating state (if the window is tiling, save the state by ensuring the Window is not in the map). If we export this and a couple helpers, I could then wire this into my toggleFullscreen
and have the desired behaviour.
Oh and it seems there already is something similar: XMonad.Util.PositionStore, XMonad.Hooks.PositionStoreHooks, XMonad.Layout.PositionStoreFloat. XMonad.Util.PositionStore implements the extensible state. The rest implements layout-based floating, which (afaik) unfortunately needs decorations for moving windows, so that's not something that is widely used I'm afraid. Also not sure if it's okay to wire XMonad.Util.PositionStore into EwmhDesktops. It's definitely something one can play with, but it's a bit more difficult when compatibility with existing users' setups should be kept. :-/
But! Maybe we can add some fullscreen/unfullscreen hooks to #399, which would then enable users to customize the behaviour, other module authors to add integrations with EwmhDesktops, and so on. That seems like something I can experiment with, even exploit as a motivation to get back to #399. :-)
Dwm handles this by saving the previous state, height, width and cords of a window, and when getting back from fullscreen it just restores those values. It should be possible to do this with xmonad, but haskell still looks like a alien language to me.
If the stackset doesn't change, then "simply sinking the window" does restore its original position. When I fullscreen a tiled window and then unfullscreen it, everything is back to where it was. If the window is moved in between, then the stackset is changed and when it sinks, it sinks into the master position or something, but I'd argue that stackset changing during fullscreen isn't all that likely.
Oh, well TIL then, thanks! Maybe this looks how much I value floating windows in general :>
Dwm handles this by saving the previous state, height, width and cords of a window, and when getting back from fullscreen it just restores those values. It should be possible to do this with xmonad, but haskell still looks like a alien language to me.
Yes this was basically the idea here:
That being said, maybe it's still worth it? A simple extensible state with M.Map Window RationalRect for saving the original floating state (if the window is tiling, save the state by ensuring the Window is not in the map). If we export this and a couple helpers, I could then wire this into my toggleFullscreen and have the desired behaviour.
I have to say that wiring something into #399 sounds pretty awesome to me (if only because then that gets worked on and the last real blocker for 0.17 vanishes :>)
Yeah, it all seems to fit into the puzzle. With (un)fullscreen hooks in EwmhDesktop, even X.L.Fullscreen can hook into it and make the two cooperate cleanly. That might be a considerable win. I'm excited. :-)
what do other people think?
I think the floating window should remain floating. The fact that it becomes tiling is not intuitive. But, as far as I understand, it is not so easy to implement now :).
Not that difficult, either: remember its state in XS on entering fullscreen, use saved state to put it back floating or tiled afterward, include an extra hook for delete window to clean up the state if it's closed while still fullscreen. The truly difficult one would be trying to remember its exact state in the tile, since it'd be dependent on the layout in question and might change.
I'd advice using the layout modifiers in XMonad.Layout.Fullscreen instead if you want this behavior.