Wheat Wizard
Wheat Wizard

Reputation: 4219

How can I modify the windowSet in XMonad?

I have a function that looks like:

sinkFocus :: StackSet i l a s sd -> Maybe (StackSet i l a s sd)
sinkFocus = (fmap . flip sink) <*> peek

However I would like an X () so that I can use it. For example additionalKeys uses an X ().

The documentation says that X is a IO with some state and reader transformers, so I am under the impression that the StackSet is contained within the state of X. So in theory it should be possible to modify the relevant part of the state. However the state accessible is XState not the StackState I want, so I need to be able to turn my function on StackState to one on XState.

This would be easy enough if I had a function of the type

(StackSet i l a s sd -> StackSet i l a s sd) -> X ()

However after digging around in the documentation I haven't been able to piece together a way to do this yet. Is there a way to take a function on StackSet and make an X () that performs that function?

Upvotes: 1

Views: 337

Answers (1)

Wheat Wizard
Wheat Wizard

Reputation: 4219

The X monad has an instance of MonadState

instance MonadState XState X

So we can use modify as

modify :: (XState -> XState) -> X ()

So we need to turn out function to one on XStates. And if we look at the definition

XState
    windowset :: !WindowSet
    mapped :: !(Set Window)
    waitingUnmap :: !(Map Window Int)
    dragging :: !(Maybe (Position -> Position -> X (), X ())) 
    numberlockMask :: !KeyMask
    extensibleState :: !(Map String (Either String StateExtension))

we will see WindowSet which is a type alias for a particular StackState. So you can turn a function from StackStates into one on XStates like so:

overWindowSet :: (WindowSet -> WindowSet) -> XState -> XState
overWindowSet f xState = xState { windowset = f (windowset xState) }

This can be combined with modify to make the complete function you would like:

modify . overWindowSet

Upvotes: 2

Related Questions