Search code examples
haskellxmonad

Is it possible to toggle XMonad.Hooks.EwmhDesktops.fullscreenEventHook?


Im using Xmonad as a window manager. To automatically handle fullscreen window i use XMonad.Hooks.EwmhDesktops.fullscreenEventHook. And put this in my config:

        , handleEventHook = handleEventHook def <+> docksEventHook <+> XMonad.Hooks.EwmhDesktops.fullscreenEventHook 

I would like the ability to toggle this with a keybind. So by default the fullscreen window takes up the entire screen, but when i toggle EwmhDesktops.fullscreenEventHook off it is only fullscreen in the "tiled" space the window takes up.

Full config is here


Solution

  • It's very hard to add state into XMonad itself, so we'll have to use IORef for external state. First, we'll make a fullscreen event hook that checks a boolean from an IORef and only runs the actual event hook if it's true:

    toggleableFullscreen :: IORef Bool -> Event -> X All
    toggleableFullscreen ref evt =
        io (readIORef ref) >>= \isOn ->
            if isOn
                then XMonad.Hooks.EwmhDesktops.fullscreenEventHook evt
                else return (All True)
    

    This uses io :: IO a -> X a to lift an IO monad into an X monad. Now, in our main function, we want to construct the IORef with newIORef:

    main = do
        fullscreenRef <- newIORef True -- default to being on
        -- rest of main goes here
    

    Now, we'll also edit the handleEventHook line of main to use our toggleableFullscreen with the fullscreenRef passed in:

    , handleEventHook = handleEventHook def <+> docksEventHook <+> toggleableFullscreen fullscreenRef
    

    So, that's the event hook part done. Now we need a way to toggle it. The myKeys function needs to take in the fullscreenRef as a parameter as well, so you have to add it in:

    myKeys fullscreenRef conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
        -- rest of myKeys
    

    (this is on line 125 of your config)

    Then, you have to add a new keybinding (let's say mod+shift+f) that toggles the IORef using modifyIORef:

    , ((modm .|. shiftMask, xK_f), io (modifyIORef fullscreenRef not))
    

    Then, in your main function, pass fullscreenRef into myKeys:

    , keys = myKeys fullscreenRef
    

    (line 400)

    And remove this entire chunk since you don't use it (and it won't typecheck):

    defaults = def {
          -- simple stuff
            terminal           = myTerminal,
            focusFollowsMouse  = myFocusFollowsMouse,
            clickJustFocuses   = myClickJustFocuses,
            borderWidth        = myBorderWidth,
            modMask            = myModMask,
            workspaces         = myWorkspaces,
            normalBorderColor  = myNormalBorderColor,
            focusedBorderColor = myFocusedBorderColor,
    
          -- key bindings
            keys               = myKeys,
            mouseBindings      = myMouseBindings,
    
          -- hooks, layouts
            layoutHook         = myLayout,
            manageHook         = myManageHook,
            handleEventHook    = myEventHook,
            logHook            = myLogHook,
            startupHook        = myStartupHook
        }
    

    (lines 446-467)

    Then, restart xmonad and you should be able to toggle your fullscreen event hook with mod+shift+f.