aboutsummaryrefslogtreecommitdiffstats
path: root/Operations.hs
diff options
context:
space:
mode:
authorDon Stewart <dons@cse.unsw.edu.au>2007-05-04 10:16:49 +0200
committerDon Stewart <dons@cse.unsw.edu.au>2007-05-04 10:16:49 +0200
commitba6e32758d41f1117fc125b32008c2f411eec8b1 (patch)
tree5eb85dcf427ef8a924fe45d4feb2a61c24ca156b /Operations.hs
parent2a59314ffa3997b6365bf2130ef8df0e0bc0185d (diff)
downloadxmonad-ba6e32758d41f1117fc125b32008c2f411eec8b1.tar.gz
xmonad-ba6e32758d41f1117fc125b32008c2f411eec8b1.tar.xz
xmonad-ba6e32758d41f1117fc125b32008c2f411eec8b1.zip
Constrain layout messages to be members of a Message class
Using Typeables as the only constraint on layout messages is a bit scary, as a user can send arbitrary values to layoutMsg, whether they make sense or not: there's basically no type feedback on the values you supply to layoutMsg. Folloing Simon Marlow's dynamically extensible exceptions paper, we use an existential type, and a Message type class, to constrain valid arguments to layoutMsg to be valid members of Message. That is, a user writes some data type for messages their layout algorithm accepts: data MyLayoutEvent darcs-hash:20070504081649-9c5c1-954b406e8c21c2ca4428960e4fc1f9ffb17fb296.gz
Diffstat (limited to 'Operations.hs')
-rw-r--r--Operations.hs44
1 files changed, 24 insertions, 20 deletions
diff --git a/Operations.hs b/Operations.hs
index 73e3c1d..c90ff09 100644
--- a/Operations.hs
+++ b/Operations.hs
@@ -16,7 +16,6 @@ module Operations where
import Data.List
import Data.Maybe
import Data.Bits
-import Data.Dynamic ( Typeable, toDyn, fromDynamic )
import qualified Data.Map as M
import Control.Monad.State
@@ -73,41 +72,46 @@ clearEnterEvents = do
-- uppermost.
--
switchLayout :: X ()
-switchLayout = layout (\(x, xs) -> let xs' = xs ++ [x]
- in (head xs', tail xs'))
+switchLayout = layout (\(x, xs) -> let xs' = xs ++ [x] in (head xs', tail xs'))
+-- | Throw an (extensible) message value to the current Layout scheme,
+-- possibly modifying how we layout the windows, then refresh.
--
--- TODO, using Typeable for extensible stuff is a bit gunky. Check --
--- 'extensible exceptions' paper for other ideas.
+-- TODO, this will refresh on Nothing.
--
--- Basically this thing specifies the basic operations that vary between
--- layouts.
---
-data ShrinkOrExpand = Shrink | Expand deriving (Typeable, Eq)
-
-layoutMsg :: Typeable a => a -> X () -- FIXME: The below shouldn't refresh on Nothing
-layoutMsg a = layout $ \x@(l, ls) -> maybe x (flip (,) ls) (modifyLayout l (toDyn a))
+sendMessage :: Message a => a -> X ()
+sendMessage a = layout $ \x@(l, ls) -> maybe x (flip (,) ls) (modifyLayout l (SomeMessage a))
+------------------------------------------------------------------------
--
--- Standard layout algorithms:
+-- Builtin layout algorithms:
--
-- fullscreen mode
-- tall mode
-- wide mode
+--
+-- The latter algorithms support the following operations:
+--
+-- Shrink
+-- Expand
--
-full :: Layout
-tall, wide :: Rational -> Rational -> Layout
-full = Layout { doLayout = \sc ws -> [ (w,sc) | w <- ws ]
- , modifyLayout = const Nothing }
+data Resize = Shrink | Expand deriving (Typeable, Show)
+instance Message Resize
+full :: Layout
+full = Layout { doLayout = \sc ws -> [ (w,sc) | w <- ws ]
+ , modifyLayout = const Nothing } -- no changes
+
+tall, wide :: Rational -> Rational -> Layout
wide delta frac = mirrorLayout (tall delta frac)
tall delta frac = Layout { doLayout = tile frac
- , modifyLayout = fmap f . fromDynamic }
+ , modifyLayout = fmap handler . fromMessage }
- where f s = tall delta ((op s) frac delta)
- op Shrink = (-) ; op Expand = (+)
+ where handler s = tall delta $ (case s of
+ Shrink -> (-)
+ Expand -> (+)) frac delta
-- | Mirror a rectangle
mirrorRect :: Rectangle -> Rectangle