Bläddra i källkod

`XMonad.Operations`

 * Add `windowBracket`: provide a means of handling windowset changes
   made during the course of arbitrary `X` actions. Buys composability.
 * Add `windowBracket_` variant.
 * Add `modifyWindowSet` utility for use with the above.
 * Re-implement `sendMessage` using `windowBracket_` so that its refresh
   handles changes made to the windowset by the message handler.
master
L. S. Leary 11 månader sedan
förälder
incheckning
0614ffb65c
1 ändrade filer med 25 tillägg och 3 borttagningar
  1. 25
    3
      src/XMonad/Operations.hs

+ 25
- 3
src/XMonad/Operations.hs Visa fil

@@ -21,7 +21,7 @@ import XMonad.Layout (Full(..))
21 21
 import qualified XMonad.StackSet as W
22 22
 
23 23
 import Data.Maybe
24
-import Data.Monoid          (Endo(..))
24
+import Data.Monoid          (Endo(..),Any(..))
25 25
 import Data.List            (nub, (\\), find)
26 26
 import Data.Bits            ((.|.), (.&.), complement, testBit)
27 27
 import Data.Ratio
@@ -30,6 +30,7 @@ import qualified Data.Set as S
30 30
 
31 31
 import Control.Applicative((<$>), (<*>))
32 32
 import Control.Arrow (second)
33
+import Control.Monad (void)
33 34
 import Control.Monad.Reader
34 35
 import Control.Monad.State
35 36
 import qualified Control.Exception.Extensible as C
@@ -176,6 +177,25 @@ windows f = do
176 177
     unless isMouseFocused $ clearEvents enterWindowMask
177 178
     asks (logHook . config) >>= userCodeDef ()
178 179
 
180
+-- | Modify the @WindowSet@ in state with no special handling.
181
+modifyWindowSet :: (WindowSet -> WindowSet) -> X ()
182
+modifyWindowSet f = modify $ \xst -> xst { windowset = f (windowset xst) }
183
+
184
+-- | Perform an @X@ action and check its return value against a predicate p.
185
+-- If p holds, unwind changes to the @WindowSet@ and replay them using @windows@.
186
+windowBracket :: (a -> Bool) -> X a -> X a
187
+windowBracket p action = withWindowSet $ \old -> do
188
+  a <- action
189
+  when (p a) . withWindowSet $ \new -> do
190
+    modifyWindowSet $ \_ -> old
191
+    windows         $ \_ -> new
192
+  return a
193
+
194
+-- | A version of @windowBracket@ that discards the return value, and handles an
195
+-- @X@ action reporting its need for refresh via @Any@.
196
+windowBracket_ :: X Any -> X ()
197
+windowBracket_ = void . windowBracket getAny
198
+
179 199
 -- | Produce the actual rectangle from a screen and a ratio on that screen.
180 200
 scaleRationalRect :: Rectangle -> W.RationalRect -> Rectangle
181 201
 scaleRationalRect (Rectangle sx sy sw sh) (W.RationalRect rx ry rw rh)
@@ -371,15 +391,16 @@ setFocusX w = withWindowSet $ \ws -> do
371 391
 -- Message handling
372 392
 
373 393
 -- | Throw a message to the current 'LayoutClass' possibly modifying how we
394
+-- layout the windows, in which case changes are handled through a refresh.
374 395
 sendMessage :: Message a => a -> X ()
375
-sendMessage a = do
396
+sendMessage a = windowBracket_ $ do
376 397
     w <- W.workspace . W.current <$> gets windowset
377 398
     ml' <- handleMessage (W.layout w) (SomeMessage a) `catchX` return Nothing
378 399
     whenJust ml' $ \l' ->
379
-        windows $ \ws -> ws { W.current = (W.current ws)
400
+        modifyWindowSet $ \ws -> ws { W.current = (W.current ws)
380 401
                                 { W.workspace = (W.workspace $ W.current ws)
381 402
                                   { W.layout = l' }}}
403
+    return (Any $ isJust ml')
382 404
 
383 405
 -- | Send a message to all layouts, without refreshing.
384 406
 broadcastMessage :: Message a => a -> X ()

Laddar…
Avbryt
Spara