Switch Shrink and Expand based on REFLECTX

Viewed 79

I am using XMonad.Layout.Reflect together with XMonad.Layout.MultiToggle to flip my layout left-right when needed. However, when any layout is reflected, my keybinds for shrinking and expanding the layout, eg.

...

((modm,  xK_h), sendMessage Shrink),
((modm,  xK_l), sendMessage Expand),

...

behaves as they are inversed.

So, what I want is a way to remap my keys, or maybe use a function instead of sendMessage that somehow detects the state of the layout and chooses Shrink/Expand depending on that.

Now I know that checking eg. global state variables (of which there are no such thing I guess) is not very Haskelly, so I am at a little bit of a loss on how to do this. I've considered XMonad.Actions.PerWorkspaceKeys, but it seems to do a match against the entire Workspace name. Another route could be to add/delete keybinds in defaultConfig, but again - I'm not sure this is even doable (it seems messy anyways).

Any ideas on how to approach this anyone? I know Haskell on the level of having read the "Learn you a Haskell..." book from beginning to end and making smallish programs based on that.

1 Answers

One way to do it is using the layout description to find out whether it has been reflected, following this blog post by Thomas Churchman:

import qualified XMonad.StackSet as S
import Data.List (isInfixOf)

getActiveLayoutDescription :: X String
getActiveLayoutDescription = do
    workspaces <- gets windowset
    return $ description . S.layout . S.workspace . S.current $ workspaces

The key bindings would then look like this:

((modm,  xK_h), do
    layoutDesc <- getActiveLayoutDescription
    if "ReflectX" `isInfixOf` layoutDesc
        then sendMessage Expand
        else sendMessage Shrink
,
((modm,  xK_l), do
    layoutDesc <- getActiveLayoutDescription
    if "ReflectX" `isInfixOf` layoutDesc
        then sendMessage Shrink
        else sendMessage Expand
    ),

Side notes:

my keybinds for shrinking and expanding the layout [...] behaves as they are inversed.

While what you want to do makes perfect sense, it is worth mentioning that this behaviour happens because reflecting a layout will also reflect the position of the master pane. Since Shrink and Expand act on the master pane, they will appear to be inverted, as far as absolute horizontal coordinates go, if you are using a layout like Tall, in which the master pane is on the left of the screen. Different layouts might be affected differently.

Now I know that checking eg. global state variables (of which there are no such thing I guess) is not very Haskelly, so I am at a little bit of a loss on how to do this.

This approach is not unthinkable, and XMonad.Util.ExtensibleState is meant for setting up this sort of thing. In this case, though, I feel using a stateful flag is be way more trouble than it's worth.

Related