packages feed

xmonad-contrib 0.8.1 → 0.9

raw patch · 171 files changed

+11401/−2514 lines, 171 filesdep ~X11dep ~xmonadPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: X11, xmonad

API changes (from Hackage documentation)

- XMonad.Actions.CycleWS: data WSDirection
- XMonad.Actions.MouseGestures: data Direction
- XMonad.Actions.SwapWorkspaces: data WSDirection
- XMonad.Actions.WindowNavigation: data Direction
- XMonad.Config.PlainConfig: checkConfig :: IO Bool
- XMonad.Config.PlainConfig: instance Error [(Integer, String)]
- XMonad.Config.PlainConfig: instance Read Property
- XMonad.Config.PlainConfig: instance Show Property
- XMonad.Config.PlainConfig: plainConfig :: IO ()
- XMonad.Config.PlainConfig: readConfig :: IO (Maybe (XConfig Layout))
- XMonad.Hooks.DynamicLog: dynamicLogDzen :: X ()
- XMonad.Hooks.DynamicLog: dynamicLogXmobar :: X ()
- XMonad.Hooks.EventHook: class (Read eh, Show eh) => EventHook eh
- XMonad.Hooks.EventHook: data HandleEvent eh l a
- XMonad.Hooks.EventHook: eventHook :: (EventHook eh) => eh -> l a -> (HandleEvent eh l) a
- XMonad.Hooks.EventHook: handleEvent :: (EventHook eh) => eh -> Event -> X ()
- XMonad.Hooks.EventHook: instance (EventHook eh, LayoutClass l a) => LayoutClass (HandleEvent eh l) a
- XMonad.Hooks.EventHook: instance (Read eh, Read (l a)) => Read (HandleEvent eh l a)
- XMonad.Hooks.EventHook: instance (Show eh, Show (l a)) => Show (HandleEvent eh l a)
- XMonad.Hooks.EventHook: instance Message EventHandleMsg
- XMonad.Hooks.EventHook: instance Typeable EventHandleMsg
- XMonad.Hooks.EwmhDesktops: data EwmhDesktopsHook
- XMonad.Hooks.EwmhDesktops: ewmhDesktopsLayout :: layout a -> HandleEvent EwmhDesktopsHook layout a
- XMonad.Hooks.EwmhDesktops: instance EventHook EwmhDesktopsHook
- XMonad.Hooks.EwmhDesktops: instance Read EwmhDesktopsHook
- XMonad.Hooks.EwmhDesktops: instance Show EwmhDesktopsHook
- XMonad.Hooks.ManageDocks: D :: Direction
- XMonad.Hooks.ManageDocks: L :: Direction
- XMonad.Hooks.ManageDocks: R :: Direction
- XMonad.Hooks.ManageDocks: U :: Direction
- XMonad.Hooks.ManageDocks: data Direction
- XMonad.Hooks.ManageDocks: instance Bounded Direction
- XMonad.Hooks.ManageDocks: instance Enum Direction
- XMonad.Hooks.ManageDocks: instance Eq Direction
- XMonad.Hooks.ManageDocks: instance Ord Direction
- XMonad.Hooks.ManageDocks: instance Read Direction
- XMonad.Hooks.ManageDocks: instance Show Direction
- XMonad.Hooks.ServerMode: eventHook :: (EventHook eh) => eh -> l a -> (HandleEvent eh l) a
- XMonad.Hooks.ServerMode: instance EventHook ServerMode
- XMonad.Hooks.UrgencyHook: instance (UrgencyHook h) => EventHook (WithUrgencyHook h)
- XMonad.Layout.BoringWindows: instance Read (BoringWindows a)
- XMonad.Layout.BoringWindows: instance Show (BoringWindows a)
- XMonad.Layout.Gaps: data Direction
- XMonad.Layout.LayoutCombinators: instance Message NoWrap
- XMonad.Layout.LayoutCombinators: instance Read NoWrap
- XMonad.Layout.LayoutCombinators: instance Show NoWrap
- XMonad.Layout.LayoutCombinators: instance Typeable NoWrap
- XMonad.Layout.LayoutModifier: emptyLayoutMod :: (LayoutModifier m a) => m a -> Rectangle -> [(a, Rectangle)] -> X ([(a, Rectangle)], Maybe (m a))
- XMonad.Layout.Master: data Master l a
- XMonad.Layout.Master: instance (Eq (l a)) => Eq (Master l a)
- XMonad.Layout.Master: instance (LayoutClass l Window) => LayoutClass (Master l) Window
- XMonad.Layout.Master: instance (Ord (l a)) => Ord (Master l a)
- XMonad.Layout.Master: instance (Read (l a)) => Read (Master l a)
- XMonad.Layout.Master: instance (Show (l a)) => Show (Master l a)
- XMonad.Layout.NoBorders: instance (Read a) => Read (SmartBorder a)
- XMonad.Layout.NoBorders: instance (Show a) => Show (SmartBorder a)
- XMonad.Layout.NoBorders: instance LayoutModifier SmartBorder Window
- XMonad.Layout.WindowNavigation: data Direction
- XMonad.Layout.WindowNavigation: instance Read Navigate
- XMonad.Layout.WindowNavigation: instance Show Navigate
- XMonad.Prompt: instance Eq Direction
- XMonad.Prompt: instance Eq History
- XMonad.Prompt: instance Read Direction
- XMonad.Prompt: instance Read History
- XMonad.Prompt: instance Read XPConfig
- XMonad.Prompt: instance Show Direction
- XMonad.Prompt: instance Show History
- XMonad.Prompt: instance Show XPConfig
+ XMonad.Actions.CopyWindow: runOrCopy :: String -> Query Bool -> X ()
+ XMonad.Actions.CopyWindow: wsContainingCopies :: X [WorkspaceId]
+ XMonad.Actions.CycleWS: HiddenWS :: WSType
+ XMonad.Actions.CycleWS: data Direction1D
+ XMonad.Actions.CycleWS: skipTags :: (Eq i) => [Workspace i l a] -> [i] -> [Workspace i l a]
+ XMonad.Actions.CycleWS: toggleOrDoSkip :: [WorkspaceId] -> (WorkspaceId -> WindowSet -> WindowSet) -> WorkspaceId -> X ()
+ XMonad.Actions.CycleWS: toggleOrView :: WorkspaceId -> X ()
+ XMonad.Actions.CycleWindows: cycleRecentWindows :: [KeySym] -> KeySym -> KeySym -> X ()
+ XMonad.Actions.CycleWindows: cycleStacks' :: (Stack Window -> [Stack Window]) -> [KeySym] -> KeySym -> KeySym -> X ()
+ XMonad.Actions.CycleWindows: rotDown :: [a] -> [a]
+ XMonad.Actions.CycleWindows: rotFocused' :: ([a] -> [a]) -> Stack a -> Stack a
+ XMonad.Actions.CycleWindows: rotFocusedDown :: X ()
+ XMonad.Actions.CycleWindows: rotFocusedUp :: X ()
+ XMonad.Actions.CycleWindows: rotOpposite :: X ()
+ XMonad.Actions.CycleWindows: rotOpposite' :: Stack a -> Stack a
+ XMonad.Actions.CycleWindows: rotUnfocused' :: ([a] -> [a]) -> Stack a -> Stack a
+ XMonad.Actions.CycleWindows: rotUnfocusedDown :: X ()
+ XMonad.Actions.CycleWindows: rotUnfocusedUp :: X ()
+ XMonad.Actions.CycleWindows: rotUp :: [a] -> [a]
+ XMonad.Actions.CycleWindows: shiftToFocus' :: (Eq a, Show a, Read a) => a -> Stack a -> Stack a
+ XMonad.Actions.FlexibleResize: mouseResizeEdgeWindow :: Rational -> Window -> X ()
+ XMonad.Actions.FloatSnap: D :: Direction2D
+ XMonad.Actions.FloatSnap: L :: Direction2D
+ XMonad.Actions.FloatSnap: R :: Direction2D
+ XMonad.Actions.FloatSnap: U :: Direction2D
+ XMonad.Actions.FloatSnap: data Direction2D
+ XMonad.Actions.FloatSnap: snapGrow :: Direction2D -> Maybe Int -> Window -> X ()
+ XMonad.Actions.FloatSnap: snapMagicMouseResize :: Rational -> Maybe Int -> Maybe Int -> Window -> X ()
+ XMonad.Actions.FloatSnap: snapMagicMove :: Maybe Int -> Maybe Int -> Window -> X ()
+ XMonad.Actions.FloatSnap: snapMagicResize :: [Direction2D] -> Maybe Int -> Maybe Int -> Window -> X ()
+ XMonad.Actions.FloatSnap: snapMove :: Direction2D -> Maybe Int -> Window -> X ()
+ XMonad.Actions.FloatSnap: snapShrink :: Direction2D -> Maybe Int -> Window -> X ()
+ XMonad.Actions.FocusNth: focusNth' :: Int -> Stack a -> Stack a
+ XMonad.Actions.GridSelect: GSConfig :: Integer -> Integer -> Integer -> (a -> Bool -> X (String, String)) -> String -> NavigateMap -> Double -> Double -> GSConfig a
+ XMonad.Actions.GridSelect: bringSelected :: GSConfig Window -> X ()
+ XMonad.Actions.GridSelect: buildDefaultGSConfig :: (a -> Bool -> X (String, String)) -> GSConfig a
+ XMonad.Actions.GridSelect: class HasColorizer a
+ XMonad.Actions.GridSelect: colorRangeFromClassName :: (Word8, Word8, Word8) -> (Word8, Word8, Word8) -> (Word8, Word8, Word8) -> (Word8, Word8, Word8) -> (Word8, Word8, Word8) -> Window -> Bool -> X (String, String)
+ XMonad.Actions.GridSelect: data GSConfig a
+ XMonad.Actions.GridSelect: defaultColorizer :: (HasColorizer a) => a -> Bool -> X (String, String)
+ XMonad.Actions.GridSelect: defaultGSConfig :: (HasColorizer a) => GSConfig a
+ XMonad.Actions.GridSelect: fromClassName :: Window -> Bool -> X (String, String)
+ XMonad.Actions.GridSelect: goToSelected :: GSConfig Window -> X ()
+ XMonad.Actions.GridSelect: gridselect :: GSConfig a -> [(String, a)] -> X (Maybe a)
+ XMonad.Actions.GridSelect: gridselectWindow :: GSConfig Window -> X (Maybe Window)
+ XMonad.Actions.GridSelect: gs_cellheight :: GSConfig a -> Integer
+ XMonad.Actions.GridSelect: gs_cellpadding :: GSConfig a -> Integer
+ XMonad.Actions.GridSelect: gs_cellwidth :: GSConfig a -> Integer
+ XMonad.Actions.GridSelect: gs_colorizer :: GSConfig a -> a -> Bool -> X (String, String)
+ XMonad.Actions.GridSelect: gs_font :: GSConfig a -> String
+ XMonad.Actions.GridSelect: gs_navigate :: GSConfig a -> NavigateMap
+ XMonad.Actions.GridSelect: gs_originFractX :: GSConfig a -> Double
+ XMonad.Actions.GridSelect: gs_originFractY :: GSConfig a -> Double
+ XMonad.Actions.GridSelect: instance [overlap ok] Applicative (TwoD a)
+ XMonad.Actions.GridSelect: instance [overlap ok] Functor (TwoD a)
+ XMonad.Actions.GridSelect: instance [overlap ok] HasColorizer String
+ XMonad.Actions.GridSelect: instance [overlap ok] HasColorizer Window
+ XMonad.Actions.GridSelect: instance [overlap ok] HasColorizer a
+ XMonad.Actions.GridSelect: instance [overlap ok] Monad (TwoD a)
+ XMonad.Actions.GridSelect: instance [overlap ok] MonadState (TwoDState a) (TwoD a)
+ XMonad.Actions.GridSelect: runSelectedAction :: GSConfig (X ()) -> [(String, X ())] -> X ()
+ XMonad.Actions.GridSelect: spawnSelected :: GSConfig String -> [String] -> X ()
+ XMonad.Actions.GridSelect: stringColorizer :: String -> Bool -> X (String, String)
+ XMonad.Actions.GridSelect: type NavigateMap = Map (KeyMask, KeySym) (TwoDPosition -> TwoDPosition)
+ XMonad.Actions.GridSelect: type TwoDPosition = (Integer, Integer)
+ XMonad.Actions.GridSelect: withSelectedWindow :: (Window -> X ()) -> GSConfig Window -> X ()
+ XMonad.Actions.MessageFeedback: send :: (Message a) => a -> X Bool
+ XMonad.Actions.MessageFeedback: sendSM :: SomeMessage -> X Bool
+ XMonad.Actions.MessageFeedback: sendSM_ :: SomeMessage -> X ()
+ XMonad.Actions.MessageFeedback: sm :: (Message a) => a -> SomeMessage
+ XMonad.Actions.MessageFeedback: tryInOrder :: [SomeMessage] -> X Bool
+ XMonad.Actions.MessageFeedback: tryInOrder_ :: [SomeMessage] -> X ()
+ XMonad.Actions.MessageFeedback: tryMessage :: (Message a, Message b) => a -> b -> X Bool
+ XMonad.Actions.MessageFeedback: tryMessage_ :: (Message a, Message b) => a -> b -> X ()
+ XMonad.Actions.MouseGestures: data Direction2D
+ XMonad.Actions.OnScreen: greedyViewOnScreen :: (Eq sid, Eq i) => sid -> i -> StackSet i l a sid sd -> StackSet i l a sid sd
+ XMonad.Actions.OnScreen: onScreen :: (Eq sid, Eq i) => (i -> StackSet i l a sid sd -> StackSet i l a sid sd) -> sid -> i -> StackSet i l a sid sd -> StackSet i l a sid sd
+ XMonad.Actions.OnScreen: onlyOnScreen :: (Eq sid, Eq i) => sid -> i -> StackSet i l a sid sd -> StackSet i l a sid sd
+ XMonad.Actions.OnScreen: viewOnScreen :: (Eq sid, Eq i) => sid -> i -> StackSet i l a sid sd -> StackSet i l a sid sd
+ XMonad.Actions.PhysicalScreens: P :: Int -> PhysicalScreen
+ XMonad.Actions.PhysicalScreens: getScreen :: PhysicalScreen -> X (Maybe ScreenId)
+ XMonad.Actions.PhysicalScreens: instance Enum PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Eq PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Integral PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Num PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Ord PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Read PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Real PhysicalScreen
+ XMonad.Actions.PhysicalScreens: instance Show PhysicalScreen
+ XMonad.Actions.PhysicalScreens: newtype PhysicalScreen
+ XMonad.Actions.PhysicalScreens: sendToScreen :: PhysicalScreen -> X ()
+ XMonad.Actions.PhysicalScreens: viewScreen :: PhysicalScreen -> X ()
+ XMonad.Actions.Plane: planeKeys :: KeyMask -> Lines -> Limits -> Map (KeyMask, KeySym) (X ())
+ XMonad.Actions.RandomBackground: HSV :: Double -> Double -> RandomColor
+ XMonad.Actions.RandomBackground: RGB :: Int -> Int -> RandomColor
+ XMonad.Actions.RandomBackground: data RandomColor
+ XMonad.Actions.RandomBackground: randomBg :: RandomColor -> X ()
+ XMonad.Actions.RandomBackground: randomBg' :: (MonadIO m) => RandomColor -> m String
+ XMonad.Actions.Search: (!>) :: SearchEngine -> SearchEngine -> SearchEngine
+ XMonad.Actions.Search: alpha :: SearchEngine
+ XMonad.Actions.Search: deb :: SearchEngine
+ XMonad.Actions.Search: debbts :: SearchEngine
+ XMonad.Actions.Search: debpts :: SearchEngine
+ XMonad.Actions.Search: escape :: String -> String
+ XMonad.Actions.Search: hackage :: SearchEngine
+ XMonad.Actions.Search: images :: SearchEngine
+ XMonad.Actions.Search: intelligent :: SearchEngine -> SearchEngine
+ XMonad.Actions.Search: isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
+ XMonad.Actions.Search: isohunt :: SearchEngine
+ XMonad.Actions.Search: lucky :: SearchEngine
+ XMonad.Actions.Search: multi :: SearchEngine
+ XMonad.Actions.Search: namedEngine :: Name -> SearchEngine -> SearchEngine
+ XMonad.Actions.Search: prefixAware :: SearchEngine -> SearchEngine
+ XMonad.Actions.Search: searchEngineF :: Name -> Site -> SearchEngine
+ XMonad.Actions.Search: use :: SearchEngine -> Site
+ XMonad.Actions.Search: wiktionary :: SearchEngine
+ XMonad.Actions.SpawnOn: data Spawner
+ XMonad.Actions.SpawnOn: manageSpawn :: Spawner -> ManageHook
+ XMonad.Actions.SpawnOn: mkSpawner :: (Functor m, MonadIO m) => m Spawner
+ XMonad.Actions.SpawnOn: shellPromptHere :: Spawner -> XPConfig -> X ()
+ XMonad.Actions.SpawnOn: shellPromptOn :: Spawner -> WorkspaceId -> XPConfig -> X ()
+ XMonad.Actions.SpawnOn: spawnAndDo :: Spawner -> ManageHook -> String -> X ()
+ XMonad.Actions.SpawnOn: spawnHere :: Spawner -> String -> X ()
+ XMonad.Actions.SpawnOn: spawnOn :: Spawner -> WorkspaceId -> String -> X ()
+ XMonad.Actions.Submap: submapDefault :: X () -> Map (KeyMask, KeySym) (X ()) -> X ()
+ XMonad.Actions.SwapWorkspaces: data Direction1D
+ XMonad.Actions.TopicSpace: (>*>) :: (Monad m) => m a -> Int -> m ()
+ XMonad.Actions.TopicSpace: TopicConfig :: Map Topic Dir -> Map Topic (X ()) -> (Topic -> X ()) -> Topic -> Int -> TopicConfig
+ XMonad.Actions.TopicSpace: checkTopicConfig :: [Topic] -> TopicConfig -> IO ()
+ XMonad.Actions.TopicSpace: currentTopicAction :: TopicConfig -> X ()
+ XMonad.Actions.TopicSpace: currentTopicDir :: TopicConfig -> X String
+ XMonad.Actions.TopicSpace: data TopicConfig
+ XMonad.Actions.TopicSpace: defaultTopic :: TopicConfig -> Topic
+ XMonad.Actions.TopicSpace: defaultTopicAction :: TopicConfig -> Topic -> X ()
+ XMonad.Actions.TopicSpace: getLastFocusedTopics :: X [String]
+ XMonad.Actions.TopicSpace: maxTopicHistory :: TopicConfig -> Int
+ XMonad.Actions.TopicSpace: pprWindowSet :: TopicConfig -> PP -> X String
+ XMonad.Actions.TopicSpace: setLastFocusedTopic :: TopicConfig -> Topic -> (Topic -> Bool) -> X ()
+ XMonad.Actions.TopicSpace: shiftNthLastFocused :: Int -> X ()
+ XMonad.Actions.TopicSpace: switchNthLastFocused :: TopicConfig -> Int -> X ()
+ XMonad.Actions.TopicSpace: switchTopic :: TopicConfig -> Topic -> X ()
+ XMonad.Actions.TopicSpace: topicAction :: TopicConfig -> Topic -> X ()
+ XMonad.Actions.TopicSpace: topicActionWithPrompt :: XPConfig -> TopicConfig -> X ()
+ XMonad.Actions.TopicSpace: topicActions :: TopicConfig -> Map Topic (X ())
+ XMonad.Actions.TopicSpace: topicDirs :: TopicConfig -> Map Topic Dir
+ XMonad.Actions.TopicSpace: type Dir = FilePath
+ XMonad.Actions.TopicSpace: type Topic = WorkspaceId
+ XMonad.Actions.UpdateFocus: adjustEventInput :: X ()
+ XMonad.Actions.UpdateFocus: focusOnMouseMove :: Event -> X All
+ XMonad.Actions.UpdatePointer: TowardsCentre :: Rational -> Rational -> PointerPosition
+ XMonad.Actions.UpdatePointer: instance Read PointerPosition
+ XMonad.Actions.UpdatePointer: instance Show PointerPosition
+ XMonad.Actions.Warp: banishScreen :: Corner -> X ()
+ XMonad.Actions.WindowBringer: gotoMenu' :: String -> X ()
+ XMonad.Actions.WindowGo: ifWindow :: Query Bool -> ManageHook -> X () -> X ()
+ XMonad.Actions.WindowGo: ifWindows :: Query Bool -> ([Window] -> X ()) -> X () -> X ()
+ XMonad.Actions.WindowGo: raiseAndDo :: X () -> Query Bool -> (Window -> X ()) -> X ()
+ XMonad.Actions.WindowGo: raiseHook :: ManageHook
+ XMonad.Actions.WindowGo: raiseMaster :: X () -> Query Bool -> X ()
+ XMonad.Actions.WindowGo: runOrRaiseAndDo :: String -> Query Bool -> (Window -> X ()) -> X ()
+ XMonad.Actions.WindowGo: runOrRaiseMaster :: String -> Query Bool -> X ()
+ XMonad.Actions.WindowMenu: windowMenu :: X ()
+ XMonad.Actions.WindowNavigation: data Direction2D
+ XMonad.Actions.WithAll: killAll :: X ()
+ XMonad.Actions.WithAll: sinkAll :: X ()
+ XMonad.Actions.WithAll: withAll :: (Window -> X ()) -> X ()
+ XMonad.Actions.WithAll: withAll' :: (Window -> WindowSet -> WindowSet) -> X ()
+ XMonad.Actions.WorkspaceCursors: data WorkspaceCursors a
+ XMonad.Actions.WorkspaceCursors: focusDepth :: Cursors t -> Int
+ XMonad.Actions.WorkspaceCursors: focusNth' :: Int -> Stack a -> Stack a
+ XMonad.Actions.WorkspaceCursors: getFocus :: Cursors b -> b
+ XMonad.Actions.WorkspaceCursors: instance (Eq a) => Eq (Cursors a)
+ XMonad.Actions.WorkspaceCursors: instance (Read a) => Read (Cursors a)
+ XMonad.Actions.WorkspaceCursors: instance (Show a) => Show (Cursors a)
+ XMonad.Actions.WorkspaceCursors: instance Foldable Cursors
+ XMonad.Actions.WorkspaceCursors: instance Functor Cursors
+ XMonad.Actions.WorkspaceCursors: instance LayoutModifier WorkspaceCursors a
+ XMonad.Actions.WorkspaceCursors: instance Message ChangeCursors
+ XMonad.Actions.WorkspaceCursors: instance Read (WorkspaceCursors a)
+ XMonad.Actions.WorkspaceCursors: instance Show (WorkspaceCursors a)
+ XMonad.Actions.WorkspaceCursors: instance Typeable ChangeCursors
+ XMonad.Actions.WorkspaceCursors: instance Typeable1 Cursors
+ XMonad.Actions.WorkspaceCursors: instance Typeable1 WorkspaceCursors
+ XMonad.Actions.WorkspaceCursors: makeCursors :: [[String]] -> Cursors String
+ XMonad.Actions.WorkspaceCursors: modifyLayer :: (Stack (Cursors String) -> Stack (Cursors String)) -> Int -> X ()
+ XMonad.Actions.WorkspaceCursors: modifyLayer' :: (Stack (Cursors String) -> X (Stack (Cursors String))) -> Int -> X ()
+ XMonad.Actions.WorkspaceCursors: noWrapDown :: Stack t -> Stack t
+ XMonad.Actions.WorkspaceCursors: noWrapUp :: Stack t -> Stack t
+ XMonad.Actions.WorkspaceCursors: shiftLayer :: (Stack (Cursors String) -> Stack (Cursors WorkspaceId)) -> Int -> X ()
+ XMonad.Actions.WorkspaceCursors: shiftModifyLayer :: (Stack (Cursors String) -> Stack (Cursors WorkspaceId)) -> Int -> X ()
+ XMonad.Actions.WorkspaceCursors: toList :: (Foldable t) => t a -> [a]
+ XMonad.Actions.WorkspaceCursors: workspaceCursors :: Cursors String -> l a -> ModifiedLayout WorkspaceCursors l a
+ XMonad.Config.Arossato: arossatoConfig :: IO (XConfig (ModifiedLayout AvoidStruts (NewSelect (ModifiedLayout (Decoration SimpleDecoration DefaultShrinker) (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat))) (NewSelect (ModifiedLayout WithBorder (ModifiedLayout (Decoration TabbedDecoration DefaultShrinker) Simplest)) (ModifiedLayout WindowArranger (NewSelect (ModifiedLayout Magnifier Tall) (NewSelect (ModifiedLayout WithBorder Full) (NewSelect (Mirror Tall) Accordion))))))))
+ XMonad.Config.Azerty: azertyConfig :: XConfig (Choose Tall (Choose (Mirror Tall) Full))
+ XMonad.Config.Azerty: azertyKeys :: XConfig t -> Map (KeyMask, KeySym) (X ())
+ XMonad.Config.Desktop: desktopConfig :: XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full)))
+ XMonad.Config.Desktop: desktopLayoutModifiers :: (LayoutClass l a) => l a -> ModifiedLayout AvoidStruts l a
+ XMonad.Config.Droundy: config :: XConfig (ModifiedLayout ShowWName (ModifiedLayout WorkspaceDir (ModifiedLayout BoringWindows (ModifiedLayout SmartBorder (ModifiedLayout WindowNavigation (ModifiedLayout Magnifier (ToggleLayouts Full (ModifiedLayout AvoidStruts (NewSelect (ModifiedLayout Named (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest)) (NewSelect (ModifiedLayout Named (CombineTwo (DragPane ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (CombineTwo (Square ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest)))) (NewSelect (ModifiedLayout Named (CombineTwo (DragPane ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (CombineTwo (DragPane ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (CombineTwo (Square ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest))))) (ModifiedLayout Named (CombineTwo (DragPane ()) (CombineTwo (DragPane ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest)) (CombineTwo (Square ()) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest) (ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest)))))))))))))))
+ XMonad.Config.Droundy: mytab :: ModifiedLayout (Decoration TabbedDecoration CustomShrink) Simplest Window
+ XMonad.Config.Gnome: gnomeConfig :: XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full)))
+ XMonad.Config.Gnome: gnomeRegister :: (MonadIO m) => m ()
+ XMonad.Config.Kde: kde4Config :: XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full)))
+ XMonad.Config.Kde: kdeConfig :: XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full)))
+ XMonad.Config.Sjanssen: sjanssenConfig :: IO (XConfig (ModifiedLayout SmartBorder (Choose (Choose HintedTile (Choose HintedTile Full)) (ModifiedLayout (Decoration TabbedDecoration DefaultShrinker) Simplest))))
+ XMonad.Config.Sjanssen: sjanssenConfigXmobar :: IO (XConfig (ModifiedLayout AvoidStruts (ModifiedLayout SmartBorder (Choose (Choose HintedTile (Choose HintedTile Full)) (ModifiedLayout (Decoration TabbedDecoration DefaultShrinker) Simplest)))))
+ XMonad.Config.Xfce: xfceConfig :: XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full)))
+ XMonad.Hooks.DynamicLog: dzenStrip :: String -> String
+ XMonad.Hooks.DynamicLog: statusBar :: (LayoutClass l Window) => String -> PP -> (XConfig Layout -> (KeyMask, KeySym)) -> XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))
+ XMonad.Hooks.DynamicLog: trim :: String -> String
+ XMonad.Hooks.DynamicLog: xmobarStrip :: String -> String
+ XMonad.Hooks.EwmhDesktops: ewmh :: XConfig a -> XConfig a
+ XMonad.Hooks.EwmhDesktops: ewmhDesktopsEventHook :: Event -> X All
+ XMonad.Hooks.EwmhDesktops: ewmhDesktopsStartup :: X ()
+ XMonad.Hooks.FadeInactive: fadeIf :: Query Bool -> Rational -> Query Rational
+ XMonad.Hooks.FadeInactive: fadeIn :: Window -> X ()
+ XMonad.Hooks.FadeInactive: fadeOut :: Rational -> Window -> X ()
+ XMonad.Hooks.FadeInactive: fadeOutLogHook :: Query Rational -> X ()
+ XMonad.Hooks.FadeInactive: isUnfocused :: Query Bool
+ XMonad.Hooks.FadeInactive: setOpacity :: Window -> Rational -> X ()
+ XMonad.Hooks.FloatNext: floatAllNew :: Bool -> X ()
+ XMonad.Hooks.FloatNext: floatNext :: Bool -> X ()
+ XMonad.Hooks.FloatNext: floatNextHook :: ManageHook
+ XMonad.Hooks.FloatNext: runLogHook :: X ()
+ XMonad.Hooks.FloatNext: toggleFloatAllNew :: X ()
+ XMonad.Hooks.FloatNext: toggleFloatNext :: X ()
+ XMonad.Hooks.FloatNext: willFloatAllNew :: X Bool
+ XMonad.Hooks.FloatNext: willFloatAllNewPP :: (String -> String) -> X (Maybe String)
+ XMonad.Hooks.FloatNext: willFloatNext :: X Bool
+ XMonad.Hooks.FloatNext: willFloatNextPP :: (String -> String) -> X (Maybe String)
+ XMonad.Hooks.InsertPosition: Above :: Position
+ XMonad.Hooks.InsertPosition: Below :: Position
+ XMonad.Hooks.InsertPosition: End :: Position
+ XMonad.Hooks.InsertPosition: Master :: Position
+ XMonad.Hooks.InsertPosition: Newer :: Focus
+ XMonad.Hooks.InsertPosition: Older :: Focus
+ XMonad.Hooks.InsertPosition: data Focus
+ XMonad.Hooks.InsertPosition: data Position
+ XMonad.Hooks.InsertPosition: insertPosition :: Position -> Focus -> ManageHook
+ XMonad.Hooks.ManageDocks: SetStruts :: [Direction2D] -> [Direction2D] -> SetStruts
+ XMonad.Hooks.ManageDocks: addedStruts :: SetStruts -> [Direction2D]
+ XMonad.Hooks.ManageDocks: calcGap :: Set Direction2D -> X (Rectangle -> Rectangle)
+ XMonad.Hooks.ManageDocks: data SetStruts
+ XMonad.Hooks.ManageDocks: instance Message SetStruts
+ XMonad.Hooks.ManageDocks: instance Read SetStruts
+ XMonad.Hooks.ManageDocks: instance Show SetStruts
+ XMonad.Hooks.ManageDocks: instance Typeable SetStruts
+ XMonad.Hooks.ManageDocks: removedStruts :: SetStruts -> [Direction2D]
+ XMonad.Hooks.ManageHelpers: C :: Side
+ XMonad.Hooks.ManageHelpers: CE :: Side
+ XMonad.Hooks.ManageHelpers: CW :: Side
+ XMonad.Hooks.ManageHelpers: NC :: Side
+ XMonad.Hooks.ManageHelpers: NE :: Side
+ XMonad.Hooks.ManageHelpers: NW :: Side
+ XMonad.Hooks.ManageHelpers: SC :: Side
+ XMonad.Hooks.ManageHelpers: SE :: Side
+ XMonad.Hooks.ManageHelpers: SW :: Side
+ XMonad.Hooks.ManageHelpers: data Side
+ XMonad.Hooks.ManageHelpers: doFloatAt :: Rational -> Rational -> ManageHook
+ XMonad.Hooks.ManageHelpers: doFloatDep :: (RationalRect -> RationalRect) -> ManageHook
+ XMonad.Hooks.ManageHelpers: doHideIgnore :: ManageHook
+ XMonad.Hooks.ManageHelpers: doSideFloat :: Side -> ManageHook
+ XMonad.Hooks.ManageHelpers: instance Eq Side
+ XMonad.Hooks.ManageHelpers: instance Read Side
+ XMonad.Hooks.ManageHelpers: instance Show Side
+ XMonad.Hooks.ManageHelpers: isDialog :: Query Bool
+ XMonad.Hooks.ManageHelpers: isInProperty :: String -> String -> Query Bool
+ XMonad.Hooks.ManageHelpers: pid :: Query (Maybe ProcessID)
+ XMonad.Hooks.Place: data Placement
+ XMonad.Hooks.Place: fixed :: (Rational, Rational) -> Placement
+ XMonad.Hooks.Place: inBounds :: Placement -> Placement
+ XMonad.Hooks.Place: instance (Eq a) => Eq (SmartRectangle a)
+ XMonad.Hooks.Place: instance (Show a) => Show (SmartRectangle a)
+ XMonad.Hooks.Place: instance Eq Placement
+ XMonad.Hooks.Place: instance Read Placement
+ XMonad.Hooks.Place: instance Show Placement
+ XMonad.Hooks.Place: placeFocused :: Placement -> X ()
+ XMonad.Hooks.Place: placeHook :: Placement -> ManageHook
+ XMonad.Hooks.Place: purePlaceWindow :: Placement -> Rectangle -> [Rectangle] -> (Position, Position) -> Rectangle -> Rectangle
+ XMonad.Hooks.Place: simpleSmart :: Placement
+ XMonad.Hooks.Place: smart :: (Rational, Rational) -> Placement
+ XMonad.Hooks.Place: underMouse :: (Rational, Rational) -> Placement
+ XMonad.Hooks.Place: withGaps :: (Dimension, Dimension, Dimension, Dimension) -> Placement -> Placement
+ XMonad.Hooks.RestoreMinimized: RestoreMinimized :: RestoreMinimized
+ XMonad.Hooks.RestoreMinimized: data RestoreMinimized
+ XMonad.Hooks.RestoreMinimized: instance Read RestoreMinimized
+ XMonad.Hooks.RestoreMinimized: instance Show RestoreMinimized
+ XMonad.Hooks.RestoreMinimized: restoreMinimizedEventHook :: Event -> X All
+ XMonad.Hooks.ServerMode: serverModeEventHook :: Event -> X All
+ XMonad.Hooks.ServerMode: serverModeEventHook' :: X [(String, X ())] -> Event -> X All
+ XMonad.Hooks.UrgencyHook: Dont :: RemindWhen
+ XMonad.Hooks.UrgencyHook: Every :: Interval -> RemindWhen
+ XMonad.Hooks.UrgencyHook: Repeatedly :: Int -> Interval -> RemindWhen
+ XMonad.Hooks.UrgencyHook: clearUrgents :: X ()
+ XMonad.Hooks.UrgencyHook: data RemindWhen
+ XMonad.Hooks.UrgencyHook: instance Eq Reminder
+ XMonad.Hooks.UrgencyHook: instance Read RemindWhen
+ XMonad.Hooks.UrgencyHook: instance Show RemindWhen
+ XMonad.Hooks.UrgencyHook: minutes :: Rational -> Rational
+ XMonad.Hooks.UrgencyHook: remindWhen :: UrgencyConfig -> RemindWhen
+ XMonad.Hooks.WorkspaceByPos: workspaceByPos :: ManageHook
+ XMonad.Layout.AutoMaster: autoMaster :: (LayoutClass l a) => Int -> Float -> l a -> ModifiedLayout AutoMaster l a
+ XMonad.Layout.AutoMaster: instance LayoutModifier AutoMaster Window
+ XMonad.Layout.AutoMaster: instance Read (AutoMaster a)
+ XMonad.Layout.AutoMaster: instance Show (AutoMaster a)
+ XMonad.Layout.BorderResize: BR :: [BorderWithWin] -> BorderResize a
+ XMonad.Layout.BorderResize: borderResize :: l a -> ModifiedLayout BorderResize l a
+ XMonad.Layout.BorderResize: data BorderResize a
+ XMonad.Layout.BorderResize: instance Eq BorderInfo
+ XMonad.Layout.BorderResize: instance LayoutModifier BorderResize Window
+ XMonad.Layout.BorderResize: instance Read (BorderResize a)
+ XMonad.Layout.BorderResize: instance Read BorderInfo
+ XMonad.Layout.BorderResize: instance Show (BorderResize a)
+ XMonad.Layout.BorderResize: instance Show BorderInfo
+ XMonad.Layout.BoringWindows: Merge :: String -> [Window] -> BoringMessage
+ XMonad.Layout.BoringWindows: Replace :: String -> [Window] -> BoringMessage
+ XMonad.Layout.BoringWindows: UpdateBoring :: UpdateBoring
+ XMonad.Layout.BoringWindows: boringAuto :: (LayoutClass l a, Eq a) => l a -> ModifiedLayout BoringWindows l a
+ XMonad.Layout.BoringWindows: data BoringMessage
+ XMonad.Layout.BoringWindows: data BoringWindows a
+ XMonad.Layout.BoringWindows: data UpdateBoring
+ XMonad.Layout.BoringWindows: focusMaster :: X ()
+ XMonad.Layout.BoringWindows: instance (Read a) => Read (BoringWindows a)
+ XMonad.Layout.BoringWindows: instance (Show a) => Show (BoringWindows a)
+ XMonad.Layout.BoringWindows: instance Message UpdateBoring
+ XMonad.Layout.BoringWindows: instance Typeable UpdateBoring
+ XMonad.Layout.CenteredMaster: centerMaster :: (LayoutClass l a) => l a -> ModifiedLayout CenteredMaster l a
+ XMonad.Layout.CenteredMaster: instance LayoutModifier CenteredMaster Window
+ XMonad.Layout.CenteredMaster: instance LayoutModifier TopRightMaster Window
+ XMonad.Layout.CenteredMaster: instance Read (CenteredMaster a)
+ XMonad.Layout.CenteredMaster: instance Read (TopRightMaster a)
+ XMonad.Layout.CenteredMaster: instance Show (CenteredMaster a)
+ XMonad.Layout.CenteredMaster: instance Show (TopRightMaster a)
+ XMonad.Layout.CenteredMaster: topRightMaster :: (LayoutClass l a) => l a -> ModifiedLayout TopRightMaster l a
+ XMonad.Layout.Column: Column :: Float -> Column a
+ XMonad.Layout.Column: data Column a
+ XMonad.Layout.Column: instance LayoutClass Column a
+ XMonad.Layout.Column: instance Read (Column a)
+ XMonad.Layout.Column: instance Show (Column a)
+ XMonad.Layout.ComboP: And :: Property -> Property -> Property
+ XMonad.Layout.ComboP: ClassName :: String -> Property
+ XMonad.Layout.ComboP: Const :: Bool -> Property
+ XMonad.Layout.ComboP: Machine :: String -> Property
+ XMonad.Layout.ComboP: Not :: Property -> Property
+ XMonad.Layout.ComboP: Or :: Property -> Property -> Property
+ XMonad.Layout.ComboP: Resource :: String -> Property
+ XMonad.Layout.ComboP: Role :: String -> Property
+ XMonad.Layout.ComboP: SwapWindow :: SwapWindow
+ XMonad.Layout.ComboP: SwapWindowN :: Int -> SwapWindow
+ XMonad.Layout.ComboP: Title :: String -> Property
+ XMonad.Layout.ComboP: combineTwoP :: (LayoutClass super (), LayoutClass l1 Window, LayoutClass l2 Window) => super () -> l1 Window -> l2 Window -> Property -> CombineTwoP (super ()) l1 l2 Window
+ XMonad.Layout.ComboP: data CombineTwoP l l1 l2 a
+ XMonad.Layout.ComboP: data Property
+ XMonad.Layout.ComboP: data SwapWindow
+ XMonad.Layout.ComboP: instance (LayoutClass l (), LayoutClass l1 Window, LayoutClass l2 Window) => LayoutClass (CombineTwoP (l ()) l1 l2) Window
+ XMonad.Layout.ComboP: instance (Read l, Read a, Read (l1 a), Read (l2 a)) => Read (CombineTwoP l l1 l2 a)
+ XMonad.Layout.ComboP: instance (Show l, Show a, Show (l1 a), Show (l2 a)) => Show (CombineTwoP l l1 l2 a)
+ XMonad.Layout.ComboP: instance Message SwapWindow
+ XMonad.Layout.ComboP: instance Read SwapWindow
+ XMonad.Layout.ComboP: instance Show SwapWindow
+ XMonad.Layout.ComboP: instance Typeable SwapWindow
+ XMonad.Layout.Cross: Cross :: !Rational -> !Rational -> Cross a
+ XMonad.Layout.Cross: crossInc :: Cross a -> !Rational
+ XMonad.Layout.Cross: crossProp :: Cross a -> !Rational
+ XMonad.Layout.Cross: data Cross a
+ XMonad.Layout.Cross: instance LayoutClass Cross a
+ XMonad.Layout.Cross: instance Read (Cross a)
+ XMonad.Layout.Cross: instance Show (Cross a)
+ XMonad.Layout.Cross: simpleCross :: Cross a
+ XMonad.Layout.Decoration: findWindowByDecoration :: Window -> DecorationState -> Maybe (OrigWin, (Window, Maybe Rectangle))
+ XMonad.Layout.Decoration: shrinkWhile :: (String -> [String]) -> (String -> X Bool) -> String -> X String
+ XMonad.Layout.FixedColumn: FixedColumn :: !Int -> !Int -> !Int -> !Int -> FixedColumn a
+ XMonad.Layout.FixedColumn: data FixedColumn a
+ XMonad.Layout.FixedColumn: instance LayoutClass FixedColumn Window
+ XMonad.Layout.FixedColumn: instance Read (FixedColumn a)
+ XMonad.Layout.FixedColumn: instance Show (FixedColumn a)
+ XMonad.Layout.Gaps: data Direction2D
+ XMonad.Layout.Grid: GridRatio :: Double -> Grid a
+ XMonad.Layout.Grid: defaultRatio :: Double
+ XMonad.Layout.GridVariants: B :: Orientation
+ XMonad.Layout.GridVariants: Grid :: !Rational -> Grid a
+ XMonad.Layout.GridVariants: IncMasterCols :: !Int -> ChangeMasterGeom
+ XMonad.Layout.GridVariants: IncMasterRows :: !Int -> ChangeMasterGeom
+ XMonad.Layout.GridVariants: L :: Orientation
+ XMonad.Layout.GridVariants: R :: Orientation
+ XMonad.Layout.GridVariants: SplitGrid :: Orientation -> !Int -> !Int -> !Rational -> !Rational -> !Rational -> SplitGrid a
+ XMonad.Layout.GridVariants: T :: Orientation
+ XMonad.Layout.GridVariants: TallGrid :: !Int -> !Int -> !Rational -> !Rational -> !Rational -> TallGrid a
+ XMonad.Layout.GridVariants: data ChangeMasterGeom
+ XMonad.Layout.GridVariants: data Grid a
+ XMonad.Layout.GridVariants: data Orientation
+ XMonad.Layout.GridVariants: data SplitGrid a
+ XMonad.Layout.GridVariants: data TallGrid a
+ XMonad.Layout.GridVariants: instance Eq Orientation
+ XMonad.Layout.GridVariants: instance LayoutClass Grid a
+ XMonad.Layout.GridVariants: instance LayoutClass SplitGrid a
+ XMonad.Layout.GridVariants: instance LayoutClass TallGrid a
+ XMonad.Layout.GridVariants: instance Message ChangeMasterGeom
+ XMonad.Layout.GridVariants: instance Read (Grid a)
+ XMonad.Layout.GridVariants: instance Read (SplitGrid a)
+ XMonad.Layout.GridVariants: instance Read (TallGrid a)
+ XMonad.Layout.GridVariants: instance Read Orientation
+ XMonad.Layout.GridVariants: instance Show (Grid a)
+ XMonad.Layout.GridVariants: instance Show (SplitGrid a)
+ XMonad.Layout.GridVariants: instance Show (TallGrid a)
+ XMonad.Layout.GridVariants: instance Show Orientation
+ XMonad.Layout.GridVariants: instance Typeable ChangeMasterGeom
+ XMonad.Layout.HintedGrid: GridRatio :: Double -> Bool -> Grid a
+ XMonad.Layout.HintedGrid: defaultRatio :: Double
+ XMonad.Layout.IM: Machine :: String -> Property
+ XMonad.Layout.IndependentScreens: countScreens :: (MonadIO m, Integral i) => m i
+ XMonad.Layout.IndependentScreens: marshall :: ScreenId -> VirtualWorkspace -> PhysicalWorkspace
+ XMonad.Layout.IndependentScreens: onCurrentScreen :: (VirtualWorkspace -> WindowSet -> a) -> (PhysicalWorkspace -> WindowSet -> a)
+ XMonad.Layout.IndependentScreens: type PhysicalWorkspace = WorkspaceId
+ XMonad.Layout.IndependentScreens: type VirtualWorkspace = WorkspaceId
+ XMonad.Layout.IndependentScreens: unmarshall :: PhysicalWorkspace -> (ScreenId, VirtualWorkspace)
+ XMonad.Layout.IndependentScreens: withScreens :: ScreenId -> [VirtualWorkspace] -> [PhysicalWorkspace]
+ XMonad.Layout.IndependentScreens: workspaces' :: XConfig l -> [VirtualWorkspace]
+ XMonad.Layout.LayoutBuilder: Abs :: Int -> SubMeasure
+ XMonad.Layout.LayoutBuilder: IncLayoutN :: Int -> IncLayoutN
+ XMonad.Layout.LayoutBuilder: Rel :: Rational -> SubMeasure
+ XMonad.Layout.LayoutBuilder: SubBox :: SubMeasure -> SubMeasure -> SubMeasure -> SubMeasure -> SubBox
+ XMonad.Layout.LayoutBuilder: absBox :: Int -> Int -> Int -> Int -> SubBox
+ XMonad.Layout.LayoutBuilder: data IncLayoutN
+ XMonad.Layout.LayoutBuilder: data SubBox
+ XMonad.Layout.LayoutBuilder: data SubMeasure
+ XMonad.Layout.LayoutBuilder: instance (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutClass (LayoutN l1 l2) a
+ XMonad.Layout.LayoutBuilder: instance (Read a, Read (l1 a), Read (l2 a)) => Read (LayoutN l1 l2 a)
+ XMonad.Layout.LayoutBuilder: instance (Show a, Show (l1 a), Show (l2 a)) => Show (LayoutN l1 l2 a)
+ XMonad.Layout.LayoutBuilder: instance Message IncLayoutN
+ XMonad.Layout.LayoutBuilder: instance Read SubBox
+ XMonad.Layout.LayoutBuilder: instance Read SubMeasure
+ XMonad.Layout.LayoutBuilder: instance Show SubBox
+ XMonad.Layout.LayoutBuilder: instance Show SubMeasure
+ XMonad.Layout.LayoutBuilder: instance Typeable IncLayoutN
+ XMonad.Layout.LayoutBuilder: layoutAll :: (Read a, Eq a, LayoutClass l1 a) => SubBox -> l1 a -> LayoutN l1 Full a
+ XMonad.Layout.LayoutBuilder: layoutN :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) => Int -> SubBox -> Maybe SubBox -> l1 a -> LayoutN l2 l3 a -> LayoutN l1 (LayoutN l2 l3) a
+ XMonad.Layout.LayoutBuilder: layoutR :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) => Rational -> Rational -> SubBox -> Maybe SubBox -> l1 a -> LayoutN l2 l3 a -> LayoutN l1 (LayoutN l2 l3) a
+ XMonad.Layout.LayoutBuilder: relBox :: Rational -> Rational -> Rational -> Rational -> SubBox
+ XMonad.Layout.LayoutCombinators: NextLayoutNoWrap :: JumpToLayout
+ XMonad.Layout.LayoutCombinators: Wrap :: JumpToLayout
+ XMonad.Layout.LayoutHints: instance LayoutModifier LayoutHintsToCenter Window
+ XMonad.Layout.LayoutHints: instance Read (LayoutHintsToCenter a)
+ XMonad.Layout.LayoutHints: instance Show (LayoutHintsToCenter a)
+ XMonad.Layout.LayoutHints: layoutHintsToCenter :: (LayoutClass l a) => l a -> ModifiedLayout LayoutHintsToCenter l a
+ XMonad.Layout.LayoutHints: layoutHintsWithPlacement :: (LayoutClass l a) => (Double, Double) -> l a -> ModifiedLayout LayoutHints l a
+ XMonad.Layout.LimitWindows: decreaseLimit :: X ()
+ XMonad.Layout.LimitWindows: increaseLimit :: X ()
+ XMonad.Layout.LimitWindows: instance Eq (Selection a)
+ XMonad.Layout.LimitWindows: instance LayoutModifier LimitWindows a
+ XMonad.Layout.LimitWindows: instance LayoutModifier Selection a
+ XMonad.Layout.LimitWindows: instance Message LimitChange
+ XMonad.Layout.LimitWindows: instance Read (LimitWindows a)
+ XMonad.Layout.LimitWindows: instance Read (Selection a)
+ XMonad.Layout.LimitWindows: instance Read SliceStyle
+ XMonad.Layout.LimitWindows: instance Show (LimitWindows a)
+ XMonad.Layout.LimitWindows: instance Show (Selection a)
+ XMonad.Layout.LimitWindows: instance Show SliceStyle
+ XMonad.Layout.LimitWindows: instance Typeable LimitChange
+ XMonad.Layout.LimitWindows: limitSelect :: Int -> Int -> l a -> ModifiedLayout Selection l a
+ XMonad.Layout.LimitWindows: limitSlice :: Int -> l a -> ModifiedLayout LimitWindows l a
+ XMonad.Layout.LimitWindows: limitWindows :: Int -> l a -> ModifiedLayout LimitWindows l a
+ XMonad.Layout.LimitWindows: setLimit :: Int -> X ()
+ XMonad.Layout.MagicFocus: disableFollowOnWS :: [WorkspaceId] -> X Bool
+ XMonad.Layout.MagicFocus: followOnlyIf :: X Bool -> Event -> X All
+ XMonad.Layout.MagicFocus: promoteWarp :: Event -> X All
+ XMonad.Layout.MagicFocus: promoteWarp' :: PointerPosition -> Event -> X All
+ XMonad.Layout.Master: instance LayoutModifier AddMaster Window
+ XMonad.Layout.Master: instance Read (AddMaster a)
+ XMonad.Layout.Master: instance Show (AddMaster a)
+ XMonad.Layout.MessageControl: Escape :: SomeMessage -> EscapedMessage
+ XMonad.Layout.MessageControl: data Ignore m l w
+ XMonad.Layout.MessageControl: data UnEscape w
+ XMonad.Layout.MessageControl: escape :: (Message m) => m -> EscapedMessage
+ XMonad.Layout.MessageControl: ignore :: (Message m, LayoutClass l w) => m -> l w -> (Ignore m l w)
+ XMonad.Layout.MessageControl: instance (Message m, LayoutClass l w) => LayoutClass (Ignore m l) w
+ XMonad.Layout.MessageControl: instance (Read (l w)) => Read (Ignore m l w)
+ XMonad.Layout.MessageControl: instance (Show (l w)) => Show (Ignore m l w)
+ XMonad.Layout.MessageControl: instance LayoutModifier UnEscape a
+ XMonad.Layout.MessageControl: instance Message EscapedMessage
+ XMonad.Layout.MessageControl: instance Read (UnEscape w)
+ XMonad.Layout.MessageControl: instance Show (UnEscape w)
+ XMonad.Layout.MessageControl: instance Typeable EscapedMessage
+ XMonad.Layout.MessageControl: newtype EscapedMessage
+ XMonad.Layout.MessageControl: unEscape :: (LayoutClass l w) => l w -> ModifiedLayout UnEscape l w
+ XMonad.Layout.Minimize: MinimizeWin :: Window -> MinimizeMsg
+ XMonad.Layout.Minimize: RestoreMinimizedWin :: Window -> MinimizeMsg
+ XMonad.Layout.Minimize: RestoreNextMinimizedWin :: MinimizeMsg
+ XMonad.Layout.Minimize: data MinimizeMsg
+ XMonad.Layout.Minimize: instance Eq MinimizeMsg
+ XMonad.Layout.Minimize: instance LayoutModifier Minimize Window
+ XMonad.Layout.Minimize: instance Message MinimizeMsg
+ XMonad.Layout.Minimize: instance Read (Minimize a)
+ XMonad.Layout.Minimize: instance Show (Minimize a)
+ XMonad.Layout.Minimize: instance Typeable MinimizeMsg
+ XMonad.Layout.Minimize: minimize :: (LayoutClass l Window) => l Window -> ModifiedLayout Minimize l Window
+ XMonad.Layout.Monitor: And :: Property -> Property -> Property
+ XMonad.Layout.Monitor: ClassName :: String -> Property
+ XMonad.Layout.Monitor: Const :: Bool -> Property
+ XMonad.Layout.Monitor: HideMonitor :: MonitorMessage
+ XMonad.Layout.Monitor: HideMonitorNamed :: String -> MonitorMessage
+ XMonad.Layout.Monitor: Machine :: String -> Property
+ XMonad.Layout.Monitor: Monitor :: Property -> Rectangle -> Bool -> String -> Bool -> Rational -> Monitor a
+ XMonad.Layout.Monitor: Not :: Property -> Property
+ XMonad.Layout.Monitor: Or :: Property -> Property -> Property
+ XMonad.Layout.Monitor: Resource :: String -> Property
+ XMonad.Layout.Monitor: Role :: String -> Property
+ XMonad.Layout.Monitor: ShowMonitor :: MonitorMessage
+ XMonad.Layout.Monitor: ShowMonitorNamed :: String -> MonitorMessage
+ XMonad.Layout.Monitor: Title :: String -> Property
+ XMonad.Layout.Monitor: ToggleMonitor :: MonitorMessage
+ XMonad.Layout.Monitor: ToggleMonitorNamed :: String -> MonitorMessage
+ XMonad.Layout.Monitor: data Monitor a
+ XMonad.Layout.Monitor: data MonitorMessage
+ XMonad.Layout.Monitor: data Property
+ XMonad.Layout.Monitor: doHideIgnore :: ManageHook
+ XMonad.Layout.Monitor: instance Eq MonitorMessage
+ XMonad.Layout.Monitor: instance LayoutModifier Monitor Window
+ XMonad.Layout.Monitor: instance Message MonitorMessage
+ XMonad.Layout.Monitor: instance Read (Monitor a)
+ XMonad.Layout.Monitor: instance Read MonitorMessage
+ XMonad.Layout.Monitor: instance Show (Monitor a)
+ XMonad.Layout.Monitor: instance Show MonitorMessage
+ XMonad.Layout.Monitor: instance Typeable MonitorMessage
+ XMonad.Layout.Monitor: manageMonitor :: Monitor a -> ManageHook
+ XMonad.Layout.Monitor: monitor :: Monitor a
+ XMonad.Layout.Monitor: name :: Monitor a -> String
+ XMonad.Layout.Monitor: opacity :: Monitor a -> Rational
+ XMonad.Layout.Monitor: persistent :: Monitor a -> Bool
+ XMonad.Layout.Monitor: prop :: Monitor a -> Property
+ XMonad.Layout.Monitor: rect :: Monitor a -> Rectangle
+ XMonad.Layout.Monitor: visible :: Monitor a -> Bool
+ XMonad.Layout.Mosaic: Reset :: Aspect
+ XMonad.Layout.Mosaic: SlopeMod :: ([Rational] -> [Rational]) -> Aspect
+ XMonad.Layout.Mosaic: Taller :: Aspect
+ XMonad.Layout.Mosaic: Wider :: Aspect
+ XMonad.Layout.Mosaic: changeFocused :: (Rational -> Rational) -> X ()
+ XMonad.Layout.Mosaic: changeMaster :: (Rational -> Rational) -> X ()
+ XMonad.Layout.Mosaic: data Aspect
+ XMonad.Layout.Mosaic: instance Foldable Tree
+ XMonad.Layout.Mosaic: instance Functor Tree
+ XMonad.Layout.Mosaic: instance LayoutClass Mosaic a
+ XMonad.Layout.Mosaic: instance Message Aspect
+ XMonad.Layout.Mosaic: instance Monoid (Tree a)
+ XMonad.Layout.Mosaic: instance Read (Mosaic a)
+ XMonad.Layout.Mosaic: instance Show (Mosaic a)
+ XMonad.Layout.Mosaic: instance Typeable Aspect
+ XMonad.Layout.Mosaic: mosaic :: Rational -> [Rational] -> Mosaic a
+ XMonad.Layout.MouseResizableTile: ExpandSlave :: MRTMessage
+ XMonad.Layout.MouseResizableTile: ShrinkSlave :: MRTMessage
+ XMonad.Layout.MouseResizableTile: data MRTMessage
+ XMonad.Layout.MouseResizableTile: instance LayoutClass MouseResizableTile a
+ XMonad.Layout.MouseResizableTile: instance Message MRTMessage
+ XMonad.Layout.MouseResizableTile: instance Read (MouseResizableTile a)
+ XMonad.Layout.MouseResizableTile: instance Read DraggerInfo
+ XMonad.Layout.MouseResizableTile: instance Show (MouseResizableTile a)
+ XMonad.Layout.MouseResizableTile: instance Show DraggerInfo
+ XMonad.Layout.MouseResizableTile: instance Typeable MRTMessage
+ XMonad.Layout.MouseResizableTile: mouseResizableTile :: MouseResizableTile a
+ XMonad.Layout.MouseResizableTile: mouseResizableTileMirrored :: MouseResizableTile a
+ XMonad.Layout.Named: instance LayoutModifier NameTail a
+ XMonad.Layout.Named: instance Read (NameTail a)
+ XMonad.Layout.Named: instance Show (NameTail a)
+ XMonad.Layout.Named: nameTail :: l a -> ModifiedLayout NameTail l a
+ XMonad.Layout.NoBorders: Combine :: With -> Ambiguity -> Ambiguity -> Ambiguity
+ XMonad.Layout.NoBorders: Difference :: With
+ XMonad.Layout.NoBorders: EmptyScreen :: Ambiguity
+ XMonad.Layout.NoBorders: Intersection :: With
+ XMonad.Layout.NoBorders: Never :: Ambiguity
+ XMonad.Layout.NoBorders: OnlyFloat :: Ambiguity
+ XMonad.Layout.NoBorders: OtherIndicated :: Ambiguity
+ XMonad.Layout.NoBorders: Screen :: Ambiguity
+ XMonad.Layout.NoBorders: Union :: With
+ XMonad.Layout.NoBorders: class SetsAmbiguous p
+ XMonad.Layout.NoBorders: data Ambiguity
+ XMonad.Layout.NoBorders: data With
+ XMonad.Layout.NoBorders: hiddens :: (SetsAmbiguous p) => p -> WindowSet -> Maybe (Stack Window) -> [(Window, Rectangle)] -> [Window]
+ XMonad.Layout.NoBorders: instance (Read p, Read w) => Read (ConfigurableBorder p w)
+ XMonad.Layout.NoBorders: instance (Read p, Show p, SetsAmbiguous p) => LayoutModifier (ConfigurableBorder p) Window
+ XMonad.Layout.NoBorders: instance (Show p, Show w) => Show (ConfigurableBorder p w)
+ XMonad.Layout.NoBorders: instance Read Ambiguity
+ XMonad.Layout.NoBorders: instance Read With
+ XMonad.Layout.NoBorders: instance SetsAmbiguous Ambiguity
+ XMonad.Layout.NoBorders: instance Show Ambiguity
+ XMonad.Layout.NoBorders: instance Show With
+ XMonad.Layout.NoBorders: lessBorders :: (SetsAmbiguous p, Read p, Show p, LayoutClass l a) => p -> l a -> ModifiedLayout (ConfigurableBorder p) l a
+ XMonad.Layout.NoFrillsDecoration: instance (Eq a) => DecorationStyle NoFrillsDecoration a
+ XMonad.Layout.NoFrillsDecoration: instance Read (NoFrillsDecoration a)
+ XMonad.Layout.NoFrillsDecoration: instance Show (NoFrillsDecoration a)
+ XMonad.Layout.NoFrillsDecoration: noFrillsDeco :: (Eq a, Shrinker s) => s -> Theme -> l a -> ModifiedLayout (Decoration NoFrillsDecoration s) l a
+ XMonad.Layout.OneBig: OneBig :: Float -> Float -> OneBig a
+ XMonad.Layout.OneBig: data OneBig a
+ XMonad.Layout.OneBig: instance LayoutClass OneBig a
+ XMonad.Layout.OneBig: instance Read (OneBig a)
+ XMonad.Layout.OneBig: instance Show (OneBig a)
+ XMonad.Layout.ResizableTile: _delta :: ResizableTall a -> Rational
+ XMonad.Layout.ResizableTile: _frac :: ResizableTall a -> Rational
+ XMonad.Layout.ResizableTile: _nmaster :: ResizableTall a -> Int
+ XMonad.Layout.ResizableTile: _slaves :: ResizableTall a -> [Rational]
+ XMonad.Layout.Spacing: instance LayoutModifier Spacing a
+ XMonad.Layout.Spacing: instance Read (Spacing a)
+ XMonad.Layout.Spacing: instance Show (Spacing a)
+ XMonad.Layout.Spacing: spacing :: Int -> l a -> ModifiedLayout Spacing l a
+ XMonad.Layout.SubLayouts: Broadcast :: SomeMessage -> Broadcast
+ XMonad.Layout.SubLayouts: Merge :: a -> a -> GroupMsg a
+ XMonad.Layout.SubLayouts: MergeAll :: a -> GroupMsg a
+ XMonad.Layout.SubLayouts: Migrate :: a -> a -> GroupMsg a
+ XMonad.Layout.SubLayouts: SubMessage :: SomeMessage -> a -> GroupMsg a
+ XMonad.Layout.SubLayouts: UnMerge :: a -> GroupMsg a
+ XMonad.Layout.SubLayouts: UnMergeAll :: a -> GroupMsg a
+ XMonad.Layout.SubLayouts: WithGroup :: (Stack a -> X (Stack a)) -> a -> GroupMsg a
+ XMonad.Layout.SubLayouts: data Broadcast
+ XMonad.Layout.SubLayouts: data GroupMsg a
+ XMonad.Layout.SubLayouts: defaultSublMap :: XConfig l -> Map (KeyMask, KeySym) (X ())
+ XMonad.Layout.SubLayouts: instance (Read (l Window), Show (l Window), LayoutClass l Window) => LayoutModifier (Sublayout l) Window
+ XMonad.Layout.SubLayouts: instance (Read a, Read (l a)) => Read (Sublayout l a)
+ XMonad.Layout.SubLayouts: instance (Show a, Show (l a)) => Show (Sublayout l a)
+ XMonad.Layout.SubLayouts: instance (Typeable a) => Message (GroupMsg a)
+ XMonad.Layout.SubLayouts: instance Message Broadcast
+ XMonad.Layout.SubLayouts: instance Typeable Broadcast
+ XMonad.Layout.SubLayouts: instance Typeable1 GroupMsg
+ XMonad.Layout.SubLayouts: mergeDir :: (Stack Window -> Stack Window) -> Window -> GroupMsg Window
+ XMonad.Layout.SubLayouts: onGroup :: (Stack Window -> Stack Window) -> X ()
+ XMonad.Layout.SubLayouts: pullGroup :: Direction2D -> Navigate
+ XMonad.Layout.SubLayouts: pullWindow :: Direction2D -> Navigate
+ XMonad.Layout.SubLayouts: pushGroup :: Direction2D -> Navigate
+ XMonad.Layout.SubLayouts: pushWindow :: Direction2D -> Navigate
+ XMonad.Layout.SubLayouts: subLayout :: [Int] -> subl a -> l a -> ModifiedLayout (Sublayout subl) l a
+ XMonad.Layout.SubLayouts: subTabbed :: (Eq a, LayoutModifier (Sublayout Simplest) a, LayoutClass l a) => l a -> ModifiedLayout (Decoration TabbedDecoration DefaultShrinker) (ModifiedLayout (Sublayout Simplest) l) a
+ XMonad.Layout.SubLayouts: toSubl :: (Message a) => a -> X ()
+ XMonad.Layout.ThreeColumns: ThreeColMid :: !Int -> !Rational -> !Rational -> ThreeCol a
+ XMonad.Layout.ThreeColumns: threeColDelta :: ThreeCol a -> !Rational
+ XMonad.Layout.ThreeColumns: threeColFrac :: ThreeCol a -> !Rational
+ XMonad.Layout.ThreeColumns: threeColNMaster :: ThreeCol a -> !Int
+ XMonad.Layout.WindowNavigation: Apply :: (Window -> X ()) -> Direction2D -> Navigate
+ XMonad.Layout.WindowNavigation: data Direction2D
+ XMonad.Prompt: Next :: Direction1D
+ XMonad.Prompt: Prev :: Direction1D
+ XMonad.Prompt: amberXPConfig :: XPConfig
+ XMonad.Prompt: completionKey :: XPConfig -> KeySym
+ XMonad.Prompt: copyString :: XP ()
+ XMonad.Prompt: data Direction1D
+ XMonad.Prompt: defaultXPKeymap :: Map (KeyMask, KeySym) (XP ())
+ XMonad.Prompt: deleteAllDuplicates :: [String] -> [String]
+ XMonad.Prompt: deleteConsecutive :: [String] -> [String]
+ XMonad.Prompt: deleteString :: Direction1D -> XP ()
+ XMonad.Prompt: endOfLine :: XP ()
+ XMonad.Prompt: greenXPConfig :: XPConfig
+ XMonad.Prompt: historyCompletionP :: (String -> Bool) -> ComplFunction
+ XMonad.Prompt: historyFilter :: XPConfig -> [String] -> [String]
+ XMonad.Prompt: killAfter :: XP ()
+ XMonad.Prompt: killBefore :: XP ()
+ XMonad.Prompt: killWord :: Direction1D -> XP ()
+ XMonad.Prompt: moveCursor :: Direction1D -> XP ()
+ XMonad.Prompt: moveHistory :: (Stack String -> Stack String) -> XP ()
+ XMonad.Prompt: moveWord :: Direction1D -> XP ()
+ XMonad.Prompt: pasteString :: XP ()
+ XMonad.Prompt: promptKeymap :: XPConfig -> Map (KeyMask, KeySym) (XP ())
+ XMonad.Prompt: quit :: XP ()
+ XMonad.Prompt: setDone :: Bool -> XP ()
+ XMonad.Prompt: setSuccess :: Bool -> XP ()
+ XMonad.Prompt: showCompletionOnTab :: XPConfig -> Bool
+ XMonad.Prompt: startOfLine :: XP ()
+ XMonad.Prompt: type XP = StateT XPState IO
+ XMonad.Prompt.Shell: Shell :: Shell
+ XMonad.Prompt.Shell: data Shell
+ XMonad.Prompt.Window: windowPromptBringCopy :: XPConfig -> X ()
+ XMonad.Util.Cursor: setDefaultCursor :: Glyph -> X ()
+ XMonad.Util.Dmenu: menu :: String -> [String] -> X String
+ XMonad.Util.Dmenu: menuMap :: String -> Map String a -> X (Maybe a)
+ XMonad.Util.EZConfig: mkNamedKeymap :: XConfig l -> [(String, NamedAction)] -> [((KeyMask, KeySym), NamedAction)]
+ XMonad.Util.Loggers: (<$>) :: (Functor f) => (a -> b) -> f a -> f b
+ XMonad.Util.Loggers: aumixVolume :: Logger
+ XMonad.Util.Loggers: dzenColorL :: String -> String -> Logger -> Logger
+ XMonad.Util.Loggers: fixedWidthL :: Align -> String -> Int -> Logger -> Logger
+ XMonad.Util.Loggers: logCurrent :: Logger
+ XMonad.Util.Loggers: logFileCount :: FilePath -> (String -> Bool) -> Logger
+ XMonad.Util.Loggers: logLayout :: Logger
+ XMonad.Util.Loggers: logSp :: Int -> Logger
+ XMonad.Util.Loggers: logTitle :: Logger
+ XMonad.Util.Loggers: maildirNew :: FilePath -> Logger
+ XMonad.Util.Loggers: maildirUnread :: FilePath -> Logger
+ XMonad.Util.Loggers: onLogger :: (String -> String) -> Logger -> Logger
+ XMonad.Util.Loggers: padL :: Logger -> Logger
+ XMonad.Util.Loggers: shortenL :: Int -> Logger -> Logger
+ XMonad.Util.Loggers: wrapL :: String -> String -> Logger -> Logger
+ XMonad.Util.Loggers: xmobarColorL :: String -> String -> Logger -> Logger
+ XMonad.Util.NamedActions: (^++^) :: (HasName b, HasName b1) => [(d, b)] -> [(d, b1)] -> [(d, NamedAction)]
+ XMonad.Util.NamedActions: NamedAction :: a -> NamedAction
+ XMonad.Util.NamedActions: addDescrKeys :: (HasName b1, HasName b) => ((KeyMask, KeySym), [((KeyMask, KeySym), NamedAction)] -> b) -> (XConfig Layout -> [((KeyMask, KeySym), b1)]) -> XConfig l -> XConfig l
+ XMonad.Util.NamedActions: addName :: String -> X () -> NamedAction
+ XMonad.Util.NamedActions: class HasName a
+ XMonad.Util.NamedActions: data NamedAction
+ XMonad.Util.NamedActions: defaultKeysDescr :: XConfig Layout -> [((KeyMask, KeySym), NamedAction)]
+ XMonad.Util.NamedActions: instance HasName (IO ())
+ XMonad.Util.NamedActions: instance HasName (NamedAction, String)
+ XMonad.Util.NamedActions: instance HasName (X ())
+ XMonad.Util.NamedActions: instance HasName (X (), String)
+ XMonad.Util.NamedActions: instance HasName (X (), [String])
+ XMonad.Util.NamedActions: instance HasName NamedAction
+ XMonad.Util.NamedActions: instance HasName [Char]
+ XMonad.Util.NamedActions: instance Show IncMasterN
+ XMonad.Util.NamedActions: instance Show Resize
+ XMonad.Util.NamedActions: noName :: X () -> NamedAction
+ XMonad.Util.NamedActions: oneName :: (X (), String) -> NamedAction
+ XMonad.Util.NamedActions: sendMessage' :: (Message a, Show a) => a -> NamedAction
+ XMonad.Util.NamedActions: separator :: ((KeyMask, KeySym), NamedAction)
+ XMonad.Util.NamedActions: showKm :: [((KeyMask, KeySym), NamedAction)] -> [String]
+ XMonad.Util.NamedActions: showKmSimple :: [((KeyMask, KeySym), NamedAction)] -> [[Char]]
+ XMonad.Util.NamedActions: spawn' :: String -> NamedAction
+ XMonad.Util.NamedActions: submapName :: (HasName a) => [((KeyMask, KeySym), a)] -> NamedAction
+ XMonad.Util.NamedActions: subtitle :: String -> ((KeyMask, KeySym), NamedAction)
+ XMonad.Util.NamedActions: xMessage :: [((KeyMask, KeySym), NamedAction)] -> NamedAction
+ XMonad.Util.NamedScratchpad: NS :: String -> String -> Query Bool -> ManageHook -> NamedScratchpad
+ XMonad.Util.NamedScratchpad: cmd :: NamedScratchpad -> String
+ XMonad.Util.NamedScratchpad: customFloating :: RationalRect -> ManageHook
+ XMonad.Util.NamedScratchpad: data NamedScratchpad
+ XMonad.Util.NamedScratchpad: defaultFloating :: ManageHook
+ XMonad.Util.NamedScratchpad: hook :: NamedScratchpad -> ManageHook
+ XMonad.Util.NamedScratchpad: name :: NamedScratchpad -> String
+ XMonad.Util.NamedScratchpad: namedScratchpadAction :: NamedScratchpads -> String -> X ()
+ XMonad.Util.NamedScratchpad: namedScratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace]
+ XMonad.Util.NamedScratchpad: namedScratchpadManageHook :: NamedScratchpads -> ManageHook
+ XMonad.Util.NamedScratchpad: nonFloating :: ManageHook
+ XMonad.Util.NamedScratchpad: query :: NamedScratchpad -> Query Bool
+ XMonad.Util.NamedScratchpad: type NamedScratchpads = [NamedScratchpad]
+ XMonad.Util.Paste: noModMask :: KeyMask
+ XMonad.Util.Paste: pasteChar :: KeyMask -> Char -> X ()
+ XMonad.Util.Paste: pasteSelection :: X ()
+ XMonad.Util.Paste: pasteString :: String -> X ()
+ XMonad.Util.Paste: sendKey :: KeyMask -> KeySym -> X ()
+ XMonad.Util.Paste: sendKeyWindow :: KeyMask -> KeySym -> Window -> X ()
+ XMonad.Util.Replace: replace :: IO ()
+ XMonad.Util.Run: hPutStr :: Handle -> String -> IO ()
+ XMonad.Util.Run: hPutStrLn :: Handle -> String -> IO ()
+ XMonad.Util.Run: safeSpawnProg :: (MonadIO m) => FilePath -> m ()
+ XMonad.Util.Scratchpad: scratchpadSpawnActionCustom :: String -> X ()
+ XMonad.Util.StringProp: getStringListProp :: (MonadIO m) => Display -> StringProp -> m [String]
+ XMonad.Util.StringProp: getStringProp :: (MonadIO m) => Display -> StringProp -> m (Maybe [Char])
+ XMonad.Util.StringProp: setStringListProp :: (MonadIO m) => Display -> StringProp -> [String] -> m ()
+ XMonad.Util.StringProp: setStringProp :: (MonadIO m) => Display -> StringProp -> [Char] -> m ()
+ XMonad.Util.StringProp: type StringProp = String
+ XMonad.Util.Themes: kavonAutumnTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonBluesTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonChristmasTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonFireTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonForestTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonLakeTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonPeacockTheme :: ThemeInfo
+ XMonad.Util.Themes: kavonVioGreenTheme :: ThemeInfo
+ XMonad.Util.Types: D :: Direction2D
+ XMonad.Util.Types: L :: Direction2D
+ XMonad.Util.Types: Next :: Direction1D
+ XMonad.Util.Types: Prev :: Direction1D
+ XMonad.Util.Types: R :: Direction2D
+ XMonad.Util.Types: U :: Direction2D
+ XMonad.Util.Types: data Direction1D
+ XMonad.Util.Types: data Direction2D
+ XMonad.Util.Types: instance Bounded Direction2D
+ XMonad.Util.Types: instance Enum Direction2D
+ XMonad.Util.Types: instance Eq Direction1D
+ XMonad.Util.Types: instance Eq Direction2D
+ XMonad.Util.Types: instance Ord Direction2D
+ XMonad.Util.Types: instance Read Direction1D
+ XMonad.Util.Types: instance Read Direction2D
+ XMonad.Util.Types: instance Show Direction1D
+ XMonad.Util.Types: instance Show Direction2D
+ XMonad.Util.Types: instance Typeable Direction1D
+ XMonad.Util.Types: instance Typeable Direction2D
+ XMonad.Util.WindowProperties: Machine :: String -> Property
+ XMonad.Util.WindowProperties: allWithProperty :: Property -> X [Window]
+ XMonad.Util.WindowProperties: getProp32 :: Atom -> Window -> X (Maybe [CLong])
+ XMonad.Util.WindowProperties: getProp32s :: String -> Window -> X (Maybe [CLong])
+ XMonad.Util.WindowProperties: propertyToQuery :: Property -> Query Bool
+ XMonad.Util.XSelection: transformPromptSelection :: (String -> String) -> String -> X ()
+ XMonad.Util.XSelection: transformSafePromptSelection :: (String -> String) -> String -> X ()
- XMonad.Actions.CycleWS: Next :: WSDirection
+ XMonad.Actions.CycleWS: Next :: Direction1D
- XMonad.Actions.CycleWS: Prev :: WSDirection
+ XMonad.Actions.CycleWS: Prev :: Direction1D
- XMonad.Actions.CycleWS: findWorkspace :: X WorkspaceSort -> WSDirection -> WSType -> Int -> X WorkspaceId
+ XMonad.Actions.CycleWS: findWorkspace :: X WorkspaceSort -> Direction1D -> WSType -> Int -> X WorkspaceId
- XMonad.Actions.CycleWS: moveTo :: WSDirection -> WSType -> X ()
+ XMonad.Actions.CycleWS: moveTo :: Direction1D -> WSType -> X ()
- XMonad.Actions.CycleWS: shiftTo :: WSDirection -> WSType -> X ()
+ XMonad.Actions.CycleWS: shiftTo :: Direction1D -> WSType -> X ()
- XMonad.Actions.MouseGestures: D :: Direction
+ XMonad.Actions.MouseGestures: D :: Direction2D
- XMonad.Actions.MouseGestures: L :: Direction
+ XMonad.Actions.MouseGestures: L :: Direction2D
- XMonad.Actions.MouseGestures: R :: Direction
+ XMonad.Actions.MouseGestures: R :: Direction2D
- XMonad.Actions.MouseGestures: U :: Direction
+ XMonad.Actions.MouseGestures: U :: Direction2D
- XMonad.Actions.MouseGestures: mkCollect :: (MonadIO m, MonadIO m') => m (Direction -> m' [Direction], m' [Direction])
+ XMonad.Actions.MouseGestures: mkCollect :: (MonadIO m, MonadIO m') => m (Direction2D -> m' [Direction2D], m' [Direction2D])
- XMonad.Actions.MouseGestures: mouseGesture :: Map [Direction] (Window -> X ()) -> Window -> X ()
+ XMonad.Actions.MouseGestures: mouseGesture :: Map [Direction2D] (Window -> X ()) -> Window -> X ()
- XMonad.Actions.MouseGestures: mouseGestureH :: (Direction -> X ()) -> X () -> X ()
+ XMonad.Actions.MouseGestures: mouseGestureH :: (Direction2D -> X ()) -> X () -> X ()
- XMonad.Actions.Search: searchEngine :: Name -> Site -> SearchEngine
+ XMonad.Actions.Search: searchEngine :: Name -> String -> SearchEngine
- XMonad.Actions.SwapWorkspaces: Next :: WSDirection
+ XMonad.Actions.SwapWorkspaces: Next :: Direction1D
- XMonad.Actions.SwapWorkspaces: Prev :: WSDirection
+ XMonad.Actions.SwapWorkspaces: Prev :: Direction1D
- XMonad.Actions.SwapWorkspaces: swapTo :: WSDirection -> X ()
+ XMonad.Actions.SwapWorkspaces: swapTo :: Direction1D -> X ()
- XMonad.Actions.WindowNavigation: D :: Direction
+ XMonad.Actions.WindowNavigation: D :: Direction2D
- XMonad.Actions.WindowNavigation: L :: Direction
+ XMonad.Actions.WindowNavigation: L :: Direction2D
- XMonad.Actions.WindowNavigation: R :: Direction
+ XMonad.Actions.WindowNavigation: R :: Direction2D
- XMonad.Actions.WindowNavigation: U :: Direction
+ XMonad.Actions.WindowNavigation: U :: Direction2D
- XMonad.Actions.WindowNavigation: WNGo :: Direction -> WNAction
+ XMonad.Actions.WindowNavigation: WNGo :: Direction2D -> WNAction
- XMonad.Actions.WindowNavigation: WNSwap :: Direction -> WNAction
+ XMonad.Actions.WindowNavigation: WNSwap :: Direction2D -> WNAction
- XMonad.Actions.WindowNavigation: go :: IORef WNState -> Direction -> X ()
+ XMonad.Actions.WindowNavigation: go :: IORef WNState -> Direction2D -> X ()
- XMonad.Actions.WindowNavigation: swap :: IORef WNState -> Direction -> X ()
+ XMonad.Actions.WindowNavigation: swap :: IORef WNState -> Direction2D -> X ()
- XMonad.Hooks.DynamicLog: dzen :: (XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full))) -> IO t) -> IO t
+ XMonad.Hooks.DynamicLog: dzen :: (LayoutClass l Window) => XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))
- XMonad.Hooks.DynamicLog: xmobar :: (XConfig (ModifiedLayout AvoidStruts (Choose Tall (Choose (Mirror Tall) Full))) -> IO t) -> IO t
+ XMonad.Hooks.DynamicLog: xmobar :: (LayoutClass l Window) => XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))
- XMonad.Hooks.FadeInactive: fadeInactiveLogHook :: Integer -> X ()
+ XMonad.Hooks.FadeInactive: fadeInactiveLogHook :: Rational -> X ()
- XMonad.Hooks.ManageDocks: ToggleStrut :: Direction -> ToggleStruts
+ XMonad.Hooks.ManageDocks: ToggleStrut :: Direction2D -> ToggleStruts
- XMonad.Hooks.ManageDocks: avoidStrutsOn :: (LayoutClass l a) => [Direction] -> l a -> ModifiedLayout AvoidStruts l a
+ XMonad.Hooks.ManageDocks: avoidStrutsOn :: (LayoutClass l a) => [Direction2D] -> l a -> ModifiedLayout AvoidStruts l a
- XMonad.Hooks.UrgencyHook: UrgencyConfig :: SuppressWhen -> UrgencyConfig
+ XMonad.Hooks.UrgencyHook: UrgencyConfig :: SuppressWhen -> RemindWhen -> UrgencyConfig
- XMonad.Hooks.UrgencyHook: withUrgencyHook :: (LayoutClass l Window, UrgencyHook h) => h -> XConfig l -> XConfig (HandleEvent (WithUrgencyHook h) l)
+ XMonad.Hooks.UrgencyHook: withUrgencyHook :: (LayoutClass l Window, UrgencyHook h) => h -> XConfig l -> XConfig l
- XMonad.Hooks.UrgencyHook: withUrgencyHookC :: (LayoutClass l Window, UrgencyHook h) => h -> UrgencyConfig -> XConfig l -> XConfig (HandleEvent (WithUrgencyHook h) l)
+ XMonad.Hooks.UrgencyHook: withUrgencyHookC :: (LayoutClass l Window, UrgencyHook h) => h -> UrgencyConfig -> XConfig l -> XConfig l
- XMonad.Layout.Gaps: D :: Direction
+ XMonad.Layout.Gaps: D :: Direction2D
- XMonad.Layout.Gaps: DecGap :: !Int -> !Direction -> GapMessage
+ XMonad.Layout.Gaps: DecGap :: !Int -> !Direction2D -> GapMessage
- XMonad.Layout.Gaps: IncGap :: !Int -> !Direction -> GapMessage
+ XMonad.Layout.Gaps: IncGap :: !Int -> !Direction2D -> GapMessage
- XMonad.Layout.Gaps: L :: Direction
+ XMonad.Layout.Gaps: L :: Direction2D
- XMonad.Layout.Gaps: R :: Direction
+ XMonad.Layout.Gaps: R :: Direction2D
- XMonad.Layout.Gaps: ToggleGap :: !Direction -> GapMessage
+ XMonad.Layout.Gaps: ToggleGap :: !Direction2D -> GapMessage
- XMonad.Layout.Gaps: U :: Direction
+ XMonad.Layout.Gaps: U :: Direction2D
- XMonad.Layout.Gaps: type GapSpec = [(Direction, Int)]
+ XMonad.Layout.Gaps: type GapSpec = [(Direction2D, Int)]
- XMonad.Layout.Grid: arrange :: Rectangle -> [a] -> [(a, Rectangle)]
+ XMonad.Layout.Grid: arrange :: Double -> Rectangle -> [a] -> [(a, Rectangle)]
- XMonad.Layout.HintedGrid: arrange :: Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]
+ XMonad.Layout.HintedGrid: arrange :: Double -> Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]
- XMonad.Layout.LayoutModifier: pureModifier :: (LayoutModifier m a) => m a -> Rectangle -> Stack a -> [(a, Rectangle)] -> ([(a, Rectangle)], Maybe (m a))
+ XMonad.Layout.LayoutModifier: pureModifier :: (LayoutModifier m a) => m a -> Rectangle -> Maybe (Stack a) -> [(a, Rectangle)] -> ([(a, Rectangle)], Maybe (m a))
- XMonad.Layout.LayoutModifier: redoLayout :: (LayoutModifier m a) => m a -> Rectangle -> Stack a -> [(a, Rectangle)] -> X ([(a, Rectangle)], Maybe (m a))
+ XMonad.Layout.LayoutModifier: redoLayout :: (LayoutModifier m a) => m a -> Rectangle -> Maybe (Stack a) -> [(a, Rectangle)] -> X ([(a, Rectangle)], Maybe (m a))
- XMonad.Layout.Master: mastered :: (LayoutClass l a) => Rational -> Rational -> l a -> Master l a
+ XMonad.Layout.Master: mastered :: (LayoutClass l a) => Rational -> Rational -> l a -> ModifiedLayout AddMaster l a
- XMonad.Layout.WindowNavigation: D :: Direction
+ XMonad.Layout.WindowNavigation: D :: Direction2D
- XMonad.Layout.WindowNavigation: Go :: Direction -> Navigate
+ XMonad.Layout.WindowNavigation: Go :: Direction2D -> Navigate
- XMonad.Layout.WindowNavigation: L :: Direction
+ XMonad.Layout.WindowNavigation: L :: Direction2D
- XMonad.Layout.WindowNavigation: Move :: Direction -> Navigate
+ XMonad.Layout.WindowNavigation: Move :: Direction2D -> Navigate
- XMonad.Layout.WindowNavigation: R :: Direction
+ XMonad.Layout.WindowNavigation: R :: Direction2D
- XMonad.Layout.WindowNavigation: Swap :: Direction -> Navigate
+ XMonad.Layout.WindowNavigation: Swap :: Direction2D -> Navigate
- XMonad.Layout.WindowNavigation: U :: Direction
+ XMonad.Layout.WindowNavigation: U :: Direction2D
- XMonad.Prompt: XPC :: String -> String -> String -> String -> String -> String -> !Dimension -> XPPosition -> !Dimension -> !Int -> String -> Maybe Int -> XPConfig
+ XMonad.Prompt: XPC :: String -> String -> String -> String -> String -> String -> !Dimension -> XPPosition -> !Dimension -> !Int -> ([String] -> [String]) -> Map (KeyMask, KeySym) (XP ()) -> KeySym -> String -> Maybe Int -> Bool -> XPConfig
- XMonad.Util.Run: safeSpawn :: (MonadIO m) => FilePath -> String -> m ()
+ XMonad.Util.Run: safeSpawn :: (MonadIO m) => FilePath -> [String] -> m ()

Files

README view
@@ -1,28 +1,82 @@-3rd party xmonad extensions and contributions.+  xmonad-contrib : third party extensions to the xmonad window manager -Build and install through Cabal as for other Haskell packages:+                           http://xmonad.org -        runhaskell Setup configure --user --prefix=$HOME-        runhaskell Setup build-        runhaskell Setup install --user+    You need the ghc compiler and xmonad window manager installed in+    order to use these extensions. -(You may want to remove the --user flag when installing as root.)+    For installation and configuration instructions, please see the+    xmonad website, the documents included with the xmonad source+    distribution, and online haddock documentation: -scripts/ contains further external programs useful with xmonad.+    http://www.xmonad.org/xmonad-docs -Haskell code contributed to this repo should live under the-appropriate subdivision of the 'XMonad.' namespace (currently includes-Actions, Config, Hooks, Layout, Prompt, and Util). For example, to use-the Mosaic layout, one would import:+------------------------------------------------------------------------ - XMonad.Layout.Mosaic+Changelogs +    For a list of changes since the 0.8.x releases, see:++http://www.haskell.org/haskellwiki/Xmonad/Notable_changes_since_0.8+ ------------------------------------------------------------------------ +Updates to XMonadContrib-0.9 that may Require Changes to ~/.xmonad/xmonad.hs++    Please see the Changelogs and xmonad-contrib haddock documentation+    links for further details regarding the following changes.++    * XMonad.Hooks.EwmhDesktops no longer uses layoutHook, the+    ewmhDesktopsLayout modifier has been removed from xmonad-contrib. It+    uses logHook, handleEventHook, and startupHook instead and provides+    a convenient function 'ewmh' to add EWMH support to a defaultConfig.++    * Most DynamicLog users can continue with configs unchanged, but users+    of the quickbar functions 'xmobar' or 'dzen' will need to change+    xmonad.hs: their types have changed to allow easier composition with+    other XConfig modifiers. The 'dynamicLogDzen' and 'dynamicLogXmobar'+    functions have been removed.++    * WindowGo or safeSpawn users may need to change command lines due to+    safeSpawn changes.++    * People explicitly referencing the "SP" scratchpad workspace should+    change it to "NSP" which is also used by the new Util.NamedScratchpad.++    * (Optional) People who explicitly use swapMaster in key or mouse+    bindings should change it to shiftMaster. It's the current default+    used where swapMaster had been used previously. It works better than+    swapMaster when using floating and tiled windows together on the+    same workspace.++------------------------------------------------------------------------++Getting or updating XMonadContrib++    latest release: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/xmonad-contrib++    darcs version:  darcs get http://code.haskell.org/XMonadContrib++    (To use darcs xmonad-contrib you must also use the darcs version+    of xmonad.)++------------------------------------------------------------------------++Contributing++    Haskell code contributed to this repo should live under the+    appropriate subdivision of the 'XMonad.' namespace (currently+    includes Actions, Config, Hooks, Layout, Prompt, and Util). For+    example, to use the Grid layout, one would import:++        XMonad.Layout.Grid++    For further details, see the documentation for the+    XMonad.Doc.Developing module and http://xmonad.org website.++------------------------------------------------------------------------+ Code submitted to the contrib repo is licensed under the same license as xmonad itself, with copyright held by the authors.  --------------------------------------------------------------------------Documentation for the extensions and configuration system is available-in Haddock form in the XMonad.Doc module and submodules.
XMonad/Actions/Commands.hs view
@@ -41,7 +41,7 @@ -- -- Then add a keybinding to the runCommand action: ----- >    , ((modMask x .|. controlMask, xK_y), commands >>= runCommand)+-- >    , ((modm .|. controlMask, xK_y), commands >>= runCommand) -- -- and define the list of commands you want to use: --@@ -82,23 +82,22 @@     wscmds <- workspaceCommands     return $ wscmds ++ screenCommands ++ otherCommands  where-    sr = broadcastMessage ReleaseResources     otherCommands =         [ ("shrink"              , sendMessage Shrink                               )         , ("expand"              , sendMessage Expand                               )         , ("next-layout"         , sendMessage NextLayout                           )         , ("default-layout"      , asks (layoutHook . config) >>= setLayout         )-        , ("restart-wm"          , sr >> restart "xmonad" True                       )-        , ("restart-wm-no-resume", sr >> restart "xmonad" False                      )+        , ("restart-wm"          , restart "xmonad" True                            )+        , ("restart-wm-no-resume", restart "xmonad" False                           )         , ("xterm"               , spawn =<< asks (terminal .  config)              )         , ("run"                 , spawn "exe=`dmenu_path | dmenu -b` && exec $exe" )         , ("kill"                , kill                                             )         , ("refresh"             , refresh                                          )-        , ("focus-up"            , windows $ focusUp                                )-        , ("focus-down"          , windows $ focusDown                              )-        , ("swap-up"             , windows $ swapUp                                 )-        , ("swap-down"           , windows $ swapDown                               )-        , ("swap-master"         , windows $ swapMaster                             )+        , ("focus-up"            , windows focusUp                                  )+        , ("focus-down"          , windows focusDown                                )+        , ("swap-up"             , windows swapUp                                   )+        , ("swap-down"           , windows swapDown                                 )+        , ("swap-master"         , windows swapMaster                               )         , ("sink"                , withFocused $ windows . sink                     )         , ("quit-wm"             , io $ exitWith ExitSuccess                        )         ]
XMonad/Actions/ConstrainedResize.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  <dougal@dougalstanton.net>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- Lets you constrain the aspect ratio of a floating@@ -31,8 +31,8 @@ -- -- Then add something like the following to your mouse bindings: ----- >     , ((modMask x, button3),               (\w -> focus w >> Sqr.mouseResizeWindow w False))--- >     , ((modMask x .|. shiftMask, button3), (\w -> focus w >> Sqr.mouseResizeWindow w True ))+-- >     , ((modm, button3),               (\w -> focus w >> Sqr.mouseResizeWindow w False))+-- >     , ((modm .|. shiftMask, button3), (\w -> focus w >> Sqr.mouseResizeWindow w True )) -- -- The line without the shiftMask replaces the standard mouse resize -- function call, so it's not completely necessary but seems neater
XMonad/Actions/CopyWindow.hs view
@@ -2,14 +2,14 @@ ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Actions.CopyWindow--- Copyright   :  (c) David Roundy <droundy@darcs.net>, Ivan Veselov <veselov@gmail.com>+-- Copyright   :  (c) David Roundy <droundy@darcs.net>, Ivan Veselov <veselov@gmail.com>, Lanny Ripple <lan3ny@gmail.com> -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  ??? -- Stability   :  unstable -- Portability :  unportable ----- Provides a binding to duplicate a window on multiple workspaces,+-- Provides bindings to duplicate a window on multiple workspaces, -- providing dwm-like tagging functionality. -- -----------------------------------------------------------------------------@@ -17,14 +17,21 @@ module XMonad.Actions.CopyWindow (                                  -- * Usage                                  -- $usage-                                 copy, copyToAll, copyWindow, killAllOtherCopies, kill1+                                 copy, copyToAll, copyWindow, runOrCopy+                                 , killAllOtherCopies, kill1+                                 -- * Highlight workspaces containing copies in logHook+                                 -- $logHook+                                 , wsContainingCopies                                 ) where -import Prelude hiding (filter)+import XMonad+import Control.Arrow ((&&&))+import Control.Monad import qualified Data.List as L-import XMonad hiding (modify, workspaces)-import XMonad.StackSet +import XMonad.Actions.WindowGo+import qualified XMonad.StackSet as W+ -- $usage -- -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:@@ -36,7 +43,7 @@ -- > -- mod-[1..9] @@ Switch to workspace N -- > -- mod-shift-[1..9] @@ Move client to workspace N -- > -- mod-control-shift-[1..9] @@ Copy client to workspace N--- > [((m .|. modMask x, k), windows $ f i)+-- > [((m .|. modm, k), windows $ f i) -- >     | (i, k) <- zip (workspaces x) [xK_1 ..] -- >     , (f, m) <- [(W.view, 0), (W.shift, shiftMask), (copy, shiftMask .|. controlMask)]] --@@ -48,8 +55,13 @@ -- You may also wish to redefine the binding to kill a window so it only -- removes it from the current workspace, if it's present elsewhere: ----- >  , ((modMask x .|. shiftMask, xK_c     ), kill1) -- @@ Close the focused window+-- >  , ((modm .|. shiftMask, xK_c     ), kill1) -- @@ Close the focused window --+-- Instead of copying a window from one workspace to another maybe you don't+-- want to have to remember where you placed it.  For that consider:+--+-- >  , ((modm, xK_b    ), runOrCopy "firefox" (className =? "Firefox")) -- @@ run or copy firefox+-- -- Another possibility which this extension provides is 'making window -- always visible' (i.e. always on current workspace), similar to corresponding -- metacity functionality. This behaviour is emulated through copying given@@ -58,59 +70,95 @@ -- -- Here is the example of keybindings which provide these actions: ----- >  , ((modMask x, xK_v )", windows copyToAll) -- @@ Make focused window always visible--- >  , ((modMask x .|. shiftMask, xK_v ),  killAllOtherCopies) -- @@ Toggle window state back+-- >  , ((modm, xK_v ), windows copyToAll) -- @@ Make focused window always visible+-- >  , ((modm .|. shiftMask, xK_v ),  killAllOtherCopies) -- @@ Toggle window state back -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". --- | copy. Copy the focussed window to a new workspace.-copy :: (Eq s, Eq i, Eq a) => i -> StackSet i l a s sd -> StackSet i l a s sd-copy n s | Just w <- peek s = copyWindow w n s+-- $logHook+-- To distinguish workspaces containing copies of the focused window use+-- something like:+--+-- > sampleLogHook h = do+-- >    copies <- wsContainingCopies+-- >    let check ws | ws `elem` copies = pad . xmobarColor "red" "black" $ ws+-- >                 | otherwise = pad ws+-- >    dynamicLogWithPP myPP {ppHidden = check, ppOutput = hPutStrLn h}+-- >+-- > main = do+-- >    h <- spawnPipe "xmobar"+-- >    xmonad defaultConfig { logHook = sampleLogHook h }++-- | Copy the focused window to a workspace.+copy :: (Eq s, Eq i, Eq a) => i -> W.StackSet i l a s sd -> W.StackSet i l a s sd+copy n s | Just w <- W.peek s = copyWindow w n s          | otherwise = s --- | copyToAll. Copy the focused window to all of workspaces.-copyToAll :: (Eq s, Eq i, Eq a) => StackSet i l a s sd -> StackSet i l a s sd-copyToAll s = foldr copy s $ map tag (workspaces s)+-- | Copy the focused window to all workspaces.+copyToAll :: (Eq s, Eq i, Eq a) => W.StackSet i l a s sd -> W.StackSet i l a s sd+copyToAll s = foldr copy s $ map W.tag (W.workspaces s) --- | copyWindow.  Copy a window to a new workspace-copyWindow :: (Eq a, Eq i, Eq s) => a -> i -> StackSet i l a s sd -> StackSet i l a s sd+-- | Copy an arbitrary window to a workspace.+copyWindow :: (Eq a, Eq i, Eq s) => a -> i -> W.StackSet i l a s sd -> W.StackSet i l a s sd copyWindow w n = copy'-    where copy' s = if n `tagMember` s-                    then view (tag (workspace (current s))) $ insertUp' w $ view n s+    where copy' s = if n `W.tagMember` s+                    then W.view (W.currentTag s) $ insertUp' w $ W.view n s                     else s-          insertUp' a s = modify (Just $ Stack a [] [])-                          (\(Stack t l r) -> if a `elem` t:l++r-                                             then Just $ Stack t l r-                                             else Just $ Stack a (L.delete a l) (L.delete a (t:r))) s+          insertUp' a s = W.modify (Just $ W.Stack a [] [])+                          (\(W.Stack t l r) -> if a `elem` t:l++r+                                             then Just $ W.Stack t l r+                                             else Just $ W.Stack a (L.delete a l) (L.delete a (t:r))) s  +-- | runOrCopy will run the provided shell command unless it can+--  find a specified window in which case it will copy the window to+--  the current workspace.  Similar to (i.e., stolen from) "XMonad.Actions.WindowGo".+runOrCopy :: String -> Query Bool -> X ()+runOrCopy = copyMaybe . spawn++-- | Copy a window if it exists, run the first argument otherwise.+copyMaybe :: X () -> Query Bool -> X ()+copyMaybe f qry = ifWindow qry copyWin f+    where copyWin = ask >>= \w -> doF (\ws -> copyWindow w (W.currentTag ws) ws)+ -- | Remove the focused window from this workspace.  If it's present in no -- other workspace, then kill it instead. If we do kill it, we'll get a -- delete notify back from X. -- -- There are two ways to delete a window. Either just kill it, or if it--- supports the delete protocol, send a delete event (e.g. firefox)---+-- supports the delete protocol, send a delete event (e.g. firefox). kill1 :: X () kill1 = do ss <- gets windowset-           whenJust (peek ss) $ \w -> if member w $ delete'' w ss+           whenJust (W.peek ss) $ \w -> if W.member w $ delete'' w ss                                       then windows $ delete'' w                                       else kill-    where delete'' w = modify Nothing (filter (/= w))+    where delete'' w = W.modify Nothing (W.filter (/= w)) --- | Kill all other copies of focused window (if they're present)--- 'All other' means here 'copies, which are not on current workspace'------ Consider calling this function after copyToAll---+-- | Kill all other copies of focused window (if they're present).+-- 'All other' means here 'copies which are not on the current workspace'. killAllOtherCopies :: X () killAllOtherCopies = do ss <- gets windowset-                        whenJust (peek ss) $ \w -> windows $-                                                   view (tag (workspace (current ss))) .+                        whenJust (W.peek ss) $ \w -> windows $+                                                   W.view (W.currentTag ss) .                                                    delFromAllButCurrent w     where       delFromAllButCurrent w ss = foldr ($) ss $-                                  map (delWinFromWorkspace w . tag) $-                                  hidden ss ++ map workspace (visible ss)-      delWinFromWorkspace w wid ss = modify Nothing (filter (/= w)) $ view wid ss+                                  map (delWinFromWorkspace w . W.tag) $+                                  W.hidden ss ++ map W.workspace (W.visible ss)+      delWinFromWorkspace w wid = W.modify Nothing (W.filter (/= w)) . W.view wid++-- | A list of hidden workspaces containing a copy of the focused window.+wsContainingCopies :: X [WorkspaceId]+wsContainingCopies = do+    ws <- gets windowset+    return $ copiesOfOn (W.peek ws) (taggedWindows $ W.hidden ws)++-- | Get a list of tuples (tag, [Window]) for each workspace.+taggedWindows :: [W.Workspace i l a] -> [(i, [a])]+taggedWindows = map $ W.tag &&& W.integrate' . W.stack++-- | Get tags with copies of the focused window (if present.)+copiesOfOn :: (Eq a) => Maybe a -> [(i, [a])] -> [i]+copiesOfOn foc tw = maybe [] hasCopyOf foc+  where hasCopyOf f = map fst $ filter ((f `elem` ) . snd) tw
XMonad/Actions/CycleRecentWS.hs view
@@ -30,7 +30,7 @@ -- -- > import XMonad.Actions.CycleRecentWS -- >--- >   , ((modMask x, xK_Tab), cycleRecentWS [xK_Alt_L] xK_Tab xK_grave)+-- >   , ((modm, xK_Tab), cycleRecentWS [xK_Alt_L] xK_Tab xK_grave) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
XMonad/Actions/CycleSelectedLayouts.hs view
@@ -25,12 +25,12 @@  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:--- +-- -- > import XMonad hiding ((|||)) -- > import XMonad.Layout.LayoutCombinators ((|||)) -- > import XMonad.Actions.CycleSelectedLayouts ----- >   , ((modMask x,  xK_t ),   cycleThroughLayouts ["Tall", "Mirror Tall"])+-- >   , ((modm,  xK_t ),   cycleThroughLayouts ["Tall", "Mirror Tall"]) -- -- Make sure you are using NewSelect from XMonad.Layout.LayoutCombinators, -- rather than the Select defined in xmonad core.
XMonad/Actions/CycleWS.hs view
@@ -42,7 +42,11 @@                               , prevWS                               , shiftToNext                               , shiftToPrev++                                -- * Toggling the previous workspace+                                -- $toggling                               , toggleWS+                              , toggleOrView                                  -- * Moving between screens (xinerama) @@ -56,7 +60,7 @@                                 -- * Moving between workspaces, take two!                                 -- $taketwo -                              , WSDirection(..)+                              , Direction1D(..)                               , WSType(..)                                , shiftTo@@ -65,14 +69,18 @@                                 -- * The mother-combinator                                , findWorkspace+                              , toggleOrDoSkip+                              , skipTags                               ) where +import Control.Monad ( unless ) import Data.List ( findIndex ) import Data.Maybe ( isNothing, isJust )  import XMonad hiding (workspaces) import XMonad.StackSet hiding (filter)+import XMonad.Util.Types import XMonad.Util.WorkspaceCompare  -- $usage@@ -82,27 +90,27 @@ -- > -- > -- a basic CycleWS setup -- >--- >   , ((modMask x,               xK_Down),  nextWS)--- >   , ((modMask x,               xK_Up),    prevWS)--- >   , ((modMask x .|. shiftMask, xK_Down),  shiftToNext)--- >   , ((modMask x .|. shiftMask, xK_Up),    shiftToPrev)--- >   , ((modMask x,               xK_Right), nextScreen)--- >   , ((modMask x,               xK_Left),  prevScreen)--- >   , ((modMask x .|. shiftMask, xK_Right), shiftNextScreen)--- >   , ((modMask x .|. shiftMask, xK_Left),  shiftPrevScreen)--- >   , ((modMask x,               xK_z),     toggleWS)+-- >   , ((modm,               xK_Down),  nextWS)+-- >   , ((modm,               xK_Up),    prevWS)+-- >   , ((modm .|. shiftMask, xK_Down),  shiftToNext)+-- >   , ((modm .|. shiftMask, xK_Up),    shiftToPrev)+-- >   , ((modm,               xK_Right), nextScreen)+-- >   , ((modm,               xK_Left),  prevScreen)+-- >   , ((modm .|. shiftMask, xK_Right), shiftNextScreen)+-- >   , ((modm .|. shiftMask, xK_Left),  shiftPrevScreen)+-- >   , ((modm,               xK_z),     toggleWS) -- -- If you want to follow the moved window, you can use both actions: ----- >   , ((modMask x .|. shiftMask, xK_Down), shiftToNext >> nextWS)--- >   , ((modMask x .|. shiftMask, xK_Up),   shiftToPrev >> prevWS)+-- >   , ((modm .|. shiftMask, xK_Down), shiftToNext >> nextWS)+-- >   , ((modm .|. shiftMask, xK_Up),   shiftToPrev >> prevWS) -- -- You can also get fancier with 'moveTo', 'shiftTo', and 'findWorkspace'. -- For example: ----- >   , ((modMask x     , xK_f), moveTo Next EmptyWS)  -- find a free workspace--- >   , ((modMask x .|. controlMask, xK_Right),        -- a crazy keybinding!--- >         do t <- findWorkspace getXineramaWsCompare Next NonEmptyWS 2+-- >   , ((modm     , xK_f), moveTo Next EmptyWS)  -- find a free workspace+-- >   , ((modm .|. controlMask, xK_Right),        -- a crazy keybinding!+-- >         do t <- findWorkspace getSortByXineramaRule Next NonEmptyWS 2 -- >            windows . view $ t                                         ) -- -- For detailed instructions on editing your key bindings, see@@ -135,10 +143,48 @@ shiftToPrev :: X () shiftToPrev = shiftBy (-1) +-- $toggling+ -- | Toggle to the workspace displayed previously. toggleWS :: X ()-toggleWS = windows $ view =<< tag . head . hidden+toggleWS = do+    hs <- gets (hidden . windowset)+    unless (null hs) (windows . view . tag $ head hs) +-- | 'XMonad.StackSet.greedyView' a workspace, or if already there, view+-- the previously displayed workspace ala weechat. Change @greedyView@ to+-- @toggleOrView@ in your workspace bindings as in the 'XMonad.StackSet.view'+-- faq at <http://haskell.org/haskellwiki/Xmonad/Frequently_asked_questions>.+-- For more flexibility see 'toggleOrDoSkip'.+toggleOrView :: WorkspaceId -> X ()+toggleOrView = toggleOrDoSkip [] greedyView++-- | Allows ignoring listed workspace tags (such as scratchpad's \"NSP\") while+-- finding the previously displayed workspace, or choice of different actions,+-- like view, shift, etc.  For example:+--+-- > import qualified XMonad.StackSet as W+-- > import XMonad.Actions.CycleWS+-- >+-- > -- toggleOrView for people who prefer view to greedyView+-- > toggleOrView' = toggleOrDoSkip [] W.view+-- >+-- > -- toggleOrView ignoring scratchpad and named scratchpad workspace+-- > toggleOrViewNoSP = toggleOrDoSkip ["NSP"] W.greedyView+toggleOrDoSkip :: [WorkspaceId] -> (WorkspaceId -> WindowSet -> WindowSet)+                                  -> WorkspaceId -> X ()+toggleOrDoSkip skips f toWS = do+    ws <- gets windowset+    let hs' = hidden ws `skipTags` skips+    if toWS == (tag . workspace $ current ws)+        then unless (null hs') (windows . f . tag $ head hs')+        else windows (f toWS)++-- | List difference ('\\') for workspaces and tags. Removes workspaces+-- matching listed tags from the given workspace list.+skipTags :: (Eq i) => [Workspace i l a] -> [i] -> [Workspace i l a]+skipTags wss ids = filter ((`notElem` ids) . tag) wss+ switchWorkspace :: Int -> X () switchWorkspace d = wsBy d >>= windows . greedyView @@ -166,12 +212,10 @@  -} --- | Direction to cycle through the sort order.-data WSDirection = Next | Prev- -- | What type of workspaces should be included in the cycle? data WSType = EmptyWS     -- ^ cycle through empty workspaces             | NonEmptyWS  -- ^ cycle through non-empty workspaces+            | HiddenWS    -- ^ cycle through non-visible workspaces             | HiddenNonEmptyWS  -- ^ cycle through non-empty non-visible workspaces             | AnyWS       -- ^ cycle through all workspaces             | WSIs (X (WindowSpace -> Bool))@@ -182,19 +226,22 @@ wsTypeToPred :: WSType -> X (WindowSpace -> Bool) wsTypeToPred EmptyWS    = return (isNothing . stack) wsTypeToPred NonEmptyWS = return (isJust . stack)-wsTypeToPred HiddenNonEmptyWS = do hs <- gets (map tag . hidden . windowset)-                                   return (\w -> isJust (stack w) && tag w `elem` hs)+wsTypeToPred HiddenWS   = do hs <- gets (map tag . hidden . windowset)+                             return (\w -> tag w `elem` hs)+wsTypeToPred HiddenNonEmptyWS  = do ne <- wsTypeToPred NonEmptyWS+                                    hi <- wsTypeToPred HiddenWS+                                    return (\w -> hi w && ne w) wsTypeToPred AnyWS      = return (const True) wsTypeToPred (WSIs p)   = p  -- | View the next workspace in the given direction that satisfies --   the given condition.-moveTo :: WSDirection -> WSType -> X ()+moveTo :: Direction1D -> WSType -> X () moveTo dir t = findWorkspace getSortByIndex dir t 1 >>= windows . greedyView  -- | Move the currently focused window to the next workspace in the --   given direction that satisfies the given condition.-shiftTo :: WSDirection -> WSType -> X ()+shiftTo :: Direction1D -> WSType -> X () shiftTo dir t = findWorkspace getSortByIndex dir t 1 >>= windows . shift  -- | Given a function @s@ to sort workspaces, a direction @dir@, a@@ -210,14 +257,14 @@ --   that 'moveTo' and 'shiftTo' are implemented by applying @(>>= --   (windows . greedyView))@ and @(>>= (windows . shift))@, respectively, --   to the output of 'findWorkspace'.-findWorkspace :: X WorkspaceSort -> WSDirection -> WSType -> Int -> X WorkspaceId+findWorkspace :: X WorkspaceSort -> Direction1D -> WSType -> Int -> X WorkspaceId findWorkspace s dir t n = findWorkspaceGen s (wsTypeToPred t) (maybeNegate dir n)   where     maybeNegate Next d = d     maybeNegate Prev d = (-d)  findWorkspaceGen :: X WorkspaceSort -> X (WindowSpace -> Bool) -> Int -> X WorkspaceId-findWorkspaceGen _ _ 0 = (tag . workspace . current) `fmap` gets windowset+findWorkspaceGen _ _ 0 = gets (currentTag . windowset) findWorkspaceGen sortX wsPredX d = do     wsPred <- wsPredX     sort   <- sortX@@ -225,7 +272,7 @@     let cur     = workspace (current ws)         sorted  = sort (workspaces ws)         pivoted = let (a,b) = span ((/= (tag cur)) . tag) sorted in b ++ a-        ws'     = filter wsPred $ pivoted+        ws'     = filter wsPred pivoted         mCurIx  = findWsIndex cur ws'         d'      = if d > 0 then d - 1 else d         next    = if null ws'
+ XMonad/Actions/CycleWindows.hs view
@@ -0,0 +1,233 @@+--------------------------------------------------------------------------------+-- |+-- Module       : XMonad.Actions.CycleWindows+-- Copyright    : (c) Wirt Wolff <wirtwolff@gmail.com>+-- License      : BSD3-style (see LICENSE)+--+-- Maintainer   : Wirt Wolff <wirtwolff@gmail.com>+-- Stability    : unstable+-- Portability  : unportable+--+-- Provides bindings to cycle windows up or down on the current workspace+-- stack while maintaining focus in place.+--+-- Bindings are available to:+--+-- * Cycle nearby or nth windows into the focused frame+--+-- * Cycle a window halfway around the stack+--+-- * Cycle windows through the focused position.+--+-- * Cycle unfocused windows.+--+-- These bindings are especially useful with layouts that hide some of+-- the windows in the stack, such as Full, "XMonad.Layout.TwoPane" or+-- when using "XMonad.Layout.LimitWindows" to only show three or four+-- panes. See also "XMonad.Actions.RotSlaves" for related actions.+-----------------------------------------------------------------------------+module XMonad.Actions.CycleWindows (+        -- * Usage+        -- $usage++        -- * Cycling nearby or nth window into current frame+        -- $cycle+        cycleRecentWindows,+        cycleStacks',+        -- * Cycling half the stack to get rid of a boring window+        -- $opposite+        rotOpposite', rotOpposite,+        -- * Cycling windows through the current frame+        -- $focused+        rotFocused', rotFocusedUp, rotFocusedDown, shiftToFocus',+        -- * Cycling windows through other frames+        -- $unfocused+        rotUnfocused', rotUnfocusedUp, rotUnfocusedDown,+        -- * Updating the mouse pointer+        -- $pointer++        -- * Generic list rotations+        -- $generic+        rotUp, rotDown+) where++import XMonad+import qualified XMonad.StackSet as W+import XMonad.Actions.RotSlaves++import Control.Arrow (second)++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:+--+-- > import XMonad.Actions.CycleWindows+-- >    -- config+-- >    -- other key bindings with x here your config+-- >+-- >              -- make sure mod matches keysym+-- >  , ((mod4Mask,  xK_s), cycleRecentWindows [xK_Super_L] xK_s xK_w)+-- >  , ((modm, xK_z), rotOpposite)+-- >  , ((modm                , xK_i), rotUnfocusedUp)+-- >  , ((modm                , xK_u), rotUnfocusedDown)+-- >  , ((modm .|. controlMask, xK_i), rotFocusedUp)+-- >  , ((modm .|. controlMask, xK_u), rotFocusedDown)+--+-- Also, if you use focus follows mouse, you will want to read the section+-- on updating the mouse pointer below.  For detailed instructions on+-- editing your key bindings, see "XMonad.Doc.Extending#Editing_key_bindings".+{- $pointer+With FocusFollowsMouse == True, the focus is updated after binding+actions, possibly focusing a window you didn't intend to focus. Most+people using TwoPane probably already have a logHook causing the mouse+to follow focus. (See "XMonad.Actions.UpdatePointer", or "XMonad.Actions.Warp")++If you want this built into the key binding instead, use the appropriate+action from one of those modules to also have your bindings move the pointer+to the point of your choice on the current window:++> import XMonad.Actions.UpdatePointer -- or Actions.Warp++and either++> -- modify the window rotation bindings+> , ((modm .|. controlMask, xK_i   ), rotFocusedUp+>                                            >> updatePointer (Relative 1 1))+> , ((modm .|. controlMask, xK_u   ), rotFocusedDown+>                                            >> updatePointer (Relative 1 1))+>+>    -- or add to xmonad's logHook+>    , logHook = dynamicLogWithPP xmobarPP+>                    >> updatePointer Nearest -- or your preference++-}++-- $cycle+-- Cycle windows into focus from below or above the focused pane by pressing+-- a key while one or more modifier keys is held down. The window order isn't+-- changed until a modifier is released, leaving the previously focused window+-- just below the new one, (or above if the window just above is chosen.) For+-- best results use the same modifier + key combination as the one used to invoke+-- the \"bring from below\" action.  Also, once cycling, pressing a number key n+-- will focus the nth window, with 0 being the one originally focused.+cycleRecentWindows :: [KeySym] -- ^ A list of modifier keys used when invoking this action.+                               --   As soon as one of them is released, the final switch is made.+                    -> KeySym  -- ^ Key used to shift windows from below the current choice into the current frame.+                    -> KeySym  -- ^ Key used to shift windows from above the current choice into the current frame.+                               --   If it's the same as the first key, it is effectively ignored.+                    -> X ()+cycleRecentWindows = cycleStacks' stacks where+    stacks s = map (shiftToFocus' `flip` s) (wins s)+    wins (W.Stack t l r) = t : r ++ reverse l+++-- | Cycle through a /finite/ list of window stacks with repeated presses+--   of a key while a modifier key is held down. For best results use the same+--   mod key + key combination as the one used to invoke the \"bring from below\"+--   action. You could use cycleStacks' with a different stack permutations+--   function to, for example, cycle from one below to one above to two below,+--   etc. instead of in order. You are responsible for having it generate a+--   finite list, though, or xmonad may hang seeking its length.+cycleStacks' :: (W.Stack Window -> [W.Stack Window]) -- ^ A function to a finite list of permutations of a given stack.+                                    -> [KeySym]  -- ^ A list of modifier keys used to invoke 'cycleStacks''.+                                                 --   As soon as any is released, we're no longer cycling on the [Stack Window]+                                    -> KeySym    -- ^ Key used to select a \"next\" stack.+                                    -> KeySym    -- ^ Key used to select a \"previous\" stack.+                                    -> X ()+cycleStacks' filteredPerms mods keyNext keyPrev = do+    XConf {theRoot = root, display = d} <- ask+    stacks <- gets $ maybe [] filteredPerms . W.stack . W.workspace . W.current . windowset++    let evt = allocaXEvent $+                  \p -> do maskEvent d (keyPressMask .|. keyReleaseMask) p+                           KeyEvent {ev_event_type = t, ev_keycode = c} <- getEvent p+                           s <- keycodeToKeysym d c 0+                           return (t, s)+        choose n (t, s)+              | t == keyPress   && s == keyNext  = io evt >>= choose (n+1)+              | t == keyPress   && s == keyPrev  = io evt >>= choose (n-1)+              | t == keyPress   && s `elem` [xK_0..xK_9] = io evt >>= choose (numKeyToN s)+              | t == keyRelease && s `elem` mods = return ()+              | otherwise                        = doStack n >> io evt >>= choose n+        doStack n = windows . W.modify' . const $ stacks `cycref` n++    io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime+    io evt >>= choose 1+    io $ ungrabKeyboard d currentTime+  where cycref l i = l !! (i `mod` length l) -- modify' ensures l is never [], but must also be finite+        numKeyToN = subtract 48 . read . show++-- | Given a stack element and a stack, shift or insert the element (window)+--   at the currently focused position.+shiftToFocus' :: (Eq a, Show a, Read a) => a -> W.Stack a -> W.Stack a+shiftToFocus' w s@(W.Stack _ ls _) = W.Stack w (reverse revls') rs'+  where (revls', rs') = splitAt (length ls) . filter (/= w) $ W.integrate s+++-- $opposite+-- Shifts the focused window as far as possible from the current focus,+-- i.e. halfway around the stack. Windows above the focus up to the \"opposite\"+-- position remain in place, while those above the insertion shift toward+-- the current focus. This is useful for people who use lots of windows in Full,+-- TwoPane, etc., to get rid of boring windows while cycling and swapping+-- near the focus.+rotOpposite :: X()+rotOpposite = windows $ W.modify' rotOpposite'++-- | The opposite rotation on a Stack.+rotOpposite' :: W.Stack a -> W.Stack a+rotOpposite' (W.Stack t l r) = W.Stack t' l' r'+  where rrvl = r ++ reverse l+        part = (length rrvl + 1) `div` 2+        (l',t':r') =  second reverse . splitAt (length l) $+                                reverse (take part rrvl ++ t : drop part rrvl)+++-- $focused+-- Most people will want the @rotAllUp@ or @rotAllDown@ actions from+-- "XMonad.Actions.RotSlaves" to cycle all windows in the stack.+--+-- The following actions keep the \"next\" window stable, which is+-- mostly useful in two window layouts, or when you have a log viewer or+-- buffer window you want to keep next to the cycled window.++-- | Rotate windows through the focused frame, excluding the \"next\" window.+-- With, e.g. TwoPane, this allows cycling windows through either the+-- master or slave pane, without changing the other frame. When the master+-- is focused, the window below is skipped, when a non-master window is+-- focused, the master is skipped.+rotFocusedUp :: X ()+rotFocusedUp = windows . W.modify' $ rotFocused' rotUp+rotFocusedDown :: X ()+rotFocusedDown = windows . W.modify' $ rotFocused' rotDown++-- | The focused rotation on a stack.+rotFocused' :: ([a] -> [a]) -> W.Stack a -> W.Stack a+rotFocused' _ s@(W.Stack _ [] []) = s+rotFocused' f   (W.Stack t [] (r:rs)) = W.Stack t' [] (r:rs') -- Master has focus+    where (t':rs') = f (t:rs)+rotFocused' f s@(W.Stack _ _ _) = rotSlaves' f s              -- otherwise+++-- $unfocused+-- Rotate windows through the unfocused frames. This is similar to+-- @rotSlaves@, from "XMonad.Actions.RotSlaves", but excludes the current+-- frame rather than master.+rotUnfocusedUp :: X ()+rotUnfocusedUp = windows . W.modify' $ rotUnfocused' rotUp+rotUnfocusedDown :: X ()+rotUnfocusedDown = windows . W.modify' $ rotUnfocused' rotDown++-- | The unfocused rotation on a stack.+rotUnfocused' :: ([a] -> [a]) -> W.Stack a -> W.Stack a+rotUnfocused' _ s@(W.Stack _ [] []) = s+rotUnfocused' f s@(W.Stack _ [] _ ) = rotSlaves' f s                 -- Master has focus+rotUnfocused' f   (W.Stack t ls rs) = W.Stack t (reverse revls') rs' -- otherwise+    where  (master:revls)  = reverse ls+           (revls',rs') = splitAt (length ls) (f $ master:revls ++ rs)++-- $generic+-- Generic list rotations+rotUp :: [a] -> [a]+rotUp   l = tail l ++ [head l]+rotDown :: [a] -> [a]+rotDown l = last l : init l
XMonad/Actions/DeManage.hs view
@@ -5,12 +5,13 @@ -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  Spencer Janssen <spencerjanssen@gmail.com>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- This module provides a method to cease management of a window -- without unmapping it.  This is especially useful for applications--- like kicker and gnome-panel.+-- like kicker and gnome-panel.  See also "XMonad.Hooks.ManageDocks" for+-- more a more automated solution. -- -- To make a panel display correctly with xmonad: --@@ -43,7 +44,7 @@ -- -- And add a keybinding, such as: ----- > , ((modMask x,               xK_d     ), withFocused demanage)+-- > , ((modm,               xK_d     ), withFocused demanage) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
XMonad/Actions/DwmPromote.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  arcatan@kapsi.fi--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- Dwm-like swap function for xmonad.@@ -33,7 +33,7 @@ -- -- then add a keybinding or substitute 'dwmpromote' in place of promote: ----- >   , ((modMask x,               xK_Return), dwmpromote)+-- >   , ((modm,               xK_Return), dwmpromote) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
XMonad/Actions/DynamicWorkspaces.hs view
@@ -36,18 +36,18 @@ -- -- Then add keybindings like the following: ----- >   , ((modMask x .|. shiftMask, xK_BackSpace), removeWorkspace)--- >   , ((modMask x .|. shiftMask, xK_v      ), selectWorkspace defaultXPConfig)--- >   , ((modMask x, xK_m                    ), withWorkspace defaultXPConfig (windows . W.shift))--- >   , ((modMask x .|. shiftMask, xK_m      ), withWorkspace defaultXPConfig (windows . copy))--- >   , ((modMask x .|. shiftMask, xK_r      ), renameWorkspace defaultXPConfig)+-- >   , ((modm .|. shiftMask, xK_BackSpace), removeWorkspace)+-- >   , ((modm .|. shiftMask, xK_v      ), selectWorkspace defaultXPConfig)+-- >   , ((modm, xK_m                    ), withWorkspace defaultXPConfig (windows . W.shift))+-- >   , ((modm .|. shiftMask, xK_m      ), withWorkspace defaultXPConfig (windows . copy))+-- >   , ((modm .|. shiftMask, xK_r      ), renameWorkspace defaultXPConfig) -- -- > -- mod-[1..9]       %! Switch to workspace N -- > -- mod-shift-[1..9] %! Move client to workspace N -- >    ++--- >    zip (zip (repeat (modMask x)) [xK_1..xK_9]) (map (withNthWorkspace W.greedyView) [0..])+-- >    zip (zip (repeat (modm)) [xK_1..xK_9]) (map (withNthWorkspace W.greedyView) [0..]) -- >    ++--- >    zip (zip (repeat (modMask x .|. shiftMask)) [xK_1..xK_9]) (map (withNthWorkspace W.shift) [0..])+-- >    zip (zip (repeat (modm .|. shiftMask)) [xK_1..xK_9]) (map (withNthWorkspace W.shift) [0..]) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
XMonad/Actions/FindEmptyWorkspace.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  arcatan@kapsi.fi--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- Find an empty workspace.@@ -32,8 +32,8 @@ -- -- and add the desired keybindings, for example: -----  >   , ((modMask x,                xK_m    ), viewEmptyWorkspace)---  >   , ((modMask x .|. shiftMask,  xK_m    ), tagToEmptyWorkspace)+--  >   , ((modm,                xK_m    ), viewEmptyWorkspace)+--  >   , ((modm .|. shiftMask,  xK_m    ), tagToEmptyWorkspace) -- -- Now you can jump to an empty workspace with @mod-m@. @Mod-shift-m@ -- will tag the current window to an empty workspace and view it.
XMonad/Actions/FlexibleManipulate.hs view
@@ -7,7 +7,7 @@ -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  <mgsloan@gmail.com>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- Move and resize floating windows without warping the mouse.@@ -31,7 +31,7 @@ -- -- Now set up the desired mouse binding, for example: ----- >     , ((modMask x, button1), (\w -> focus w >> Flex.mouseWindow Flex.linear w))+-- >     , ((modm, button1), (\w -> focus w >> Flex.mouseWindow Flex.linear w)) -- -- * Flex.'linear' indicates that positions between the edges and the --   middle indicate a combination scale\/position.
XMonad/Actions/FlexibleResize.hs view
@@ -15,7 +15,8 @@ module XMonad.Actions.FlexibleResize (         -- * Usage         -- $usage-        XMonad.Actions.FlexibleResize.mouseResizeWindow+        XMonad.Actions.FlexibleResize.mouseResizeWindow,+        XMonad.Actions.FlexibleResize.mouseResizeEdgeWindow ) where  import XMonad@@ -28,40 +29,53 @@ -- -- Then add an appropriate mouse binding: ----- >     , ((modMask x, button3), (\w -> focus w >> Flex.mouseResizeWindow w))+-- >     , ((modm, button3), (\w -> focus w >> Flex.mouseResizeWindow w)) -- -- For detailed instructions on editing your mouse bindings, see -- "XMonad.Doc.Extending#Editing_mouse_bindings".  -- | Resize a floating window from whichever corner the mouse is --   closest to.-mouseResizeWindow :: Window -> X ()-mouseResizeWindow w = whenX (isClient w) $ withDisplay $ \d -> do+mouseResizeWindow+  :: Window -- ^ The window to resize.+  -> X ()+mouseResizeWindow = mouseResizeEdgeWindow 0+++-- | Resize a floating window from whichever corner or edge the mouse is+--   closest to.+mouseResizeEdgeWindow+  :: Rational -- ^ The size of the area where only one edge is resized.+  -> Window   -- ^ The window to resize.+  -> X ()+mouseResizeEdgeWindow edge w = whenX (isClient w) $ withDisplay $ \d -> do     io $ raiseWindow d w     wa <- io $ getWindowAttributes d w     sh <- io $ getWMNormalHints d w     (_, _, _, _, _, ix, iy, _) <- io $ queryPointer d w     let-        [pos_x, pos_y, width, height] = map (fromIntegral . ($ wa)) [wa_x, wa_y, wa_width, wa_height]-        west  = firstHalf ix width-        north = firstHalf iy height+        [pos_x, pos_y, width, height] = map (fi . ($ wa)) [wa_x, wa_y, wa_width, wa_height]+        west  = findPos ix width+        north = findPos iy height         (cx, fx, gx) = mkSel west  width  pos_x         (cy, fy, gy) = mkSel north height pos_y     io $ warpPointer d none w 0 0 0 0 cx cy-    mouseDrag (\ex ey -> do-                 wa' <- io $ getWindowAttributes d w-                 let [px, py] = map (fromIntegral . ($ wa')) [wa_x, wa_y]-                 io $ moveResizeWindow d w (fx px (fromIntegral ex))-                                           (fy py (fromIntegral ey))-                            `uncurry` applySizeHintsContents sh (gx $ fromIntegral ex, gy $ fromIntegral ey))+    mouseDrag (\ex ey -> do let (nw,nh) = applySizeHintsContents sh (gx ex, gy ey)+                            io $ moveResizeWindow d w (fx nw) (fy nh) nw nh)               (float w)     where-    firstHalf :: CInt -> Position -> Bool-    firstHalf a b = fromIntegral a * 2 <= b-    cfst = curry fst-    csnd = curry snd-    mkSel :: Bool -> Position -> Position -> (Position, a -> a -> a, CInt -> Position)-    mkSel b k p =-        if b-            then (0, csnd, ((k + p) -) . fromIntegral)-            else (k, cfst, subtract p  . fromIntegral)+    findPos :: CInt -> Position -> Maybe Bool+    findPos m s = if p < 0.5 - edge/2+                  then Just True+                  else if p < 0.5 + edge/2+                       then Nothing+                       else Just False+                  where p = fi m / fi s+    mkSel :: Maybe Bool -> Position -> Position -> (Position, Dimension -> Position, Position -> Dimension)+    mkSel b k p = case b of+                      Just True ->  (0, (fi k + fi p -).fi, (fi k + fi p -).fi)+                      Nothing ->    (k `div` 2, const p, const $ fi k)+                      Just False -> (k, const p, subtract (fi p) . fi)++fi :: (Num b, Integral a) => a -> b+fi = fromIntegral
XMonad/Actions/FloatKeys.hs view
@@ -5,7 +5,7 @@ -- License      : BSD -- -- Maintainer   : Karsten Schoelzel <kuser@gmx.de>--- Stability    : unstable+-- Stability    : stable -- Portability  : unportable -- -- Move and resize floating windows.@@ -28,11 +28,11 @@ -- -- Then add appropriate key bindings, for example: ----- >  , ((modMask x,               xK_d     ), withFocused (keysResizeWindow (-10,-10) (1,1)))--- >  , ((modMask x,               xK_s     ), withFocused (keysResizeWindow (10,10) (1,1)))--- >  , ((modMask x .|. shiftMask, xK_d     ), withFocused (keysAbsResizeWindow (-10,-10) (1024,752)))--- >  , ((modMask x .|. shiftMask, xK_s     ), withFocused (keysAbsResizeWindow (10,10) (1024,752)))--- >  , ((modMask x,               xK_a     ), withFocused (keysMoveWindowTo (512,384) (1%2,1%2)))+-- >  , ((modm,               xK_d     ), withFocused (keysResizeWindow (-10,-10) (1,1)))+-- >  , ((modm,               xK_s     ), withFocused (keysResizeWindow (10,10) (1,1)))+-- >  , ((modm .|. shiftMask, xK_d     ), withFocused (keysAbsResizeWindow (-10,-10) (1024,752)))+-- >  , ((modm .|. shiftMask, xK_s     ), withFocused (keysAbsResizeWindow (10,10) (1024,752)))+-- >  , ((modm,               xK_a     ), withFocused (keysMoveWindowTo (512,384) (1%2,1%2))) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
+ XMonad/Actions/FloatSnap.hs view
@@ -0,0 +1,328 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.FloatSnap+-- Copyright   :  (c) 2009 Anders Engstrom <ankaan@gmail.com>+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Anders Engstrom <ankaan@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Move and resize floating windows using other windows and the edge of the+-- screen as guidelines.+-----------------------------------------------------------------------------++module XMonad.Actions.FloatSnap (+                -- * Usage+                -- $usage+                Direction2D(..),+                snapMove,+                snapGrow,+                snapShrink,+                snapMagicMove,+                snapMagicResize,+                snapMagicMouseResize) where++import XMonad+import Control.Applicative((<$>))+import Data.List (sort)+import Data.Maybe (listToMaybe,fromJust,isNothing)+import qualified XMonad.StackSet as W++import XMonad.Hooks.ManageDocks (calcGap)+import XMonad.Util.Types (Direction2D(..))++import qualified Data.Set as S++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- >    import XMonad.Actions.FloatSnap+--+-- Then add appropriate key bindings, for example:+--+-- >        , ((modm,               xK_Left),  withFocused $ snapMove L Nothing)+-- >        , ((modm,               xK_Right), withFocused $ snapMove R Nothing)+-- >        , ((modm,               xK_Up),    withFocused $ snapMove U Nothing)+-- >        , ((modm,               xK_Down),  withFocused $ snapMove D Nothing)+-- >        , ((modm .|. shiftMask, xK_Left),  withFocused $ snapShrink R Nothing)+-- >        , ((modm .|. shiftMask, xK_Right), withFocused $ snapGrow R Nothing)+-- >        , ((modm .|. shiftMask, xK_Up),    withFocused $ snapShrink D Nothing)+-- >        , ((modm .|. shiftMask, xK_Down),  withFocused $ snapGrow D Nothing)+--+-- For detailed instructions on editing your key bindings, see+-- "XMonad.Doc.Extending#Editing_key_bindings".+--+-- And possibly add an appropriate mouse binding, for example:+--+-- >        , ((modm,               button1), (\w -> focus w >> mouseMoveWindow w >> snapMagicMove (Just 50) (Just 50) w))+-- >        , ((modm .|. shiftMask, button1), (\w -> focus w >> mouseMoveWindow w >> snapMagicResize [L,R,U,D] (Just 50) (Just 50) w))+-- >        , ((modm,               button3), (\w -> focus w >> mouseResizeWindow w >> snapMagicResize [R,D] (Just 50) (Just 50) w))+--+-- For detailed instructions on editing your mouse bindings, see+-- "XMonad.Doc.Extending#Editing_mouse_bindings".+--+-- Using these mouse bindings, it will not snap while moving, but allow you to click the window once after it has been moved or resized to snap it into place.+-- Note that the order in which the commands are applied in the mouse bindings are important.+--+-- Interesting values for the distance to look for window in the orthogonal axis are Nothing (to snap against every window), Just 0 (to only snap+-- against windows that we should collide with geometrically while moving) and Just 1 (to also snap against windows we brush against).+--+-- For 'snapMagicMove', 'snapMagicResize' and 'snapMagicMouseResize', try instead setting it to the same as the maximum snapping distance.+--+-- When a value is specified it can be geometrically conceived as adding a border with the specified width around the window and then checking which+-- windows it should collide with.++-- | Resize the window by each edge independently to snap against the closest part of other windows or the edge of the screen. Use the location of the+--   mouse over the window to decide which edges to snap. In corners, the two adjoining edges will be snapped, along the middle of an edge only that edge+--   will be snapped. In the center of the window all edges will snap. Intended to be used together with "XMonad.Actions.FlexibleResize" or+--   "XMonad.Actions.FlexibleManipulate".+snapMagicMouseResize+    :: Rational  -- ^ How big the middle snap area of each axis should be.+    -> Maybe Int -- ^ The distance in the orthogonal axis to look for windows to snap against. Use Nothing to snap against every window.+    -> Maybe Int -- ^ The maximum distance to snap. Use Nothing to not impose any boundary.+    -> Window    -- ^ The window to move and resize.+    -> X ()+snapMagicMouseResize middle collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do+    wa <- io $ getWindowAttributes d w+    (_, _, _, px, py, _, _, _) <- io $ queryPointer d w+    let x = (fromIntegral px - wx wa)/(ww wa)+        y = (fromIntegral py - wy wa)/(wh wa)+        ml = if x <= (0.5 - middle/2) then [L] else []+        mr = if x >  (0.5 + middle/2) then [R] else []+        mu = if y <= (0.5 - middle/2) then [U] else []+        md = if y >  (0.5 + middle/2) then [D] else []+        mdir = ml++mr++mu++md+        dir = if mdir == []+              then [L,R,U,D]+              else mdir+    snapMagicResize dir collidedist snapdist w+    where+        wx = fromIntegral.wa_x+        wy = fromIntegral.wa_y+        ww = fromIntegral.wa_width+        wh = fromIntegral.wa_height++-- | Resize the window by each edge independently to snap against the closest part of other windows or the edge of the screen.+snapMagicResize+    :: [Direction2D] -- ^ The edges to snap.+    -> Maybe Int   -- ^ The distance in the orthogonal axis to look for windows to snap against. Use Nothing to snap against every window.+    -> Maybe Int   -- ^ The maximum distance to snap. Use Nothing to not impose any boundary.+    -> Window      -- ^ The window to move and resize.+    -> X ()+snapMagicResize dir collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do+    io $ raiseWindow d w+    wa <- io $ getWindowAttributes d w++    (xbegin,xend) <- handleAxis True d wa+    (ybegin,yend) <- handleAxis False d wa++    let xbegin' = if L `elem` dir then xbegin else (wx wa)+        xend'   = if R `elem` dir then xend   else (wx wa + ww wa)+        ybegin' = if U `elem` dir then ybegin else (wy wa)+        yend'   = if D `elem` dir then yend   else (wy wa + wh wa)++    io $ moveWindow d w (fromIntegral $ xbegin') (fromIntegral $ ybegin')+    io $ resizeWindow d w (fromIntegral $ xend' - xbegin') (fromIntegral $ yend' - ybegin')+    float w+    where+        wx = fromIntegral.wa_x+        wy = fromIntegral.wa_y+        ww = fromIntegral.wa_width+        wh = fromIntegral.wa_height++        handleAxis horiz d wa = do+            ((mbl,mbr,bs),(mfl,mfr,fs)) <- getSnap horiz collidedist d w+            let begin = if bs+                        then wpos wa+                        else case (mbl,mbr) of+                            (Just bl,Just br) -> if wpos wa - bl < br - wpos wa then bl else br+                            (Just bl,Nothing) -> bl+                            (Nothing,Just br) -> br+                            (Nothing,Nothing) -> wpos wa+                end = if fs+                      then wpos wa + wdim wa+                      else case (if mfl==(Just begin) then Nothing else mfl,mfr) of+                          (Just fl,Just fr) -> if wpos wa + wdim wa - fl < fr - wpos wa - wdim wa then fl else fr+                          (Just fl,Nothing) -> fl+                          (Nothing,Just fr) -> fr+                          (Nothing,Nothing) -> wpos wa + wdim wa+                begin' = if isNothing snapdist || abs (begin - wpos wa) <= fromJust snapdist then begin else (wpos wa)+                end' = if isNothing snapdist || abs (end - wpos wa - wdim wa) <= fromJust snapdist then end else (wpos wa + wdim wa)+            return (begin',end')+            where+                (wpos, wdim, _, _) = constructors horiz+++-- | Move a window by both axises in any direction to snap against the closest part of other windows or the edge of the screen.+snapMagicMove+    :: Maybe Int -- ^ The distance in the orthogonal axis to look for windows to snap against. Use Nothing to snap against every window.+    -> Maybe Int -- ^ The maximum distance to snap. Use Nothing to not impose any boundary.+    -> Window    -- ^ The window to move.+    -> X ()+snapMagicMove collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do+    io $ raiseWindow d w+    wa <- io $ getWindowAttributes d w++    nx <- handleAxis True d wa+    ny <- handleAxis False d wa++    io $ moveWindow d w (fromIntegral nx) (fromIntegral ny)+    float w+    where+        handleAxis horiz d wa = do+            ((mbl,mbr,bs),(mfl,mfr,fs)) <- getSnap horiz collidedist d w+            return $ if bs || fs+                     then wpos wa+                     else let b = case (mbl,mbr) of+                                    (Just bl,Just br) -> if wpos wa - bl < br - wpos wa then bl else br+                                    (Just bl,Nothing) -> bl+                                    (Nothing,Just br) -> br+                                    (Nothing,Nothing) -> wpos wa+                              f = case (mfl,mfr) of+                                    (Just fl,Just fr) -> if wpos wa + wdim wa - fl < fr - wpos wa - wdim wa then fl else fr+                                    (Just fl,Nothing) -> fl+                                    (Nothing,Just fr) -> fr+                                    (Nothing,Nothing) -> wpos wa+                              newpos = if abs (b - wpos wa) <= abs (f - wpos wa - wdim wa) then b else (f - wdim wa)+                          in if isNothing snapdist || abs (newpos - wpos wa) <= fromJust snapdist then newpos else (wpos wa)+            where+                (wpos, wdim, _, _) = constructors horiz++-- | Move a window in the specified direction until it snaps against another window or the edge of the screen.+snapMove+    :: Direction2D -- ^ What direction to move the window in.+    -> Maybe Int -- ^ The distance in the orthogonal axis to look for windows to snap against. Use Nothing to snap against every window.+    -> Window    -- ^ The window to move.+    -> X ()+snapMove L = doSnapMove True True+snapMove R = doSnapMove True False+snapMove U = doSnapMove False True+snapMove D = doSnapMove False False++doSnapMove :: Bool -> Bool -> Maybe Int -> Window -> X ()+doSnapMove horiz rev collidedist w = whenX (isClient w) $ withDisplay $ \d -> do+    io $ raiseWindow d w+    wa <- io $ getWindowAttributes d w+    ((bl,br,_),(fl,fr,_)) <- getSnap horiz collidedist d w++    let (mb,mf) = if rev then (bl,fl)+                         else (br,fr)++        newpos = fromIntegral $ case (mb,mf) of+                                    (Just b,Nothing) -> b+                                    (Nothing,Just f) -> f - wdim wa+                                    (Just b,Just f) -> if rev /= (b < f - wdim wa)+                                                       then b+                                                       else f - wdim wa+                                    _ -> wpos wa++    if horiz then io $ moveWindow d w newpos (fromIntegral $ wa_y wa)+             else io $ moveWindow d w (fromIntegral $ wa_x wa) newpos+    float w++    where+        (wpos, wdim, _, _) = constructors horiz++-- | Grow the specified edge of a window until it snaps against another window or the edge of the screen.+snapGrow+    :: Direction2D -- ^ What edge of the window to grow.+    -> Maybe Int -- ^ The distance in the orthogonal axis to look for windows to snap against. Use Nothing to snap against every window.+    -> Window    -- ^ The window to grow.+    -> X ()+snapGrow = snapResize True++-- | Shrink the specified edge of a window until it snaps against another window or the edge of the screen.+snapShrink+    :: Direction2D -- ^ What edge of the window to shrink.+    -> Maybe Int -- ^ The distance in the orthogonal axis to look for windows to snap against. Use Nothing to snap against every window.+    -> Window    -- ^ The window to shrink.+    -> X ()+snapShrink = snapResize False++snapResize :: Bool -> Direction2D -> Maybe Int -> Window -> X ()+snapResize grow dir collidedist w = whenX (isClient w) $ withDisplay $ \d -> do+    io $ raiseWindow d w+    wa <- io $ getWindowAttributes d w+    mr <- case dir of+              L -> do ((mg,ms,_),(_,_,_)) <- getSnap True collidedist d w+                      return $ case (if grow then mg else ms) of+                                   Just v -> Just (v, wy wa, ww wa + wx wa - v, wh wa)+                                   _ -> Nothing+              R -> do ((_,_,_),(ms,mg,_)) <- getSnap True collidedist d w+                      return $ case (if grow then mg else ms) of+                                   Just v -> Just (wx wa, wy wa, v - wx wa, wh wa)+                                   _ -> Nothing+              U -> do ((mg,ms,_),(_,_,_)) <- getSnap False collidedist d w+                      return $ case (if grow then mg else ms) of+                                   Just v -> Just (wx wa, v, ww wa, wh wa + wy wa - v)+                                   _ -> Nothing+              D -> do ((_,_,_),(ms,mg,_)) <- getSnap False collidedist d w+                      return $ case (if grow then mg else ms) of+                                   Just v -> Just (wx wa, wy wa, ww wa, v - wy wa)+                                   _ -> Nothing++    case mr of+        Nothing -> return ()+        Just (nx,ny,nw,nh) -> if nw>0 && nh>0 then do io $ moveWindow d w (fromIntegral nx) (fromIntegral ny)+                                                      io $ resizeWindow d w (fromIntegral nw) (fromIntegral nh)+                                              else return ()+    float w+    where+        wx = fromIntegral.wa_x+        wy = fromIntegral.wa_y+        ww = fromIntegral.wa_width+        wh = fromIntegral.wa_height+++getSnap :: Bool -> Maybe Int -> Display -> Window -> X ((Maybe Int,Maybe Int,Bool),(Maybe Int,Maybe Int,Bool))+getSnap horiz collidedist d w = do+    wa <- io $ getWindowAttributes d w+    screen <- W.current <$> gets windowset+    let sr = screenRect $ W.screenDetail screen+        wl = W.integrate' . W.stack $ W.workspace screen+    gr <- fmap ($sr) $ calcGap $ S.fromList [minBound .. maxBound]+    wla <- filter (collides wa) `fmap` (io $ mapM (getWindowAttributes d) $ filter (/=w) wl)++    return ( neighbours (back wa sr gr wla) (wpos wa)+           , neighbours (front wa sr gr wla) (wpos wa + wdim wa)+           )++    where+        wborder = fromIntegral.wa_border_width++        (wpos, wdim, rpos, rdim) = constructors horiz+        (refwpos, refwdim, _, _) = constructors $ not horiz++        back wa sr gr wla = dropWhile (< rpos sr) $+                            takeWhile (< rpos sr + rdim sr) $+                            sort $ (rpos sr):(rpos gr):(rpos gr + rdim gr):+                                   foldr (\a as -> (wpos a):(wpos a + wdim a + wborder a + wborder wa):as) [] wla++        front wa sr gr wla = dropWhile (<= rpos sr) $+                             takeWhile (<= rpos sr + rdim sr) $+                             sort $ (rpos gr - 2*wborder wa):(rpos gr + rdim gr - 2*wborder wa):(rpos sr + rdim sr - 2*wborder wa):+                                    foldr (\a as -> (wpos a - wborder a - wborder wa):(wpos a + wdim a):as) [] wla++        neighbours l v = ( listToMaybe $ reverse $ takeWhile (< v) l+                         , listToMaybe $ dropWhile (<= v) l+                         , v `elem` l+                         )++        collides wa oa = case collidedist of+                             Nothing -> True+                             Just dist -> (  refwpos oa - wborder oa < refwpos wa + refwdim wa + wborder wa + dist+                                          && refwpos wa - wborder wa - dist < refwpos oa + refwdim oa + wborder oa )+++constructors :: Bool -> (WindowAttributes -> Int, WindowAttributes -> Int, Rectangle -> Int, Rectangle -> Int)+constructors True = ( fromIntegral.wa_x+                    , fromIntegral.wa_width+                    , fromIntegral.rect_x+                    , fromIntegral.rect_width+                    )+constructors False = ( fromIntegral.wa_y+                     , fromIntegral.wa_height+                     , fromIntegral.rect_y+                     , fromIntegral.rect_height+                     )
XMonad/Actions/FocusNth.hs view
@@ -5,7 +5,7 @@ -- License      : BSD -- -- Maintainer   : Karsten Schoelzel <kuser@gmx.de>--- Stability    : unstable+-- Stability    : stable -- Portability  : unportable -- -- Focus the nth window of the current workspace.@@ -14,7 +14,7 @@ module XMonad.Actions.FocusNth (                  -- * Usage                  -- $usage-                 focusNth) where+                 focusNth,focusNth') where  import XMonad.StackSet import XMonad@@ -27,7 +27,7 @@ -- Then add appropriate keybindings, for example: -- -- > -- mod4-[1..9] @@ Switch to window N--- > ++ [((modMask x, k), focusNth i)+-- > ++ [((modm, k), focusNth i) -- >     | (i, k) <- zip [0 .. 8] [xK_1 ..]] -- -- For detailed instructions on editing your key bindings, see
+ XMonad/Actions/GridSelect.hs view
@@ -0,0 +1,525 @@+{-# LANGUAGE ScopedTypeVariables, GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances, OverlappingInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.GridSelect+-- Copyright   :  Clemens Fruhwirth <clemens@endorphin.org>+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Clemens Fruhwirth <clemens@endorphin.org>+-- Stability   :  unstable+-- Portability :  unportable+--+-- GridSelect displays items(e.g. the opened windows) in a 2D grid and lets+-- the user select from it with the cursor/hjkl keys or the mouse.+--+-----------------------------------------------------------------------------++module XMonad.Actions.GridSelect (+    -- * Usage+    -- $usage++    -- ** Customizing+    -- *** Using a common GSConfig+    -- $commonGSConfig++    -- *** Custom keybindings+    -- $keybindings++    -- * Configuration+    GSConfig(..),+    defaultGSConfig,+    NavigateMap,+    TwoDPosition,+    buildDefaultGSConfig,++    -- * Variations on 'gridselect'+    gridselect,+    gridselectWindow,+    withSelectedWindow,+    bringSelected,+    goToSelected,+    spawnSelected,+    runSelectedAction,++    -- * Colorizers+    HasColorizer(defaultColorizer),+    fromClassName,+    stringColorizer,+    colorRangeFromClassName++    -- * Screenshots+    -- $screenshots+    ) where+import Data.Maybe+import Data.Bits+import Control.Applicative+import Control.Monad.State+import Control.Arrow+import Data.List as L+import qualified Data.Map as M+import XMonad hiding (liftX)+import XMonad.Util.Font+import XMonad.Prompt (mkUnmanagedWindow)+import XMonad.StackSet as W+import XMonad.Layout.Decoration+import XMonad.Util.NamedWindows+import XMonad.Actions.WindowBringer (bringWindow)+import Text.Printf+import System.Random (mkStdGen, genRange, next)+import Data.Word (Word8)++-- $usage+--+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- >    import XMonad.Actions.GridSelect+--+-- Then add a keybinding, e.g.+--+-- >    , ((modm, xK_g), goToSelected defaultGSConfig)+--+-- This module also supports displaying arbitrary information in a grid and letting+-- the user select from it. E.g. to spawn an application from a given list, you+-- can use the following:+--+-- >   , ((modm, xK_s), spawnSelected defaultGSConfig ["xterm","gmplayer","gvim"])++-- $commonGSConfig+--+-- It is possible to bind a @gsconfig@ at top-level in your configuration. Like so:+--+-- > -- the top of your config+-- > {-# LANGUAGE NoMonomorphismRestriction #-}+-- > import XMonad+-- > ...+-- > gsconfig1 = defaultGSConfig { gs_cellheight = 30, gs_cellWidth = 100 }+--+-- An example where 'buildDefaultGSConfig' is used instead of 'defaultGSConfig'+-- in order to specify a custom colorizer is @gsconfig2@ (found in+-- "XMonad.Actions.GridSelect#Colorizers"):+--+-- > gsconfig2 colorizer = (buildDefaultGSConfig colorizer) { gs_cellheight = 30, gs_cellWidth = 100 }+--+-- > -- | A green monochrome colorizer based on window class+-- > greenColorizer = colorRangeFromClassName+-- >                      black            -- lowest inactive bg+-- >                      (0x70,0xFF,0x70) -- highest inactive bg+-- >                      black            -- active bg+-- >                      white            -- inactive fg+-- >                      white            -- active fg+-- >   where black = minBound+-- >         white = maxBound+--+-- Then you can bind to:+--+-- >     ,((modm, xK_g), goToSelected  $ gsconfig2 myWinColorizer)+-- >     ,((modm, xK_p), spawnSelected $ spawnSelected defaultColorizer)++-- $keybindings+--+-- Adding more keybindings for gridselect to listen to is similar:+--+-- At the top of your config:+--+-- > {-# LANGAUGE NoMonomorphismRestriction #-}+-- > import XMonad+-- > import qualified Data.Map as M+--+-- Then define @gsconfig3@ which may be used in exactly the same manner as @gsconfig1@:+--+-- > gsconfig3 = defaultGSConfig+-- >    { gs_cellheight = 30+-- >    , gs_cellwidth = 100+-- >    , gs_navigate = M.unions+-- >            [reset+-- >            ,nethackKeys+-- >            ,gs_navigate                               -- get the default navigation bindings+-- >                $ defaultGSConfig `asTypeOf` gsconfig3 -- needed to fix an ambiguous type variable+-- >            ]+-- >    }+-- >   where addPair (a,b) (x,y) = (a+x,b+y)+-- >         nethackKeys = M.map addPair $ M.fromList+-- >                               [((0,xK_y),(-1,-1))+-- >                               ,((0,xK_i),(1,-1))+-- >                               ,((0,xK_n),(-1,1))+-- >                               ,((0,xK_m),(1,1))+-- >                               ]+-- >         -- jump back to the center with the spacebar, regardless of the current position.+-- >         reset = M.singleton (0,xK_space) (const (0,0))++-- $screenshots+--+-- Selecting a workspace:+--+-- <<http://haskell.org/sitewiki/images/a/a9/Xmonad-gridselect-workspace.png>>+--+-- Selecting a window by title:+--+-- <<http://haskell.org/sitewiki/images/3/35/Xmonad-gridselect-window-aavogt.png>>++data GSConfig a = GSConfig {+      gs_cellheight :: Integer,+      gs_cellwidth :: Integer,+      gs_cellpadding :: Integer,+      gs_colorizer :: a -> Bool -> X (String, String),+      gs_font :: String,+      gs_navigate :: NavigateMap,+      gs_originFractX :: Double,+      gs_originFractY :: Double+}++-- | That is 'fromClassName' if you are selecting a 'Window', or+-- 'defaultColorizer' if you are selecting a 'String'. The catch-all instance+-- @HasColorizer a@ uses the 'focusedBorderColor' and 'normalBorderColor'+-- colors.+class HasColorizer a where+    defaultColorizer :: a -> Bool -> X (String, String)++instance HasColorizer Window where+    defaultColorizer = fromClassName++instance HasColorizer String where+    defaultColorizer = stringColorizer++instance HasColorizer a where+    defaultColorizer _ isFg =+        let getColor = if isFg then focusedBorderColor else normalBorderColor+        in asks $ flip (,) "black" . getColor . config++-- | A basic configuration for 'gridselect', with the colorizer chosen based on the type.+--+-- If you want to replace the 'gs_colorizer' field, use 'buildDefaultGSConfig'+-- instead, to avoid ambiguous type variables.+defaultGSConfig :: HasColorizer a => GSConfig a+defaultGSConfig = buildDefaultGSConfig defaultColorizer++type NavigateMap = M.Map (KeyMask,KeySym) (TwoDPosition -> TwoDPosition)++type TwoDPosition = (Integer, Integer)++type TwoDElementMap a = [(TwoDPosition,(String,a))]++data TwoDState a = TwoDState { td_curpos :: TwoDPosition+                             , td_elementmap :: TwoDElementMap a+                             , td_gsconfig :: GSConfig a+                             , td_font :: XMonadFont+                             , td_paneX :: Integer+                             , td_paneY :: Integer+                             , td_drawingWin :: Window+                             }++newtype TwoD a b = TwoD { unTwoD :: StateT (TwoDState a) X b }+    deriving (Monad,Functor,MonadState (TwoDState a))++instance Applicative (TwoD a) where+    (<*>) = ap+    pure = return++liftX ::  X a1 -> TwoD a a1+liftX = TwoD . lift++evalTwoD ::  TwoD a1 a -> TwoDState a1 -> X a+evalTwoD m s = flip evalStateT s $ unTwoD m++diamondLayer :: (Enum b', Num b') => b' -> [(b', b')]+-- FIXME remove nub+diamondLayer n = let ul = [ (x,n-x) | x <- [0..n] ]+        in nub $ ul ++ (map (negate *** id) ul) +++           (map (negate *** negate) ul) +++           (map (id *** negate) ul)++diamond :: (Enum a, Num a) => [(a, a)]+diamond = concatMap diamondLayer [0..]++diamondRestrict :: Integer -> Integer -> Integer -> Integer -> [(Integer, Integer)]+diamondRestrict x y originX originY =+  L.filter (\(x',y') -> abs x' <= x && abs y' <= y) .+  map (\(x', y') -> (x' + fromInteger originX, y' + fromInteger originY)) .+  take 1000 $ diamond++tupadd :: (Num t1, Num t) => (t, t1) -> (t, t1) -> (t, t1)+tupadd (a,b) (c,d) = (a+c,b+d)++findInElementMap :: (Eq a) => a -> [(a, b)] -> Maybe (a, b)+findInElementMap pos = find ((== pos) . fst)++drawWinBox :: Window -> XMonadFont -> (String, String) -> Integer -> Integer -> String -> Integer -> Integer -> Integer -> X ()+drawWinBox win font (fg,bg) ch cw text x y cp =+  withDisplay $ \dpy -> do+  gc <- liftIO $ createGC dpy win+  bordergc <- liftIO $ createGC dpy win+  liftIO $ do+    Just fgcolor <- initColor dpy fg+    Just bgcolor <- initColor dpy bg+    Just bordercolor <- initColor dpy borderColor+    setForeground dpy gc fgcolor+    setBackground dpy gc bgcolor+    setForeground dpy bordergc bordercolor+    fillRectangle dpy win gc (fromInteger x) (fromInteger y) (fromInteger cw) (fromInteger ch)+    drawRectangle dpy win bordergc (fromInteger x) (fromInteger y) (fromInteger cw) (fromInteger ch)+  stext <- shrinkWhile (shrinkIt shrinkText)+           (\n -> do size <- liftIO $ textWidthXMF dpy font n+                     return $ size > (fromInteger (cw-(2*cp))))+           text+  printStringXMF dpy win font gc bg fg (fromInteger (x+cp)) (fromInteger (y+(div ch 2))) stext+  liftIO $ freeGC dpy gc+  liftIO $ freeGC dpy bordergc++updateAllElements :: TwoD a ()+updateAllElements =+    do+      TwoDState { td_elementmap = els } <- get+      updateElements els++updateElements :: TwoDElementMap a -> TwoD a ()+updateElements elementmap = do+    TwoDState { td_curpos = curpos,+                td_drawingWin = win,+                td_gsconfig = gsconfig,+                td_font = font,+                td_paneX = paneX,+                td_paneY = paneY} <- get+    let cellwidth = gs_cellwidth gsconfig+        cellheight = gs_cellheight gsconfig+        paneX' = div (paneX-cellwidth) 2+        paneY' = div (paneY-cellheight) 2+        updateElement (pos@(x,y),(text, element)) = liftX $ do+            colors <- gs_colorizer gsconfig element (pos == curpos)+            drawWinBox win font+                       colors+                       cellheight+                       cellwidth+                       text+                       (paneX'+x*cellwidth)+                       (paneY'+y*cellheight)+                       (gs_cellpadding gsconfig)+    mapM_ updateElement elementmap++eventLoop :: TwoD a (Maybe a)+eventLoop = do+  (keysym,string,event) <- liftX $ withDisplay $ \d -> liftIO $ allocaXEvent $ \e -> do+                             maskEvent d (exposureMask .|. keyPressMask .|. buttonReleaseMask) e+                             ev <- getEvent e+                             (ks,s) <- if ev_event_type ev == keyPress+                                       then lookupString $ asKeyEvent e+                                       else return (Nothing, "")+                             return (ks,s,ev)+  handle (fromMaybe xK_VoidSymbol keysym,string) event++handle ::  (KeySym, t) -> Event -> TwoD a (Maybe a)+handle (ks,_) (KeyEvent {ev_event_type = t, ev_state = m })+    | t == keyPress && ks == xK_Escape = return Nothing+    | t == keyPress && ks == xK_Return = do+       (TwoDState { td_curpos = pos, td_elementmap = elmap }) <- get+       return $ fmap (snd . snd) $ findInElementMap pos elmap+    | t == keyPress = do+        m' <- liftX (cleanMask m)+        keymap <- gets (gs_navigate . td_gsconfig)+        maybe eventLoop diffAndRefresh . M.lookup (m',ks) $ keymap+  where diffAndRefresh diff = do+          state <- get+          let elmap = td_elementmap state+              oldPos = td_curpos state+              newPos = diff oldPos+              newSelectedEl = findInElementMap newPos elmap+          when (isJust newSelectedEl) $ do+                                put state { td_curpos =  newPos }+                                updateElements (catMaybes [(findInElementMap oldPos elmap), newSelectedEl])+          eventLoop++handle _ (ButtonEvent { ev_event_type = t, ev_x = x, ev_y = y })+    | t == buttonRelease = do+        (TwoDState { td_elementmap = elmap, td_paneX = px, td_paneY = py,+                     td_gsconfig = (GSConfig ch cw _ _ _ _ _ _) }) <- get+        let gridX = (fi x - (px - cw) `div` 2) `div` cw+            gridY = (fi y - (py - ch) `div` 2) `div` ch+        case lookup (gridX,gridY) elmap of+             Just (_,el) -> return (Just el)+             Nothing -> eventLoop+    | otherwise = eventLoop++handle _ (ExposeEvent { }) = updateAllElements >> eventLoop++handle _ _ = eventLoop++-- FIXME probably move that into Utils?+-- Conversion scheme as in http://en.wikipedia.org/wiki/HSV_color_space+hsv2rgb :: Fractional a => (Integer,a,a) -> (a,a,a)+hsv2rgb (h,s,v) =+    let hi = (div h 60) `mod` 6 :: Integer+        f = (((fromInteger h)/60) - (fromInteger hi)) :: Fractional a => a+        q = v * (1-f)+        p = v * (1-s)+        t = v * (1-(1-f)*s)+    in case hi of+         0 -> (v,t,p)+         1 -> (q,v,p)+         2 -> (p,v,t)+         3 -> (p,q,v)+         4 -> (t,p,v)+         5 -> (v,p,q)+         _ -> error "The world is ending. x mod a >= a."++-- | Default colorizer for Strings+stringColorizer :: String -> Bool -> X (String, String)+stringColorizer s active =+    let seed x = toInteger (sum $ map ((*x).fromEnum) s) :: Integer+        (r,g,b) = hsv2rgb ((seed 83) `mod` 360,+                           (fromInteger ((seed 191) `mod` 1000))/2500+0.4,+                           (fromInteger ((seed 121) `mod` 1000))/2500+0.4)+    in if active+         then return ("#faff69", "black")+         else return ("#" ++ concat (map (twodigitHex.(round :: Double -> Word8).(*256)) [r, g, b] ), "white")++-- | Colorize a window depending on it's className.+fromClassName :: Window -> Bool -> X (String, String)+fromClassName w active = runQuery className w >>= flip defaultColorizer active++twodigitHex :: Word8 -> String+twodigitHex a = printf "%02x" a++-- | A colorizer that picks a color inside a range,+-- and depending on the window's class.+colorRangeFromClassName :: (Word8, Word8, Word8) -- ^ Beginning of the color range+                        -> (Word8, Word8, Word8) -- ^ End of the color range+                        -> (Word8, Word8, Word8) -- ^ Background of the active window+                        -> (Word8, Word8, Word8) -- ^ Inactive text color+                        -> (Word8, Word8, Word8) -- ^ Active text color+                        -> Window -> Bool -> X (String, String)+colorRangeFromClassName startC endC activeC inactiveT activeT w active =+    do classname <- runQuery className w+       if active+         then return (rgbToHex activeC, rgbToHex activeT)+         else return (rgbToHex $ mix startC endC+                  $ stringToRatio classname, rgbToHex inactiveT)+    where rgbToHex :: (Word8, Word8, Word8) -> String+          rgbToHex (r, g, b) = '#':twodigitHex r+                               ++twodigitHex g++twodigitHex b++-- | Creates a mix of two colors according to a ratio+-- (1 -> first color, 0 -> second color).+mix :: (Word8, Word8, Word8) -> (Word8, Word8, Word8)+        -> Double -> (Word8, Word8, Word8)+mix (r1, g1, b1) (r2, g2, b2) r = (mix' r1 r2, mix' g1 g2, mix' b1 b2)+    where  mix' a b = truncate $ (fi a * r) + (fi b * (1 - r))++-- | Generates a Double from a string, trying to+-- achieve a random distribution.+-- We create a random seed from the sum of all characters+-- in the string, and use it to generate a ratio between 0 and 1+stringToRatio :: String -> Double+stringToRatio "" = 0+stringToRatio s = let gen = mkStdGen $ sum $ map fromEnum s+                      range = (\(a, b) -> b - a) $ genRange gen+                      randomInt = foldr1 combine $ replicate 20 next+                      combine f1 f2 g = let (_, g') = f1 g in f2 g'+                  in fi (fst $ randomInt gen) / fi range++-- | Brings up a 2D grid of elements in the center of the screen, and one can+-- select an element with cursors keys. The selected element is returned.+gridselect :: GSConfig a -> [(String,a)] -> X (Maybe a)+gridselect gsconfig elmap =+ withDisplay $ \dpy -> do+    rootw <- asks theRoot+    s <- gets $ screenRect . W.screenDetail . W.current . windowset+    win <- liftIO $ mkUnmanagedWindow dpy (defaultScreenOfDisplay dpy) rootw+                    (rect_x s) (rect_y s) (rect_width s) (rect_height s)+    liftIO $ mapWindow dpy win+    liftIO $ selectInput dpy win (exposureMask .|. keyPressMask .|. buttonReleaseMask)+    status <- io $ grabKeyboard dpy win True grabModeAsync grabModeAsync currentTime+    io $ grabButton dpy button1 anyModifier win True buttonReleaseMask grabModeAsync grabModeAsync none none+    font <- initXMF (gs_font gsconfig)+    let screenWidth = toInteger $ rect_width s;+        screenHeight = toInteger $ rect_height s;+    selectedElement <- if (status == grabSuccess) then do+                            let restriction ss cs = (fromInteger ss/fromInteger (cs gsconfig)-1)/2 :: Double+                                restrictX = floor $ restriction screenWidth gs_cellwidth+                                restrictY = floor $ restriction screenHeight gs_cellheight+                                originPosX = floor $ ((gs_originFractX gsconfig) - (1/2)) * 2 * fromIntegral restrictX+                                originPosY = floor $ ((gs_originFractY gsconfig) - (1/2)) * 2 * fromIntegral restrictY+                                coords = diamondRestrict restrictX restrictY originPosX originPosY+                                elmap' = zip coords elmap++                            evalTwoD (updateAllElements >> eventLoop)+                                (TwoDState (head coords)+                                            elmap'+                                            gsconfig+                                            font+                                            screenWidth+                                            screenHeight+                                            win)+                      else+                          return Nothing+    liftIO $ do+      unmapWindow dpy win+      destroyWindow dpy win+      sync dpy False+    releaseXMF font+    return selectedElement++-- | Like `gridSelect' but with the current windows and their titles as elements+gridselectWindow :: GSConfig Window -> X (Maybe Window)+gridselectWindow gsconf = windowMap >>= gridselect gsconf++-- | Brings up a 2D grid of windows in the center of the screen, and one can+-- select a window with cursors keys. The selected window is then passed to+-- a callback function.+withSelectedWindow :: (Window -> X ()) -> GSConfig Window -> X ()+withSelectedWindow callback conf = do+    mbWindow <- gridselectWindow conf+    case mbWindow of+        Just w -> callback w+        Nothing -> return ()++windowMap :: X [(String,Window)]+windowMap = do+    ws <- gets windowset+    wins <- mapM keyValuePair (W.allWindows ws)+    return wins+ where keyValuePair w = flip (,) w `fmap` decorateName' w++decorateName' :: Window -> X String+decorateName' w = do+  fmap show $ getName w++-- | Builds a default gs config from a colorizer function.+buildDefaultGSConfig :: (a -> Bool -> X (String,String)) -> GSConfig a+buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8" defaultGSNav (1/2) (1/2)++defaultGSNav :: NavigateMap+defaultGSNav = M.map tupadd $ M.fromList+    [((0,xK_Left) ,(-1,0))+    ,((0,xK_h)    ,(-1,0))+    ,((0,xK_Right),(1,0))+    ,((0,xK_l)    ,(1,0))+    ,((0,xK_Down) ,(0,1))+    ,((0,xK_j)    ,(0,1))+    ,((0,xK_Up)   ,(0,-1))+    ,((0,xK_k)    ,(0,-1))+    ]++borderColor :: String+borderColor = "white"++-- | Brings selected window to the current workspace.+bringSelected :: GSConfig Window -> X ()+bringSelected = withSelectedWindow $ \w -> do+    windows (bringWindow w)+    XMonad.focus w+    windows W.shiftMaster++-- | Switches to selected window's workspace and focuses that window.+goToSelected :: GSConfig Window -> X ()+goToSelected = withSelectedWindow $ windows . W.focusWindow++-- | Select an application to spawn from a given list+spawnSelected :: GSConfig String -> [String] -> X ()+spawnSelected conf lst = gridselect conf (zip lst lst) >>= flip whenJust spawn++-- | Select an action and run it in the X monad+runSelectedAction :: GSConfig (X ()) -> [(String, X ())] -> X ()+runSelectedAction conf actions = do+    selectedActionM <- gridselect conf actions+    case selectedActionM of+        Just selectedAction -> selectedAction+        Nothing -> return ()
+ XMonad/Actions/MessageFeedback.hs view
@@ -0,0 +1,99 @@+-----------------------------------------------------------------------------+-- |+-- Module       : XMonad.Actions.MessageFeedback+-- Copyright    : (c) Quentin Moser <quentin.moser@unifr.ch>+-- License      : BSD3+--+-- Maintainer   : None+-- Stability    : unstable+-- Portability  : unportable+--+-- Alternative to 'XMonad.Operations.sendMessage' that provides knowledge+-- of whether the message was handled, and utility functions based on+-- this facility.+-----------------------------------------------------------------------------++module XMonad.Actions.MessageFeedback (+                                      -- * Usage+                                      -- $usage++                                        send+                                      , tryMessage+                                      , tryMessage_+                                      , tryInOrder+                                      , tryInOrder_+                                      , sm+                                      , sendSM+                                      , sendSM_+                                      ) where++import XMonad.Core ( X (), Message, SomeMessage(..), LayoutClass(..), windowset, catchX )+import XMonad.StackSet ( current, workspace, layout, tag )+import XMonad.Operations ( updateLayout )++import Control.Monad.State ( gets )+import Data.Maybe ( isJust )+import Control.Applicative ((<$>))++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Actions.MessageFeedback+--+-- You can then use this module's functions wherever an action is expected.+--+-- Note that most functions in this module have a return type of @X Bool@+-- whereas configuration options will expect a @X ()@ action.+-- For example, the key binding+--+-- > -- Shrink the master area of a tiled layout, or move the focused window+-- > -- to the left in a WindowArranger-based layout+-- > ((modKey, xK_Left), tryMessage Shrink (MoveLeft 50))+--+-- is mis-typed. For this reason, this module provides alternatives (ending with+-- an underscore, e.g. tryMessage_) that discard their result and return an @X ()@.+-- For example, to correct the previous example:+--+-- > ((modKey, xK_Left), tryMessage_ Shrink (MoveLeft 50))+--+++-- | Behaves like 'XMonad.Operations.sendMessage', but returns True of the+-- message was handled by the layout, False otherwise.+send :: Message a => a -> X Bool+send = sendSM . sm++-- | Sends the first message, and if it was not handled, sends the second.+-- Returns True if either message was handled, False otherwise.+tryMessage :: (Message a, Message b) => a -> b -> X Bool+tryMessage m1 m2 = do b <- send m1+                      if b then return True else send m2++tryMessage_ :: (Message a, Message b) => a -> b -> X ()+tryMessage_ m1 m2 = tryMessage m1 m2 >> return ()++-- | Tries sending every message of the list in order until one of them+-- is handled. Returns True if one of the messages was handled, False otherwise.+tryInOrder :: [SomeMessage] -> X Bool+tryInOrder [] = return False+tryInOrder (m:ms) = do b <- sendSM m+                       if b then return True else tryInOrder ms++tryInOrder_ :: [SomeMessage] -> X ()+tryInOrder_ ms = tryInOrder ms >> return ()+++-- | Convenience shorthand for 'XMonad.Core.SomeMessage'.+sm :: Message a => a -> SomeMessage+sm = SomeMessage+++sendSM :: SomeMessage -> X Bool+sendSM m = do w <- workspace . current <$> gets windowset+              ml' <- handleMessage (layout w) m `catchX` return Nothing+              updateLayout (tag w) ml'+              return $ isJust ml'+++sendSM_ :: SomeMessage -> X ()+sendSM_ m = sendSM m >> return ()
XMonad/Actions/MouseGestures.hs view
@@ -15,14 +15,14 @@ module XMonad.Actions.MouseGestures (     -- * Usage     -- $usage-    Direction(..),+    Direction2D(..),     mouseGestureH,     mouseGesture,     mkCollect ) where  import XMonad-import XMonad.Hooks.ManageDocks (Direction(..))+import XMonad.Util.Types (Direction2D(..))  import Data.IORef import qualified Data.Map as M@@ -39,7 +39,7 @@ -- -- then add an appropriate mouse binding: ----- >     , ((modMask x .|. shiftMask, button3), mouseGesture gestures)+-- >     , ((modm .|. shiftMask, button3), mouseGesture gestures) -- -- where @gestures@ is a 'Data.Map.Map' from gestures to actions on -- windows, for example:@@ -64,10 +64,10 @@     where     d a b = abs (a - b) -dir :: Pos -> Pos -> Direction+dir :: Pos -> Pos -> Direction2D dir (ax, ay) (bx, by) = trans . (/ pi) $ atan2 (fromIntegral $ ay - by) (fromIntegral $ bx - ax)     where-    trans :: Double -> Direction+    trans :: Double -> Direction2D     trans x         | rg (-3/4) (-1/4) x = D         | rg (-1/4)  (1/4) x = R@@ -75,7 +75,7 @@         | otherwise          = L     rg a z x = a <= x && x < z -gauge :: (Direction -> X ()) -> Pos -> IORef (Maybe (Direction, Pos)) -> Position -> Position -> X ()+gauge :: (Direction2D -> X ()) -> Pos -> IORef (Maybe (Direction2D, Pos)) -> Position -> Position -> X () gauge hook op st nx ny = do     let np = (nx, ny)     stx <- io $ readIORef st@@ -96,7 +96,7 @@ -- | @'mouseGestureH' moveHook endHook@ is a mouse button -- event handler. It collects mouse movements, calling @moveHook@ for each -- update; when the button is released, it calls @endHook@.-mouseGestureH :: (Direction -> X ()) -> X () -> X ()+mouseGestureH :: (Direction2D -> X ()) -> X () -> X () mouseGestureH moveHook endHook = do     dpy <- asks display     root <- asks theRoot@@ -108,7 +108,7 @@  -- | A utility function on top of 'mouseGestureH'. It uses a 'Data.Map.Map' to -- look up the mouse gesture, then executes the corresponding action (if any).-mouseGesture :: Map [Direction] (Window -> X ()) -> Window -> X ()+mouseGesture :: Map [Direction2D] (Window -> X ()) -> Window -> X () mouseGesture tbl win = do     (mov, end) <- mkCollect     mouseGestureH (\d -> mov d >> return ()) $ end >>= \gest ->@@ -121,7 +121,7 @@ -- collect mouse movements (and return the current gesture as a list); the end -- hook will return a list of the completed gesture, which you can access with -- 'Control.Monad.>>='.-mkCollect :: (MonadIO m, MonadIO m') => m (Direction -> m' [Direction], m' [Direction])+mkCollect :: (MonadIO m, MonadIO m') => m (Direction2D -> m' [Direction2D], m' [Direction2D]) mkCollect = liftIO $ do     acc <- newIORef []     let
XMonad/Actions/MouseResize.hs view
@@ -47,11 +47,11 @@ -- -- Then edit your @layoutHook@ by modifying a given layout: ----- > myLayouts = mouseResize $ windowArrange $ layoutHook defaultConfig+-- > myLayout = mouseResize $ windowArrange $ layoutHook defaultConfig -- -- and then: ----- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -65,7 +65,8 @@ instance Read (MouseResize a) where readsPrec _ s = [(MR [], s)]  instance LayoutModifier MouseResize Window where-    redoLayout (MR st) _ s wrs+    redoLayout _       _ Nothing  wrs = return (wrs, Nothing)+    redoLayout (MR st) _ (Just s) wrs         | [] <- st  = initState    >>= \nst -> return (wrs, Just $ MR nst)         | otherwise = processState >>= \nst -> return (wrs, Just $ MR nst)         where
XMonad/Actions/NoBorders.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  Lukas Mai <l.mai@web.de>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- This module provides helper functions for dealing with window borders.@@ -21,7 +21,7 @@ -- | Toggle the border of the currently focused window. To use it, add a -- keybinding like so: ----- > , ((modMask x,  xK_g ),   withFocused toggleBorder)+-- > , ((modm,  xK_g ),   withFocused toggleBorder) -- toggleBorder :: Window -> X () toggleBorder w = do
+ XMonad/Actions/OnScreen.hs view
@@ -0,0 +1,115 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.OnScreen+-- Copyright   :  (c) 2009 Nils Schweinsberg+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Nils Schweinsberg <mail@n-sch.de>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Control workspaces on different screens (in xinerama mode).+--+-----------------------------------------------------------------------------++module XMonad.Actions.OnScreen (+    -- * Usage+    -- $usage+    onScreen+    , viewOnScreen+    , greedyViewOnScreen+    , onlyOnScreen+    ) where++import XMonad.StackSet+import Control.Monad(guard)+import Data.List+import Data.Maybe(fromMaybe)+import Data.Function(on)++-- $usage+--+-- This module provides an easy way to control, what you see on other screens in+-- xinerama mode without having to focus them. Put this into your+-- @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Actions.OnScreen+--+-- Then add the appropriate keybindings, for example replace your current keys+-- to switch the workspaces with this at the bottom of your keybindings:+--+-- >     +++-- >     [ ((m .|. modm, k), windows (f i))+-- >       | (i, k) <- zip (workspaces conf) ([xK_1 .. xK_9] ++ [xK_0])+-- >       , (f, m) <- [ (viewOnScreen 0, 0)+-- >                   , (viewOnScreen 1, controlMask)+-- >                   , (greedyView, controlMask .|. shiftMask) ]+-- >     ]+--+-- This will provide you with the following keybindings:+--+--      * modkey + 1-0:+--      Switch to workspace 1-0 on screen 0+--+--      * modkey + control + 1-0:+--      Switch to workspace 1-0 on screen 1+--+--      * modkey + control + shift + 1-0:+--      Default greedyView behaviour+--+--+-- A more basic version inside the default keybindings would be:+--+-- >        , ((modm .|. controlMask, xK_1) windows (viewOnScreen 0 "1"))+--+-- where 0 is the first screen and "1" the workspace with the tag "1".+--+-- For detailed instructions on editing your key bindings, see+-- "XMonad.Doc.Extending#Editing_key_bindings".++-- | Switch to the (hidden) workspace with index 'i' on the screen 'sc'.+-- A default function (for example 'view' or 'greedyView') will be run if 'sc' is+-- the current screen, no valid screen id or workspace 'i' is already visible.+onScreen :: (Eq sid, Eq i)+          => (i -> StackSet i l a sid sd -> StackSet i l a sid sd) -- ^ default action+          -> sid                      -- ^ screen id+          -> i                        -- ^ index of the workspace+          -> StackSet i l a sid sd    -- ^ current stack+          -> StackSet i l a sid sd+onScreen defFunc sc i st = fromMaybe (defFunc i st) $ do+    -- on unfocused current screen+    guard $ screen (current st) /= sc+    x <- find ((i==) . tag    ) (hidden  st)+    s <- find ((sc==) . screen) (screens st)+    o <- find ((sc==) . screen) (visible st)+    let newScreen = s { workspace = x }+    return st { visible   = newScreen : deleteBy ((==) `on` screen) newScreen (visible st)+              , hidden    = workspace o : deleteBy ((==) `on` tag) x (hidden st)+              }++-- | Switch to workspace 'i' on screen 'sc'. If 'i' is visible use 'greedyView'+-- to switch the current workspace with workspace 'i'.+greedyViewOnScreen :: (Eq sid, Eq i)+    => sid                          -- ^ screen id+    -> i                            -- ^ index of the workspace+    -> StackSet i l a sid sd        -- ^ current stack+    -> StackSet i l a sid sd+greedyViewOnScreen = onScreen greedyView++-- | Switch to workspace 'i' on screen 'sc'. If 'i' is visible use 'view' to+-- switch focus to the workspace 'i'.+viewOnScreen :: (Eq sid, Eq i)+    => sid                          -- ^ screen id+    -> i                            -- ^ index of the workspace+    -> StackSet i l a sid sd        -- ^ current stack+    -> StackSet i l a sid sd+viewOnScreen = onScreen view++-- | Switch to workspace 'i' on screen 'sc'. If 'i' is visible do nothing.+onlyOnScreen :: (Eq sid, Eq i)+    => sid                          -- ^ screen id+    -> i                            -- ^ index of the workspace+    -> StackSet i l a sid sd        -- ^ current stack+    -> StackSet i l a sid sd+onlyOnScreen = onScreen doNothing+  where doNothing _ st = st
XMonad/Actions/PerWorkspaceKeys.hs view
@@ -36,7 +36,7 @@  -- | Uses supplied function to decide which action to run depending on current workspace name. chooseAction :: (String->X()) -> X()-chooseAction f = withWindowSet (f . S.tag . S.workspace . S.current)+chooseAction f = withWindowSet (f . S.currentTag)  -- | If current workspace is listed, run appropriate action (only the first match counts!) -- If it isn't listed, then run default action (marked with empty string, \"\"), or do nothing if default isn't supplied.
+ XMonad/Actions/PhysicalScreens.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+-----------------------------------------------------------------------------+-- |+-- Module       : XMonad.Actions.PhysicalScreens+-- Copyright    : (c) Nelson Elhage <nelhage@mit.edu>+-- License      : BSD+--+-- Maintainer   : Nelson Elhage <nelhage@mit.edu>+-- Stability    : unstable+-- Portability  : unportable+--+-- Manipulate screens ordered by physical location instead of ID+-----------------------------------------------------------------------------++module XMonad.Actions.PhysicalScreens (+                                        -- * Usage+                                        -- $usage+                                        PhysicalScreen(..)+                                      , getScreen+                                      , viewScreen+                                      , sendToScreen+                                      ) where++import XMonad+import qualified XMonad.StackSet as W++import qualified Graphics.X11.Xlib as X+import Graphics.X11.Xinerama++import Data.List (sortBy)+import Data.Function (on)++{- $usage++This module allows you name Xinerama screens from XMonad using their+physical location relative to each other (as reported by Xinerama),+rather than their @ScreenID@ s, which are arbitrarily determined by+your X server and graphics hardware.++Screens are ordered by the upper-left-most corner, from top-to-bottom+and then left-to-right.++Example usage in your @~\/.xmonad\/xmonad.hs@ file:++> import XMonad.Actions.PhysicalSCreens++> --+> -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3+> -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3+> --+> [((modm .|. mask, key), f sc)+>     | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]+>     , (f, mask) <- [(viewScreen, 0), (sendToScreen, shiftMask)]]++For detailed instructions on editing your key bindings, see+"XMonad.Doc.Extending#Editing_key_bindings".+ -}++-- | The type of the index of a screen by location+newtype PhysicalScreen = P Int deriving (Eq,Ord,Show,Read,Enum,Num,Integral,Real)++-- | Translate a physical screen index to a "ScreenId"+getScreen :: PhysicalScreen -> X (Maybe ScreenId)+getScreen (P i) = withDisplay $ \dpy -> do+                    screens <- io $ getScreenInfo dpy+                    if i >= length screens+                     then return Nothing+                     else let ss = sortBy (cmpScreen `on` fst) $ zip screens [0..]+                          in return $ Just $ snd $ ss !! i++-- | Switch to a given physical screen+viewScreen :: PhysicalScreen -> X ()+viewScreen p = do i <- getScreen p+                  whenJust i $ \s -> do+                  w <- screenWorkspace s+                  whenJust w $ windows . W.view++-- | Send the active window to a given physical screen+sendToScreen :: PhysicalScreen -> X ()+sendToScreen p = do i <- getScreen p+                    whenJust i $ \s -> do+                      w <- screenWorkspace s+                      whenJust w $ windows . W.shift++-- | Compare two screens by their top-left corners, ordering+-- | top-to-bottom and then left-to-right.+cmpScreen :: Rectangle -> Rectangle -> Ordering+cmpScreen  (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (y1,x1) (y2,x2)
XMonad/Actions/Plane.hs view
@@ -29,6 +29,9 @@     , Limits (..)     , Lines (..) +    -- * Key bindings+    , planeKeys+     -- * Navigating through workspaces     , planeShift     , planeMove@@ -36,7 +39,8 @@     where  import Control.Monad-import Data.List hiding (union)+import Data.List+import Data.Map hiding (split) import Data.Maybe  import XMonad@@ -52,12 +56,7 @@ -- > -- > myKeys conf = union (keys defaultConfig conf) $ myNewKeys conf -- >--- > myNewkeys (XConfig {modMask = m}) =--- >     fromList--- >     [ ((keyMask .|. m, keySym), function (Lines 3) Finite direction)--- >     | (keySym, direction) <- zip [xK_Left .. xK_Down] $ enumFrom ToLeft--- >     , (keyMask, function) <- [(0, planeMove), (shiftMask, planeShift)]--- >     ]+-- > myNewkeys (XConfig {modMask = modm}) = planeKeys modm (Lines 3) Finite -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -65,13 +64,12 @@ -- | Direction to go in the plane. data Direction =  ToLeft | ToUp | ToRight | ToDown deriving Enum --- | Defines whether it's a finite or a circular organization of workspaces.+-- | Defines the behaviour when you're trying to move out of the limits. data Limits-    = Finite   -- ^ When you're at a edge of the plane, there's no way to move-               -- to the next region.-    | Circular -- ^ If you try to move, you'll get to the other edge, on the-               -- other side.-    | Linear   -- ^ The plan comes as a row.+    = Finite   -- ^ Ignore the function call, and keep in the same workspace.+    | Circular -- ^ Get on the other side, like in the Snake game.+    | Linear   -- ^ The plan comes as a row, so it goes to the next or prev if+               -- the workspaces were numbered.     deriving Eq  -- | The number of lines in which the workspaces will be arranged.  It's@@ -80,28 +78,24 @@ -- divisor, the last line will have the remaining workspaces. data Lines     = GConf     -- ^ Use @gconftool-2@ to find out the number of lines.-    | Lines Int -- ^ Specify the number of lines explicity.+    | Lines Int -- ^ Specify the number of lines explicitly. --- $navigating------ There're two parameters that must be provided to navigate, and it's a good--- idea to use them with the same values in each keybinding.------ The first is the number of lines in which the workspaces are going to be--- organized.  It's possible to use a number of lines that is not a divisor--- of the number of workspaces, but the results are better when using a--- divisor.  If it's not a divisor, the last line will have the remaining--- workspaces.------ The other one is 'Limits'.+-- | This is the way most people would like to use this module.  It attaches the+-- 'KeyMask' passed as a parameter with 'xK_Left', 'xK_Up', 'xK_Right' and+-- 'xK_Down', associating it with 'planeMove' to the corresponding 'Direction'.+-- It also associates these bindings with 'shiftMask' to 'planeShift'.+planeKeys :: KeyMask -> Lines -> Limits -> Map (KeyMask, KeySym) (X ())+planeKeys modm ln limits =+  fromList $+  [ ((keyMask, keySym), function ln limits direction)+  | (keySym, direction) <- zip [xK_Left .. xK_Down] $ enumFrom ToLeft+  , (keyMask, function) <- [(modm, planeMove), (shiftMask .|. modm, planeShift)]+  ]  -- | Shift a window to the next workspace in 'Direction'.  Note that this will--- also move to the next workspace.-planeShift-    :: Lines-    -> Limits-    -> Direction-    -> X ()+-- also move to the next workspace.  It's a good idea to use the same 'Lines'+-- and 'Limits' for all the bindings.+planeShift :: Lines -> Limits -> Direction -> X () planeShift = plane shift'  shift' ::
XMonad/Actions/Promote.hs view
@@ -33,7 +33,7 @@ -- -- then add a keybinding or substitute 'promote' in place of swapMaster: ----- >   , ((modMask x,               xK_Return), promote)+-- >   , ((modm,               xK_Return), promote) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
+ XMonad/Actions/RandomBackground.hs view
@@ -0,0 +1,72 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.RandomBackground+-- Copyright   :  (c) 2009 Anze Slosar+--                translation to Haskell by Adam Vogt+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  <vogt.adam@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- An action to start terminals with a random background color+--+-----------------------------------------------------------------------------++module XMonad.Actions.RandomBackground (+    -- * Usage+    -- $usage+    randomBg',+    randomBg,+    RandomColor(HSV,RGB)+    ) where++import XMonad(X, XConf(config), XConfig(terminal), io, spawn,+              MonadIO, asks)+import System.Random+import Control.Monad(liftM)+import Numeric(showHex)++-- $usage+--+-- Add to your keybindings something like:+--+-- > ,((modm .|. shiftMask, xK_Return), randomBg $ HSV 0xff 0x20++-- | RandomColor fixes constraints when generating random colors. All+-- parameters should be in the range 0 -- 0xff+data RandomColor = RGB { _colorMin :: Int+                       , _colorMax :: Int+                       } -- ^ specify the minimum and maximum lowest values for each color channel.+                 | HSV { _colorSaturation :: Double+                       , _colorValue :: Double+                       } -- ^ specify the saturation and value, leaving the hue random.++toHex :: [Int] -> String+toHex =  ("'#"++) . (++"'") . concatMap (ensure 2 . ($ "") . showHex)+    where ensure x = reverse . take x . (++repeat '0') . reverse++randPermutation ::  (RandomGen g) => [a] -> g -> [a]+randPermutation xs g = swap $ zip (randoms g) xs+  where+    swap ((True,x):(c,y):ys) = y:swap ((c,x):ys)+    swap ((False,x):ys) = x:swap ys+    swap x = map snd x++-- | @randomBg'@ produces a random hex number in the form @'#xxyyzz'@+randomBg' ::  (MonadIO m) => RandomColor -> m String+randomBg' (RGB l h) = io $ liftM (toHex . take 3 . randomRs (l,h)) newStdGen+randomBg' (HSV s v) = io $ do+    g <- newStdGen+    let x = (^(2::Int)) $ fst $ randomR (0,sqrt $ pi / 3) g+    return $ toHex $ map round $ randPermutation [v,(v-s)*x + s,s] g++-- | @randomBg@ starts a terminal with the background color taken from 'randomBg''+--+-- This depends on the your 'terminal' configuration field accepting an+-- argument like @-bg '#ff0023'@+randomBg :: RandomColor -> X ()+randomBg x = do+    t <- asks (terminal . config)+    c <- randomBg' x+    spawn $ t ++ " -bg " ++ c
XMonad/Actions/RotSlaves.hs view
@@ -5,7 +5,7 @@ -- License      : BSD3-style (see LICENSE) -- -- Maintainer   : Hans Philipp Annen <haphi@gmx.net>--- Stability    : unstable+-- Stability    : stable -- Portability  : unportable -- -- Rotate all windows except the master window and keep the focus in@@ -28,7 +28,7 @@ -- -- and add whatever keybindings you would like, for example: ----- > , ((modMask x .|. shiftMask, xK_Tab   ), rotSlavesUp)+-- > , ((modm .|. shiftMask, xK_Tab   ), rotSlavesUp) -- -- This operation will rotate all windows except the master window, -- while the focus stays where it is. It is useful together with the
XMonad/Actions/Search.hs view
@@ -10,39 +10,56 @@    Modeled after the handy Surfraw CLI search tools at <https://secure.wikimedia.org/wikipedia/en/wiki/Surfraw>.     Additional sites welcomed. -}-module XMonad.Actions.Search (    -- * Usage-                                  -- $usage-                               search,-                               SearchEngine(..),-                               searchEngine,-                               promptSearch,-                               promptSearchBrowser,-                               selectSearch,-                               selectSearchBrowser,--                               amazon,-                               codesearch,-                               dictionary,-                               google,-                               hoogle,-                               imdb,-                               maps,-                               mathworld,-                               scholar,-                               thesaurus,-                               wayback,-                               wikipedia,-                               youtube+module XMonad.Actions.Search (   -- * Usage+                                 -- $usage+                                 search,+                                 SearchEngine(..),+                                 searchEngine,+                                 searchEngineF,+                                 promptSearch,+                                 promptSearchBrowser,+                                 selectSearch,+                                 selectSearchBrowser,+                                 isPrefixOf,+                                 escape,+                                 use,+                                 intelligent,+                                 (!>),+                                 prefixAware,+                                 namedEngine, +                                 amazon,+                                 alpha,+                                 codesearch,+                                 deb,+                                 debbts,+                                 debpts,+                                 dictionary,+                                 google,+                                 hackage,+                                 hoogle,+                                 images,+                                 imdb,+                                 isohunt,+                                 lucky,+                                 maps,+                                 mathworld,+                                 scholar,+                                 thesaurus,+                                 wayback,+                                 wikipedia,+                                 wiktionary,+                                 youtube,+                                 multi                                   -- * Use case: searching with a submap                                   -- $tip-                           ) where  import Data.Char (chr, ord, isAlpha, isMark, isDigit)+import Data.List (isPrefixOf) import Numeric (showIntAtBase) import XMonad (X(), MonadIO, liftIO)-import XMonad.Prompt (XPrompt(showXPrompt), mkXPrompt, XPConfig(), historyCompletion)+import XMonad.Prompt (XPrompt(showXPrompt), mkXPrompt, XPConfig(), historyCompletionP) import XMonad.Prompt.Shell (getBrowser) import XMonad.Util.Run (safeSpawn) import XMonad.Util.XSelection (getSelection)@@ -73,16 +90,32 @@  * 'amazon' -- Amazon keyword search. +* 'alpha' -- Wolfram|Alpha query.+ * 'codesearch' -- Google Labs Code Search search. +* 'deb'    -- Debian package search.++* 'debbts' -- Debian Bug Tracking System.++* 'debpts'  -- Debian Package Tracking System.+ * 'dictionary' -- dictionary.reference.com search.  * 'google' -- basic Google search. -* 'hoogle' -- Hoogle, the Haskell libraries search engine.+* 'hackage' -- Hackage, the Haskell package database. +* 'hoogle' -- Hoogle, the Haskell libraries API search engine.++* 'images' -- Google images.+ * 'imdb'   -- the Internet Movie Database. +* 'isohunt' -- isoHunt search.++* 'lucky' -- Google "I'm feeling lucky" search.+ * 'maps'   -- Google maps.  * 'mathworld' -- Wolfram MathWorld search.@@ -97,6 +130,8 @@  * 'youtube' -- Youtube video search. +* 'multi' -- Search based on the prefix. \"amazon:Potter\" will use amazon, etc. With no prefix searches google.+ Feel free to add more! -}  {- $tip@@ -125,6 +160,22 @@ >       , ((0, xK_w), method S.wikipedia) >       ] +Or in combination with XMonad.Util.EZConfig:++> ...+> ] -- end of regular keybindings+> -- Search commands+> ++ [("M-s " ++ k, S.promptSearch P.defaultXPConfig f) | (k,f) <- searchList ]+> ++ [("M-S-s " ++ k, S.selectSearch f) | (k,f) <- searchList ]+>+> ...+>+> searchList :: [(String, S.SearchEngine)]+> searchList = [ ("g", S.google)+>              , ("h", S.hoohle)+>              , ("w", S.wikipedia)+>              ]+ Make sure to set firefox to open new pages in a new window instead of in a new tab: @Firefox -> Edit -> Preferences -> Tabs -> New pages should be opened in...@@@ -154,14 +205,14 @@                (Char -> Bool)      -- a predicate which returns 'False' if should escape                -> String           -- the string to process                -> String           -- the resulting URI string-           escapeURIString p s = concatMap (escapeURIChar p) s+           escapeURIString = concatMap . escapeURIChar            escapeURIChar :: (Char->Bool) -> Char -> String            escapeURIChar p c                | p c       = [c]                | otherwise = '%' : myShowHex (ord c) ""                where                  myShowHex :: Int -> ShowS-                 myShowHex n r =  case showIntAtBase 16 (toChrHex) n r of+                 myShowHex n r =  case showIntAtBase 16 toChrHex n r of                                     []  -> "00"                                     [ch] -> ['0',ch]                                     cs  -> cs@@ -171,14 +222,21 @@  type Browser      = FilePath type Query        = String-type Site         = String+type Site         = String -> String type Name         = String data SearchEngine = SearchEngine Name Site --- | Given a browser, a search engine, and a search term, perform the+-- | Given an already defined search engine, extracts its transformation+--   function, making it easy to create compound search engines.+--   For an instance you can use @use google@ to get a function which+--   makes the same transformation as the google search engine would.+use :: SearchEngine -> Site+use (SearchEngine _ engine) = engine++-- | Given a browser, a search engine's transformation function, and a search term, perform the --   requested search in the browser. search :: Browser -> Site -> Query -> X ()-search browser site query = safeSpawn browser (site ++ (escape query))+search browser site query = safeSpawn browser [site query]  {- | Given a base URL, create the 'SearchEngine' that escapes the query and    appends it to the base. You can easily define a new engine locally using@@ -188,38 +246,113 @@     The important thing is that the site has a interface which accepts the escaped query    string as part of the URL. Alas, the exact URL to feed searchEngine varies-   from site to site, often considerably, so there's no general way to cover this.+   from site to site, often considerably, so there\'s no general way to cover this.     Generally, examining the resultant URL of a search will allow you to reverse-engineer    it if you can't find the necessary URL already described in other projects such as Surfraw. -}-searchEngine :: Name -> Site -> SearchEngine-searchEngine name site = SearchEngine name site+searchEngine :: Name -> String -> SearchEngine+searchEngine name site = searchEngineF name (\s -> site ++ (escape s)) +{- | If your search engine is more complex than this (you may want to identify+   the kind of input and make the search URL dependent on the input or put the query+   inside of a URL instead of in the end) you can use the alternative 'searchEngineF' function.++> searchFunc :: String -> String+> searchFunc s | s `isPrefixOf` "wiki:"   = "http://en.wikipedia.org/wiki/" ++ (escape $ tail $ snd $ break (==':') s)+>              | s `isPrefixOf` "http://" = s+>              | otherwise               = (use google) s+> myNewEngine = searchEngineF "mymulti" searchFunc++   @searchFunc@ here searches for a word in wikipedia if it has a prefix+   of \"wiki:\" (you can use the 'escape' function to escape any forbidden characters), opens an address+   directly if it starts with \"http:\/\/\" and otherwise uses the provided google search engine.+   You can use other engines inside of your own through the 'use' function as shown above to make+   complex searches.++   The user input will be automatically escaped in search engines created with 'searchEngine',+   'searchEngineF', however, completely depends on the transformation function passed to it. -}+searchEngineF :: Name -> Site -> SearchEngine+searchEngineF = SearchEngine+ -- The engines.-amazon, codesearch, dictionary, google, hoogle, imdb, maps, mathworld,-  scholar, thesaurus, wayback, wikipedia, youtube :: SearchEngine+amazon, alpha, codesearch, deb, debbts, debpts, dictionary, google, hackage, hoogle,+  images, imdb, isohunt, lucky, maps, mathworld, scholar, thesaurus, wayback, wikipedia, wiktionary,+  youtube :: SearchEngine amazon     = searchEngine "amazon"     "http://www.amazon.com/exec/obidos/external-search?index=all&keyword="+alpha      = searchEngine "alpha"      "http://www.wolframalpha.com/input/?i=" codesearch = searchEngine "codesearch" "http://www.google.com/codesearch?q="-dictionary = searchEngine "dictionary" "http://dictionary.reference.com/browse/"+deb        = searchEngine "deb"        "http://packages.debian.org/"+debbts     = searchEngine "debbts"     "http://bugs.debian.org/"+debpts     = searchEngine "debpts"     "http://packages.qa.debian.org/"+dictionary = searchEngine "dict"       "http://dictionary.reference.com/browse/" google     = searchEngine "google"     "http://www.google.com/search?num=100&q="+hackage    = searchEngine "hackage"    "http://hackage.haskell.org/package/" hoogle     = searchEngine "hoogle"     "http://www.haskell.org/hoogle/?q="+images     = searchEngine "images"     "http://images.google.fr/images?q=" imdb       = searchEngine "imdb"       "http://www.imdb.com/Find?select=all&for="+isohunt    = searchEngine "isohunt"    "http://isohunt.com/torrents/?ihq="+lucky      = searchEngine "lucky"      "http://www.google.com/search?btnI&q=" maps       = searchEngine "maps"       "http://maps.google.com/maps?q=" mathworld  = searchEngine "mathworld"  "http://mathworld.wolfram.com/search/?query=" scholar    = searchEngine "scholar"    "http://scholar.google.com/scholar?q=" thesaurus  = searchEngine "thesaurus"  "http://thesaurus.reference.com/search?q="-wikipedia  = searchEngine "wikipedia"  "https://secure.wikimedia.org/wikipedia/en/wiki/Special:Search?go=Go&search="+wikipedia  = searchEngine "wiki"       "https://secure.wikimedia.org/wikipedia/en/wiki/Special:Search?go=Go&search="+wiktionary = searchEngine "wikt"      "http://en.wiktionary.org/wiki/Special:Search?go=Go&search=" youtube    = searchEngine "youtube"    "http://www.youtube.com/results?search_type=search_videos&search_query=" {- This doesn't seem to work, but nevertheless, it seems to be the official    method at <http://web.archive.org/collections/web/advanced.html> to get the    latest backup. -} wayback   = searchEngine "wayback" "http://web.archive.org/" +multi :: SearchEngine+multi = namedEngine "multi" $ foldr1 (!>) [amazon, alpha, codesearch, deb, debbts, debpts, dictionary, google, hackage, hoogle, images, imdb, isohunt, lucky, maps, mathworld, scholar, thesaurus, wayback, wikipedia, wiktionary, (prefixAware google)]++{- | This function wraps up a search engine and creates a new one, which works+   like the argument, but goes directly to a URL if one is given rather than+   searching.++> myIntelligentGoogleEngine = intelligent google++   Now if you search for http:\/\/xmonad.org it will directly open in your browser-}+intelligent :: SearchEngine -> SearchEngine+intelligent (SearchEngine name site) = searchEngineF name (\s -> if (fst $ break (==':') s) `elem` ["http", "https", "ftp"] then s else (site s))++-- | > removeColonPrefix "foo://bar" ~> "//bar"+-- > removeColonPrefix "foo//bar" ~> "foo//bar"+removeColonPrefix :: String -> String+removeColonPrefix s = if ':' `elem` s then drop 1 $ dropWhile (':' /=) s else s++{- | Connects a few search engines into one. If the search engines\' names are+   \"s1\", \"s2\" and \"s3\", then the resulting engine will use s1 if the query+   is @s1:word@, s2 if you type @s2:word@ and s3 in all other cases.++   Example:++> multiEngine = intelligent (wikipedia !> mathworld !> (prefixAware google))++  Now if you type \"wiki:Haskell\" it will search for \"Haskell\" in Wikipedia,+  \"mathworld:integral\" will search mathworld, and everything else will fall back to+  google. The use of intelligent will make sure that URLs are opened directly. -}+(!>) :: SearchEngine -> SearchEngine -> SearchEngine+(SearchEngine name1 site1) !> (SearchEngine name2 site2) = searchEngineF (name1 ++ "/" ++ name2) (\s -> if s `isPrefixOf` (name1++":") then site1 (removeColonPrefix s) else site2 s)++{- | Makes a search engine prefix-aware. Especially useful together with '!>'.+   It will automatically remove the prefix from a query so that you don\'t end+     up searching for google:xmonad if google is your fallback engine and you+     explicitly add the prefix. -}+prefixAware :: SearchEngine -> SearchEngine+prefixAware (SearchEngine name site) = SearchEngine name (\s -> if s `isPrefixOf` (name++":") then site $ removeColonPrefix s else site s)++{- | Changes search engine's name -}+namedEngine :: Name -> SearchEngine -> SearchEngine+namedEngine name (SearchEngine _ site) = searchEngineF name site+ {- | Like 'search', but for use with the output from a Prompt; it grabs the    Prompt's result, passes it to a given searchEngine and opens it in a given    browser. -} promptSearchBrowser :: XPConfig -> Browser -> SearchEngine -> X ()-promptSearchBrowser config browser (SearchEngine name site) = mkXPrompt (Search name) config (historyCompletion) $ search browser site+promptSearchBrowser config browser (SearchEngine name site) =+    mkXPrompt (Search name) config (historyCompletionP ("Search [" `isPrefixOf`)) $ search browser site  {- | Like 'search', but in this case, the string is not specified but grabbed  from the user's response to a prompt. Example:
XMonad/Actions/SimpleDate.hs view
@@ -29,7 +29,7 @@ -- -- and add a keybinding, for example: ----- >    , ((modMask x,               xK_d     ), date)+-- >    , ((modm,               xK_d     ), date) -- -- In this example, a popup date menu will now be bound to @mod-d@. --
XMonad/Actions/SinkAll.hs view
@@ -5,17 +5,20 @@ -- Stability    : unstable -- Portability  : unportable ----- Provides a simple binding that pushes all floating windows on the current--- workspace back into tiling.+-- Provides a simple binding that pushes all floating windows on the+-- current workspace back into tiling.  Note that the functionality of+-- this module has been folded into the more general+-- "XMonad.Actions.WithAll"; this module simply re-exports the+-- 'sinkAll' function for backwards compatibility. -----------------------------------------------------------------------------  module XMonad.Actions.SinkAll (     -- * Usage     -- $usage+     sinkAll) where -import XMonad-import XMonad.StackSet+import XMonad.Actions.WithAll (sinkAll)  -- $usage --@@ -25,16 +28,7 @@ -- -- then add a keybinding; for example: -----     , ((modMask x .|. shiftMask, xK_t), sinkAll)+-- >   , ((modm .|. shiftMask, xK_t), sinkAll) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".---- | Un-float all floating windows on the current workspace.-sinkAll :: X ()-sinkAll = withAll sink---- | Apply a function to all windows on current workspace.-withAll :: (Window -> WindowSet -> WindowSet) -> X ()-withAll f = windows $ \ws -> let all' = integrate' . stack . workspace . current $ ws-                             in foldr f ws all'
+ XMonad/Actions/SpawnOn.hs view
@@ -0,0 +1,122 @@+-----------------------------------------------------------------------------+-- |+-- Module       : XMonad.Actions.SpawnOn+-- Copyright    : (c) Spencer Janssen+-- License      : BSD+--+-- Maintainer   : Spencer Janssen <spencerjanssen@gmail.com>+-- Stability    : unstable+-- Portability  : unportable+--+-- Provides a way to modify a window spawned by a command(e.g shift it to the workspace+-- it was launched on) by using the _NET_WM_PID property that most windows set on creation.+-- Hence this module won't work on applications that don't set this property.+--+-----------------------------------------------------------------------------++module XMonad.Actions.SpawnOn (+    -- * Usage+    -- $usage+    Spawner,+    mkSpawner,+    manageSpawn,+    spawnHere,+    spawnOn,+    spawnAndDo,+    shellPromptHere,+    shellPromptOn+) where++import Data.List (isInfixOf)+import Data.IORef+import System.Posix.Types (ProcessID)++import XMonad+import qualified XMonad.StackSet as W++import XMonad.Hooks.ManageHelpers+import XMonad.Prompt+import XMonad.Prompt.Shell++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- >    import XMonad.Actions.SpawnOn+--+-- >    main = do+-- >      sp <- mkSpawner+-- >      xmonad defaultConfig {+-- >         ...+-- >         manageHook = manageSpawn sp <+> manageHook defaultConfig+-- >         ...+-- >      }+--+-- To ensure that application appears on a workspace it was launched at, add keybindings like:+--+-- >  , ((mod1Mask,xK_o), spawnHere sp "urxvt")+-- >  , ((mod1Mask,xK_s), shellPromptHere sp defaultXPConfig)+--+-- The module can also be used to apply other manage hooks to the window of+-- the spawned application(e.g. float or resize it).+--+-- For detailed instructions on editing your key bindings, see+-- "XMonad.Doc.Extending#Editing_key_bindings".++newtype Spawner = Spawner {pidsRef :: IORef [(ProcessID, ManageHook)]}++maxPids :: Int+maxPids = 5++-- | Create 'Spawner' which then has to be passed to other functions.+mkSpawner :: (Functor m, MonadIO m) => m Spawner+mkSpawner = io . fmap Spawner $ newIORef []++-- | Provides a manage hook to react on process spawned with+-- 'spawnOn', 'spawnHere' etc.+manageSpawn :: Spawner -> ManageHook+manageSpawn sp = do+    pids <- io . readIORef $ pidsRef sp+    mp <- pid+    case flip lookup pids =<< mp of+        Nothing -> doF id+        Just mh  -> do+            whenJust mp $ \p ->+                io . modifyIORef (pidsRef sp) $ filter ((/= p) . fst)+            mh++mkPrompt :: (String -> X ()) -> XPConfig -> X ()+mkPrompt cb c = do+    cmds <- io $ getCommands+    mkXPrompt Shell c (getShellCompl cmds) cb++-- | Replacement for Shell prompt ("XMonad.Prompt.Shell") which launches+-- application on current workspace.+shellPromptHere :: Spawner -> XPConfig -> X ()+shellPromptHere sp = mkPrompt (spawnHere sp)++-- | Replacement for Shell prompt ("XMonad.Prompt.Shell") which launches+-- application on given workspace.+shellPromptOn :: Spawner -> WorkspaceId -> XPConfig -> X ()+shellPromptOn sp ws = mkPrompt (spawnOn sp ws)++-- | Replacement for 'spawn' which launches+-- application on current workspace.+spawnHere :: Spawner -> String -> X ()+spawnHere sp cmd = withWindowSet $ \ws -> spawnOn sp (W.currentTag ws) cmd++-- | Replacement for 'spawn' which launches+-- application on given workspace.+spawnOn :: Spawner -> WorkspaceId -> String -> X ()+spawnOn sp ws cmd = spawnAndDo sp (doShift ws) cmd++-- | Spawn an application and apply the manage hook when it opens.+spawnAndDo :: Spawner -> ManageHook -> String -> X ()+spawnAndDo sp mh cmd = do+    p <- spawnPID $ mangle cmd+    io $ modifyIORef (pidsRef sp) (take maxPids . ((p,mh) :))+ where+    -- TODO this is silly, search for a better solution+    mangle xs | any (`elem` metaChars) xs || "exec" `isInfixOf` xs = xs+              | otherwise = "exec " ++ xs+    metaChars = "&|;"+
XMonad/Actions/Submap.hs view
@@ -15,9 +15,10 @@ module XMonad.Actions.Submap (                              -- * Usage                              -- $usage-                             submap+                             submap,+                             submapDefault                             ) where-+import Data.Bits import XMonad hiding (keys) import qualified Data.Map as M import Control.Monad.Fix (fix)@@ -33,7 +34,7 @@  Allows you to create a sub-mapping of keys. Example: ->    , ((modMask x, xK_a), submap . M.fromList $+>    , ((modm, xK_a), submap . M.fromList $ >        [ ((0, xK_n),     spawn "mpc next") >        , ((0, xK_p),     spawn "mpc prev") >        , ((0, xK_z),     spawn "mpc random")@@ -57,7 +58,11 @@ --   corresponding action, or does nothing if the key is not found in --   the map. submap :: M.Map (KeyMask, KeySym) (X ()) -> X ()-submap keys = do+submap keys = submapDefault (return ()) keys++-- | Like 'submap', but executes a default action if the key did not match.+submapDefault :: X () -> M.Map (KeyMask, KeySym) (X ()) -> X ()+submapDefault def keys = do     XConf { theRoot = root, display = d } <- ask      io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime@@ -69,8 +74,8 @@         if isModifierKey keysym             then nextkey             else return (m, keysym)+    -- Remove num lock mask and Xkb group state bits+    m' <- cleanMask $ m .&. ((1 `shiftL` 12) - 1)+    maybe def id (M.lookup (m', s) keys)      io $ ungrabKeyboard d currentTime--    m' <- cleanMask m-    whenJust (M.lookup (m', s) keys) id
XMonad/Actions/SwapWorkspaces.hs view
@@ -19,12 +19,13 @@                                      swapWithCurrent,                                      swapTo,                                      swapWorkspaces,-                                     WSDirection(..)+                                     Direction1D(..)                                     ) where  import XMonad (windows, X()) import XMonad.StackSet import XMonad.Actions.CycleWS+import XMonad.Util.Types import XMonad.Util.WorkspaceCompare  @@ -36,7 +37,7 @@ -- Then throw something like this in your keys definition: -- -- > ++--- > [((modMask x .|. controlMask, k), windows $ swapWithCurrent i)+-- > [((modm .|. controlMask, k), windows $ swapWithCurrent i) -- >     | (i, k) <- zip workspaces [xK_1 ..]] -- -- After installing this update, if you're on workspace 1, hitting mod-ctrl-5@@ -48,11 +49,11 @@ -- | Swaps the currently focused workspace with the given workspace tag, via --   @swapWorkspaces@. swapWithCurrent :: Eq i => i -> StackSet i l a s sd -> StackSet i l a s sd-swapWithCurrent t s = swapWorkspaces t (tag $ workspace $ current s) s+swapWithCurrent t s = swapWorkspaces t (currentTag s) s  -- | Say @swapTo Next@ or @swapTo Prev@ to move your current workspace. -- This is an @X ()@ so can be hooked up to your keybindings directly.-swapTo :: WSDirection -> X ()+swapTo :: Direction1D -> X () swapTo dir = findWorkspace getSortByIndex dir AnyWS 1 >>= windows . swapWithCurrent  -- | Takes two workspace tags and an existing XMonad.StackSet and returns a new
XMonad/Actions/TagWindows.hs view
@@ -42,16 +42,16 @@ -- -- and add keybindings such as the following: ----- >   , ((modMask x,                 xK_f  ), withFocused (addTag "abc"))--- >   , ((modMask x .|. controlMask, xK_f  ), withFocused (delTag "abc"))--- >   , ((modMask x .|. shiftMask,   xK_f  ), withTaggedGlobal "abc" sink)--- >   , ((modMask x,                 xK_d  ), withTaggedP "abc" (shiftWin "2"))--- >   , ((modMask x .|. shiftMask,   xK_d  ), withTaggedGlobalP "abc" shiftHere)--- >   , ((modMask x .|. controlMask, xK_d  ), focusUpTaggedGlobal "abc")--- >   , ((modMask x,                 xK_g  ), tagPrompt defaultXPConfig (\s -> withFocused (addTag s)))--- >   , ((modMask x .|. controlMask, xK_g  ), tagDelPrompt defaultXPConfig)--- >   , ((modMask x .|. shiftMask,   xK_g  ), tagPrompt defaultXPConfig (\s -> withTaggedGlobal s float))--- >   , ((modWinMask,                xK_g  ), tagPrompt defaultXPConfig (\s -> withTaggedP s (shiftWin "2")))+-- >   , ((modm,                 xK_f  ), withFocused (addTag "abc"))+-- >   , ((modm .|. controlMask, xK_f  ), withFocused (delTag "abc"))+-- >   , ((modm .|. shiftMask,   xK_f  ), withTaggedGlobalP "abc" W.sink)+-- >   , ((modm,                 xK_d  ), withTaggedP "abc" (W.shiftWin "2"))+-- >   , ((modm .|. shiftMask,   xK_d  ), withTaggedGlobalP "abc" shiftHere)+-- >   , ((modm .|. controlMask, xK_d  ), focusUpTaggedGlobal "abc")+-- >   , ((modm,                 xK_g  ), tagPrompt defaultXPConfig (\s -> withFocused (addTag s)))+-- >   , ((modm .|. controlMask, xK_g  ), tagDelPrompt defaultXPConfig)+-- >   , ((modm .|. shiftMask,   xK_g  ), tagPrompt defaultXPConfig (\s -> withTaggedGlobal s float))+-- >   , ((modWinMask,                xK_g  ), tagPrompt defaultXPConfig (\s -> withTaggedP s (W.shiftWin "2"))) -- >   , ((modWinMask .|. shiftMask,  xK_g  ), tagPrompt defaultXPConfig (\s -> withTaggedGlobalP s shiftHere)) -- >   , ((modWinMask .|. controlMask, xK_g ), tagPrompt defaultXPConfig (\s -> focusUpTaggedGlobal s)) --@@ -120,7 +120,7 @@ wsToListGlobal :: (Ord i) => StackSet i l a s sd -> [a] wsToListGlobal ws = concat ([crs] ++ rws ++ lws ++ [cls])     where-        curtag = tag . workspace . current $ ws+        curtag = currentTag ws         (crs, cls) = (cms down, cms (reverse . up))         cms f = maybe [] f (stack . workspace . current $ ws)         (lws, rws) = (mws (<), mws (>))@@ -149,8 +149,7 @@ withTaggedGlobal t f = withTaggedGlobal' t (mapM_ f)  withTagged' :: String -> ([Window] -> X ()) -> X ()-withTagged' t m = gets windowset >>=-    filterM (hasTag t) . integrate' . stack . workspace . current >>= m+withTagged' t m = gets windowset >>= filterM (hasTag t) . index >>= m  withTaggedGlobal' :: String -> ([Window] -> X ()) -> X () withTaggedGlobal' t m = gets windowset >>=@@ -160,7 +159,7 @@ withFocusedP f = withFocused $ windows . f  shiftHere :: (Ord a, Eq s, Eq i) => a -> StackSet i l a s sd -> StackSet i l a s sd-shiftHere w s = shiftWin (tag . workspace . current $ s) w s+shiftHere w s = shiftWin (currentTag s) w s  shiftToScreen :: (Ord a, Eq s, Eq i) => s -> a -> StackSet i l a s sd -> StackSet i l a s sd shiftToScreen sid w s = case filter (\m -> sid /= screen m) ((current s):(visible s)) of
+ XMonad/Actions/TopicSpace.hs view
@@ -0,0 +1,317 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.TopicSpace+-- Copyright   :  (c) Nicolas Pouillard+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Nicolas Pouillard <nicolas.pouillard@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Turns your workspaces into a more topic oriented system.+-----------------------------------------------------------------------------++module XMonad.Actions.TopicSpace+  (+  -- * Overview+  -- $overview++  -- * Usage+  -- $usage+   Topic+  , Dir+  , TopicConfig(..)+  , getLastFocusedTopics+  , setLastFocusedTopic+  , pprWindowSet+  , topicActionWithPrompt+  , topicAction+  , currentTopicAction+  , switchTopic+  , switchNthLastFocused+  , shiftNthLastFocused+  , currentTopicDir+  , checkTopicConfig+  , (>*>)+  )+where++import XMonad++import Data.List+import Data.Maybe (fromMaybe, isNothing, listToMaybe)+import Data.Ord+import qualified Data.Map as M+import Control.Monad ((=<<),liftM2,when,unless,replicateM_)+import System.IO++import XMonad.Operations+import qualified XMonad.StackSet as W++import XMonad.Prompt+import XMonad.Prompt.Workspace++import XMonad.Hooks.UrgencyHook+import XMonad.Hooks.DynamicLog (PP(..))+import qualified XMonad.Hooks.DynamicLog as DL++import XMonad.Util.Run (spawnPipe)+import XMonad.Util.StringProp(getStringListProp,setStringListProp)++-- $overview+-- This module allows to organize your workspaces on a precise topic basis.  So+-- instead of having a workspace called `work' you can setup one workspace per+-- task.  Here we call these workspaces, topics. The great thing with+-- topics is that one can attach a directory that makes sense to each+-- particular topic.  One can also attach an action which will be triggered+-- when switching to a topic that does not have any windows in it.  So you can+-- attach your mail client to the mail topic, some terminals in the right+-- directory to the xmonad topic... This package also provides a nice way to+-- display your topics in an historical way using a custom `pprWindowSet'+-- function. You can also easily switch to recent topics using this history+-- of last focused topics.++-- $usage+-- Here is an example of configuration using TopicSpace:+--+-- @+-- -- The list of all topics/workspaces of your xmonad configuration.+-- -- The order is important, new topics must be inserted+-- -- at the end of the list if you want hot-restarting+-- -- to work.+-- myTopics :: [Topic]+-- myTopics =+--   [ \"dashboard\" -- the first one+--   , \"admin\", \"build\", \"cleaning\", \"conf\", \"darcs\", \"haskell\", \"irc\"+--   , \"mail\", \"movie\", \"music\", \"talk\", \"text\", \"tools\", \"web\", \"xmonad\"+--   , \"yi\", \"documents\", \"twitter\", \"pdf\"+--   ]+-- @+--+-- @+--  myTopicConfig :: TopicConfig+--  myTopicConfig = TopicConfig+--    { topicDirs = M.fromList $+--        [ (\"conf\", \"w\/conf\")+--        , (\"dashboard\", \"Desktop\")+--        , (\"yi\", \"w\/dev-haskell\/yi\")+--        , (\"darcs\", \"w\/dev-haskell\/darcs\")+--        , (\"haskell\", \"w\/dev-haskell\")+--        , (\"xmonad\", \"w\/dev-haskell\/xmonad\")+--        , (\"tools\", \"w\/tools\")+--        , (\"movie\", \"Movies\")+--        , (\"talk\", \"w\/talks\")+--        , (\"music\", \"Music\")+--        , (\"documents\", \"w\/documents\")+--        , (\"pdf\", \"w\/documents\")+--        ]+--    , defaultTopicAction = const $ spawnShell >*> 3+--    , defaultTopic = \"dashboard\"+--    , maxTopicHistory = 10+--    , topicActions = M.fromList $+--        [ (\"conf\",       spawnShell >> spawnShellIn \"wd\/ertai\/private\")+--        , (\"darcs\",      spawnShell >*> 3)+--        , (\"yi\",         spawnShell >*> 3)+--        , (\"haskell\",    spawnShell >*> 2 >>+--                         spawnShellIn \"wd\/dev-haskell\/ghc\")+--        , (\"xmonad\",     spawnShellIn \"wd\/x11-wm\/xmonad\" >>+--                         spawnShellIn \"wd\/x11-wm\/xmonad\/contrib\" >>+--                         spawnShellIn \"wd\/x11-wm\/xmonad\/utils\" >>+--                         spawnShellIn \".xmonad\" >>+--                         spawnShellIn \".xmonad\")+--        , (\"mail\",       mailAction)+--        , (\"irc\",        ssh somewhere)+--        , (\"admin\",      ssh somewhere >>+--                         ssh nowhere)+--        , (\"dashboard\",  spawnShell)+--        , (\"twitter\",    spawnShell)+--        , (\"web\",        spawn browserCmd)+--        , (\"movie\",      spawnShell)+--        , (\"documents\",  spawnShell >*> 2 >>+--                         spawnShellIn \"Documents\" >*> 2)+--        , (\"pdf\",        spawn pdfViewerCmd)+--        ]+--    }+-- @+--+-- @+--  -- extend your keybindings+--  myKeys conf\@XConfig{modMask=modm} =+--    [ ((modm              , xK_n     ), spawnShell) -- %! Launch terminal+--    , ((modm              , xK_a     ), currentTopicAction myTopicConfig)+--    , ((modm              , xK_g     ), promptedGoto)+--    , ((modm .|. shiftMask, xK_g     ), promptedShift)+--    ...+--    ]+--    +++--    [ ((modm, k), switchNthLastFocused myTopicConfig i)+--    | (i, k) <- zip [1..] workspaceKeys]+-- @+--+-- @+--  spawnShell :: X ()+--  spawnShell = currentTopicDir myTopicConfig >>= spawnShellIn+-- @+--+-- @+--  spawnShellIn :: Dir -> X ()+--  spawnShellIn dir = spawn $ \"urxvt '(cd ''\" ++ dir ++ \"'' && \" ++ myShell ++ \" )'\"+-- @+--+-- @+--  goto :: Topic -> X ()+--  goto = switchTopic myTopicConfig+-- @+--+-- @+--  promptedGoto :: X ()+--  promptedGoto = workspacePrompt myXPConfig goto+-- @+--+-- @+--  promptedShift :: X ()+--  promptedShift = workspacePrompt myXPConfig $ windows . W.shift+-- @+--+-- @+--  myConfig = do+--      checkTopicConfig myTopics myTopicConfig+--      myLogHook <- makeMyLogHook+--      return $ defaultConfig+--           { borderWidth = 1 -- Width of the window border in pixels.+--           , workspaces = myTopics+--           , layoutHook = myModifiers myLayout+--           , manageHook = myManageHook+--           , logHook = myLogHook+--           , handleEventHook = myHandleEventHook+--           , terminal = myTerminal -- The preferred terminal program.+--           , normalBorderColor = \"#3f3c6d\"+--           , focusedBorderColor = \"#4f66ff\"+--           , XMonad.modMask = mod1Mask+--           , keys = myKeys+--           , mouseBindings = myMouseBindings+--           }+-- @+--+-- @+--  main :: IO ()+--  main = xmonad =<< myConfig+-- @++-- | An alias for @flip replicateM_@+(>*>) :: Monad m => m a -> Int -> m ()+(>*>) = flip replicateM_+infix >*>++-- | 'Topic' is just an alias for 'WorkspaceId'+type Topic = WorkspaceId++-- | 'Dir' is just an alias for 'FilePath' but should points to a directory.+type Dir = FilePath++-- | Here is the topic space configuration area.+data TopicConfig = TopicConfig { topicDirs          :: M.Map Topic Dir+                                 -- ^ This mapping associate a directory to each topic.+                               , topicActions       :: M.Map Topic (X ())+                                 -- ^ This mapping associate an action to trigger when+                                 -- switching to a given topic which workspace is empty.+                               , defaultTopicAction :: Topic -> X ()+                                 -- ^ This is the default topic action.+                               , defaultTopic       :: Topic+                                 -- ^ This is the default topic.+                               , maxTopicHistory    :: Int+                                 -- ^ This setups the maximum depth of topic history, usually+                                 -- 10 is a good default since we can bind all of them using+                                 -- numeric keypad.+                               }++-- | Returns the list of last focused workspaces the empty list otherwise.+-- This function rely on a reserved property namely _XMONAD_LAST_FOCUSED_WORKSPACES.+getLastFocusedTopics :: X [String]+getLastFocusedTopics = asks display >>= flip getStringListProp "_XMONAD_LAST_FOCUSED_WORKSPACES"++-- | Given a 'TopicConfig', the last focused topic, and a predicate that will+-- select topics that one want to keep, this function will set the property+-- of last focused topics.+setLastFocusedTopic :: TopicConfig -> Topic -> (Topic -> Bool) -> X ()+setLastFocusedTopic tg w predicate = do+  disp <- asks display+  setStringListProp disp "_XMONAD_LAST_FOCUSED_WORKSPACES"+    . take (maxTopicHistory tg) . nub . (w:) . filter predicate =<< getLastFocusedTopics++-- | This function is a variant of 'DL.pprWindowSet' which takes a topic configuration+-- and a pretty-printing record 'PP'. It will show the list of topics sorted historically+-- and highlighting topics with urgent windows.+pprWindowSet :: TopicConfig -> PP -> X String+pprWindowSet tg pp = do+    winset <- gets windowset+    urgents <- readUrgents+    let empty_workspaces = map W.tag $ filter (isNothing . W.stack) $ W.workspaces winset+        maxDepth = maxTopicHistory tg+    setLastFocusedTopic tg (W.tag . W.workspace . W.current $ winset)+                           (`notElem` empty_workspaces)+    lastWs <- getLastFocusedTopics+    let depth topic = elemIndex topic lastWs+        add_depth proj topic = proj pp $ maybe topic (((topic++":")++) . show) $ depth topic+        pp' = pp { ppHidden = add_depth ppHidden, ppVisible = add_depth ppVisible }+        sortWindows = take (maxDepth - 1) . sortBy (comparing $ fromMaybe maxDepth . depth . W.tag)+    return $ DL.pprWindowSet sortWindows urgents pp' winset++-- | Given a prompt configuration and a topic configuration, triggers the action associated with+-- the topic given in prompt.+topicActionWithPrompt :: XPConfig -> TopicConfig -> X ()+topicActionWithPrompt xp tg = workspacePrompt xp (liftM2 (>>) (switchTopic tg) (topicAction tg))++-- | Given a configuration and a topic, triggers the action associated with the given topic.+topicAction :: TopicConfig -> Topic -> X ()+topicAction tg topic = fromMaybe (defaultTopicAction tg topic) $ M.lookup topic $ topicActions tg++-- | Trigger the action associated with the current topic.+currentTopicAction :: TopicConfig -> X ()+currentTopicAction tg = topicAction tg =<< gets (W.tag . W.workspace . W.current . windowset)++-- | Switch to the given topic.+switchTopic :: TopicConfig -> Topic -> X ()+switchTopic tg topic = do+  windows $ W.greedyView topic+  wins <- gets (W.integrate' . W.stack . W.workspace . W.current . windowset)+  when (null wins) $ topicAction tg topic++-- | Switch to the Nth last focused topic or failback to the 'defaultTopic'.+switchNthLastFocused ::TopicConfig -> Int -> X ()+switchNthLastFocused tg depth = do+  lastWs <- getLastFocusedTopics+  switchTopic tg $ (lastWs ++ repeat (defaultTopic tg)) !! depth++-- | Shift the focused window to the Nth last focused topic, or fallback to doing nothing.+shiftNthLastFocused :: Int -> X ()+shiftNthLastFocused n = do+  ws <- fmap (listToMaybe . drop n) getLastFocusedTopics+  whenJust ws $ windows . W.shift++-- | Returns the directory associated with current topic returns the empty string otherwise.+currentTopicDir :: TopicConfig -> X String+currentTopicDir tg = do+  topic <- gets (W.tag . W.workspace . W.current . windowset)+  return . fromMaybe "" . M.lookup topic $ topicDirs tg++-- | Check the given topic configuration for duplicates topics or undefined topics.+checkTopicConfig :: [Topic] -> TopicConfig -> IO ()+checkTopicConfig tags tg = do+    -- tags <- gets $ map W.tag . workspaces . windowset++    let+      seenTopics = nub $ sort $ M.keys (topicDirs tg) ++ M.keys (topicActions tg)+      dups       = tags \\ nub tags+      diffTopic  = seenTopics \\ sort tags+      check lst msg = unless (null lst) $ xmessage $ msg ++ " (tags): " ++ show lst++    check diffTopic "Seen but missing topics/workspaces"+    check dups      "Duplicate topics/workspaces"++-- | Display the given message using the @xmessage@ program.+xmessage :: String -> IO ()+xmessage s = do+  h <- spawnPipe "xmessage -file -"+  hPutStr h s+  hClose h
+ XMonad/Actions/UpdateFocus.hs view
@@ -0,0 +1,61 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.UpdateFocus+-- Copyright   :  (c) Daniel Schoepe+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Daniel Schoepe <asgaroth_@gmx.de>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Updates the focus on mouse move in unfocused windows.+--+-----------------------------------------------------------------------------++module XMonad.Actions.UpdateFocus (+    -- * Usage+    -- $usage+    focusOnMouseMove,+    adjustEventInput+) where++import XMonad+import qualified XMonad.StackSet as W+import Graphics.X11.Xlib.Extras+import Control.Monad (when)+import Data.Monoid++-- $usage+-- To make the focus update on mouse movement within an unfocused window, add the+-- following to your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Actions.UpdateFocus+-- > xmonad $ defaultConfig {+-- >   ..+-- >   startupHook = adjustEventInput+-- >   handleEventHook = focusOnMouseMove+-- >   ..+-- > }+--+-- This module is probably only useful when focusFollowsMouse is set to True(default).++-- | Changes the focus if the mouse is moved within an unfocused window.+focusOnMouseMove :: Event -> X All+focusOnMouseMove (MotionEvent { ev_x = x, ev_y = y, ev_window = root }) = do+    -- check only every 15 px to avoid excessive calls to translateCoordinates+    when (x `mod` 15 == 0 || y `mod` 15 == 0) $ do+      dpy <- asks display+      Just foc <- withWindowSet $ return . W.peek+      -- get the window under the pointer:+      (_,_,_,w) <- io $ translateCoordinates dpy root root (fromIntegral x) (fromIntegral y)+      when (foc /= w) $ focus w+    return (All True)+focusOnMouseMove _ = return (All True)++-- | Adjusts the event mask to pick up pointer movements.+adjustEventInput :: X ()+adjustEventInput = withDisplay $ \dpy -> do+  rootw <- asks theRoot+  io $ selectInput dpy rootw $  substructureRedirectMask .|. substructureNotifyMask+                                .|. enterWindowMask .|. leaveWindowMask .|. structureNotifyMask+                                .|. buttonPressMask .|. pointerMotionMask
XMonad/Actions/UpdatePointer.hs view
@@ -3,7 +3,7 @@ -- Module      :  XMonadContrib.UpdatePointer -- Copyright   :  (c) Robert Marlow <robreim@bobturf.org> -- License     :  BSD3-style (see LICENSE)--- +-- -- Maintainer  :  Robert Marlow <robreim@bobturf.org> -- Stability   :  stable -- Portability :  portable@@ -14,7 +14,7 @@ -- ----------------------------------------------------------------------------- -module XMonad.Actions.UpdatePointer +module XMonad.Actions.UpdatePointer     (      -- * Usage      -- $usage@@ -25,7 +25,8 @@  import XMonad import Control.Monad-import XMonad.StackSet (member)+import XMonad.StackSet (member, peek, screenDetail, current)+import Data.Maybe  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:@@ -34,9 +35,9 @@ -- > import XMonad.Actions.UpdatePointer -- -- Enable it by including it in your logHook definition. Eg:--- +-- -- > logHook = updatePointer Nearest--- +-- -- which will move the pointer to the nearest point of a newly focused window, or -- -- > logHook = updatePointer (Relative 0.5 0.5)@@ -50,43 +51,55 @@ -- -- which moves the pointer to the bottom-right corner of the focused window. -data PointerPosition = Nearest | Relative Rational Rational+data PointerPosition = Nearest | Relative Rational Rational | TowardsCentre Rational Rational+    deriving (Read,Show)  -- | Update the pointer's location to the currently focused--- window unless it's already there, or unless the user was changing+-- window or empty screen unless it's already there, or unless the user was changing -- focus with the mouse updatePointer :: PointerPosition -> X ()-updatePointer p = withFocused $ \w -> do+updatePointer p = do   ws <- gets windowset   dpy <- asks display+  rect <- case peek ws of+        Nothing -> return $ (screenRect . screenDetail .current) ws+        Just w  -> windowAttributesToRectangle `fmap` io (getWindowAttributes dpy w)   root <- asks theRoot   mouseIsMoving <- asks mouseFocused-  wa <- io $ getWindowAttributes dpy w   (_sameRoot,_,currentWindow,rootx,rooty,_,_,_) <- io $ queryPointer dpy root-  unless (pointWithinRegion rootx rooty (wa_x wa) (wa_y wa) (wa_width wa) (wa_height wa)+  drag <- gets dragging+  unless (pointWithin (fi rootx) (fi rooty) rect           || mouseIsMoving-          || not (currentWindow `member` ws)) $+          || isJust drag+          || not (currentWindow `member` ws || currentWindow == none)) $     case p of     Nearest -> do-      let x = moveWithin rootx (wa_x wa) ((wa_x wa) + (wa_width  wa))-      let y = moveWithin rooty (wa_y wa) ((wa_y wa) + (wa_height wa))-      io $ warpPointer dpy none root 0 0 0 0 (fromIntegral x) (fromIntegral y)+      let x = moveWithin (fi rootx) (rect_x rect) (fi (rect_x rect) + fi (rect_width  rect))+          y = moveWithin (fi rooty) (rect_y rect) (fi (rect_y rect) + fi (rect_height rect))+      io $ warpPointer dpy none root 0 0 0 0 x y+    TowardsCentre xfrc yfrc -> do+      let cx = fi (rect_width rect) / 2 + fi (rect_x rect)+          cy = fi (rect_height rect) / 2 + fi (rect_y rect)+          x,y,cx,cy :: Rational+          x = moveWithin (fi rootx) (fi $ rect_x rect) (fi (rect_x rect) + fi (rect_width  rect))+          y = moveWithin (fi rooty) (fi $ rect_y rect) (fi (rect_y rect) + fi (rect_height rect))+      io $ warpPointer dpy none root 0 0 0 0 (round $ x + xfrc*(cx-x)) (round $ y + yfrc*(cy-y))     Relative h v ->-      io $ warpPointer dpy none w 0 0 0 0-           (fraction h (wa_width wa)) (fraction v (wa_height wa))+      io $ warpPointer dpy none root 0 0 0 0+           (rect_x rect + fraction h (rect_width rect))+           (rect_y rect + fraction v (rect_height rect))         where fraction x y = floor (x * fromIntegral y) -moveWithin :: Integral a => a -> a -> a -> a-moveWithin current lower upper =-    if current < lower+windowAttributesToRectangle :: WindowAttributes -> Rectangle+windowAttributesToRectangle wa = Rectangle (fi (wa_x wa))     (fi (wa_y wa))+                                           (fi (wa_width wa)) (fi (wa_height wa))+moveWithin :: Ord a => a -> a -> a -> a+moveWithin now lower upper =+    if now < lower     then lower-    else if current > upper+    else if now > upper          then upper-         else current+         else now --- Test that a point resides within a region. --- This belongs somewhere more generally accessible than this module.-pointWithinRegion :: Integral a => a -> a -> a -> a -> a -> a -> Bool-pointWithinRegion px py rx ry rw rh =-    within px rx (rx + rw) && within py ry (ry + rh)-    where within x left right = x >= left && x <= right+fi :: (Num b, Integral a) => a -> b+fi = fromIntegral
XMonad/Actions/Warp.hs view
@@ -16,6 +16,7 @@                            -- * Usage                            -- $usage                            banish,+                           banishScreen,                            Corner(..),                            warpToScreen,                            warpToWindow@@ -33,11 +34,11 @@  then add appropriate keybindings to warp the pointer; for example: -> , ((modMask x,   xK_z     ), warpToWindow (1%2) (1%2)) -- @@ Move pointer to currently focused window+> , ((modm,   xK_z     ), warpToWindow (1%2) (1%2)) -- @@ Move pointer to currently focused window > >-- mod-ctrl-{w,e,r} @@ Move mouse pointer to screen 1, 2, or 3 >->   [((modMask x .|. controlMask, key), warpToScreen sc (1%2) (1%2))+>   [((modm .|. controlMask, key), warpToScreen sc (1%2) (1%2)) >       | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]]  Note that warping to a particular screen may change the focus.@@ -49,7 +50,7 @@  data Corner = UpperLeft | UpperRight | LowerLeft | LowerRight -{- | Move the mouse cursor to a corner of the screen. Useful for+{- | Move the mouse cursor to a corner of the focused window. Useful for    uncluttering things.     Internally, this uses numerical parameters. We parametrize on the 'Corner'@@ -64,7 +65,22 @@                      LowerRight -> warpToWindow 1 1                      LowerLeft  -> warpToWindow 0 1                      UpperLeft  -> warpToWindow 0 0-                     UpperRight  -> warpToWindow 1 0+                     UpperRight -> warpToWindow 1 0++{- | Same as 'banish' but moves the mouse to the corner of the+   currently focused screen -}+banishScreen :: Corner -> X ()+banishScreen direction = case direction of+                           LowerRight -> warpToCurrentScreen 1 1+                           LowerLeft  -> warpToCurrentScreen 0 1+                           UpperLeft  -> warpToCurrentScreen 0 0+                           UpperRight -> warpToCurrentScreen 1 0+    where+      warpToCurrentScreen h v =+          do ws <- gets windowset+             warpToScreen (W.screen $ current ws) h v+             windows (const ws)+  fraction :: (Integral a, Integral b) => Rational -> a -> b fraction f x = floor (f * fromIntegral x)
XMonad/Actions/WindowBringer.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD-style (see LICENSE) -- -- Maintainer  :  Devin Mullins <me@twifkak.com>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- dmenu operations to bring windows to you, and bring you to windows.@@ -15,11 +15,11 @@ -----------------------------------------------------------------------------  module XMonad.Actions.WindowBringer (-                                    -- * Usage-                                    -- $usage-                                    gotoMenu, bringMenu, windowMap,-                                    bringWindow-                                   ) where+                    -- * Usage+                    -- $usage+                    gotoMenu, gotoMenu', bringMenu, windowMap,+                    bringWindow+                   ) where  import Data.Char (toLower) import qualified Data.Map as M@@ -27,7 +27,7 @@ import qualified XMonad.StackSet as W import XMonad import qualified XMonad as X-import XMonad.Util.Dmenu (dmenuMap)+import XMonad.Util.Dmenu (menuMap) import XMonad.Util.NamedWindows (getName)  -- $usage@@ -38,8 +38,8 @@ -- -- and define appropriate key bindings: ----- > , ((modMask x .|. shiftMask, xK_g     ), gotoMenu)--- > , ((modMask x .|. shiftMask, xK_b     ), bringMenu)+-- > , ((modm .|. shiftMask, xK_g     ), gotoMenu)+-- > , ((modm .|. shiftMask, xK_b     ), bringMenu) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -50,6 +50,9 @@ gotoMenu :: X () gotoMenu = actionMenu W.focusWindow +gotoMenu' :: String -> X ()+gotoMenu' menuCmd = actionMenu' menuCmd W.focusWindow+ -- | Pops open a dmenu with window titles. Choose one, and it will be --   dragged, kicking and screaming, into your current workspace. bringMenu :: X ()@@ -57,12 +60,18 @@  -- | Brings the specified window into the current workspace. bringWindow :: Window -> X.WindowSet -> X.WindowSet-bringWindow w ws = W.shiftWin (W.tag . W.workspace . W.current $ ws) w ws+bringWindow w ws = W.shiftWin (W.currentTag ws) w ws  -- | Calls dmenuMap to grab the appropriate Window, and hands it off to action --   if found. actionMenu :: (Window -> X.WindowSet -> X.WindowSet) -> X()-actionMenu action = windowMap >>= dmenuMap >>= flip X.whenJust (windows . action)+actionMenu action = actionMenu' "dmenu" action++actionMenu' :: String -> (Window -> X.WindowSet -> X.WindowSet) -> X()+actionMenu' menuCmd action = windowMap >>= menuMapFunction >>= flip X.whenJust (windows . action)+    where+      menuMapFunction :: M.Map String a -> X (Maybe a)+      menuMapFunction selectionMap = menuMap menuCmd selectionMap  -- | A map from window names to Windows. windowMap :: X (M.Map String Window)
XMonad/Actions/WindowGo.hs view
@@ -24,17 +24,27 @@                   raiseBrowser,                  raiseEditor,+                 runOrRaiseAndDo,+                 runOrRaiseMaster,+                 raiseAndDo,+                 raiseMaster,++                 ifWindows,+                 ifWindow,+                 raiseHook,                  module XMonad.ManageHook                 ) where -import Control.Monad (filterM)+import Control.Monad import Data.Char (toLower)--import XMonad (Query(), X(), withWindowSet, spawn, runQuery, liftIO, focus)+import Data.Monoid+import XMonad (Query(), X(), ManageHook, withWindowSet, runQuery, liftIO, ask)+import Graphics.X11 (Window) import XMonad.ManageHook+import XMonad.Operations (windows) import XMonad.Prompt.Shell (getBrowser, getEditor)-import qualified XMonad.StackSet as W (allWindows, peek)-+import qualified XMonad.StackSet as W (allWindows, peek, swapMaster, focusWindow)+import XMonad.Util.Run (safeSpawnProg) {- $usage  Import the module into your @~\/.xmonad\/xmonad.hs@:@@ -43,8 +53,8 @@  and define appropriate key bindings: -> , ((modMask x .|. shiftMask, xK_g), raise (className =? "Firefox"))-> , ((modMask x .|. shiftMask, xK_b), runOrRaise "firefox" (className =? "Firefox"))+> , ((modm .|. shiftMask, xK_g), raise (className =? "Firefox"))+> , ((modm .|. shiftMask, xK_b), runOrRaise "firefox" (className =? "Firefox"))  (Note that Firefox v3 and up have a class-name of \"Firefox\" and \"Navigator\"; lower versions use other classnames such as \"Firefox-bin\". Either choose the@@ -54,20 +64,35 @@ For detailed instructions on editing your key bindings, see "XMonad.Doc.Extending#Editing_key_bindings". -} --- | 'action' is an executable to be run via 'spawn' (of "XMonad.Core") if the Window cannot be found.+-- | If windows that satisfy the query exist, apply the supplied+-- function to them, otherwise run the action given as+-- second parameter.+ifWindows :: Query Bool -> ([Window] -> X ()) -> X () -> X ()+ifWindows qry f el = withWindowSet $ \wins -> do+  matches <- filterM (runQuery qry) $ W.allWindows wins+  case matches of+    [] -> el+    ws -> f ws++-- | The same as ifWindows, but applies a ManageHook to the first match+-- instead and discards the other matches+ifWindow :: Query Bool -> ManageHook -> X () -> X ()+ifWindow qry mh = ifWindows qry (windows . appEndo <=< runQuery mh . head)++-- | 'action' is an executable to be run via 'safeSpawnProg' (of "XMonad.Util.Run") if the Window cannot be found. --   Presumably this executable is the same one that you were looking for. runOrRaise :: String -> Query Bool -> X ()-runOrRaise action = raiseMaybe $ spawn action+runOrRaise = raiseMaybe . safeSpawnProg  -- | See 'raiseMaybe'. If the Window can't be found, quietly give up and do nothing. raise :: Query Bool -> X () raise = raiseMaybe $ return ()  {- | 'raiseMaybe' queries all Windows based on a boolean provided by the-   user. Currently, there are three such useful booleans defined in-   "XMonad.ManageHook": title, resource, className. Each one tests based pretty+   user. Currently, there are 3 such useful booleans defined in+   "XMonad.ManageHook": 'title', 'resource', 'className'. Each one tests based pretty    much as you would think. ManageHook also defines several operators, the most-   useful of which is (=?). So a useful test might be finding a Window whose+   useful of which is (=?). So a useful test might be finding a @Window@ whose    class is Firefox. Firefox 3 declares the class \"Firefox\", so you'd want to    pass in a boolean like @(className =? \"Firefox\")@. @@ -90,15 +115,15 @@   > , ((modm, xK_m), raiseMaybe (runInTerm "-title mutt" "mutt") (title =? "mutt")) -} raiseMaybe :: X () -> Query Bool -> X ()-raiseMaybe f thatUserQuery = withWindowSet $ \s -> do-    maybeResult <- filterM (runQuery thatUserQuery) (W.allWindows s)-    case maybeResult of-      []     -> f-      (x:_)  -> focus x+raiseMaybe f qry = ifWindow qry raiseHook f +-- | A manage hook that raises the window.+raiseHook :: ManageHook+raiseHook = ask >>= doF . W.focusWindow+ -- | See 'runOrRaise' and 'raiseNextMaybe'. Version that allows cycling through matches. runOrRaiseNext :: String -> Query Bool -> X ()-runOrRaiseNext action = raiseNextMaybe $ spawn action+runOrRaiseNext = raiseNextMaybe . safeSpawnProg  -- | See 'raise' and 'raiseNextMaybe'. Version that allows cycling through matches. raiseNext :: Query Bool -> X ()@@ -110,18 +135,14 @@      query the next matching window is raised. If no matches are found      the function f is executed. -}+ raiseNextMaybe :: X () -> Query Bool -> X ()-raiseNextMaybe f thatUserQuery = withWindowSet $ \s -> do-  ws <- filterM (runQuery thatUserQuery) (W.allWindows s)-  case ws of-    []    -> f-    (x:_) -> let go (Just w) | (w `elem` ws) = next w $ cycle ws-                 go _ = focus x-             in go $ W.peek s-  where-    next w (x:y:_) | x==w = focus y-    next w (_:xs)         = next w xs-    next _ _ = error "raiseNextMaybe: empty list"+raiseNextMaybe f qry = flip (ifWindows qry) f $ \ws -> do+  foc <- withWindowSet $ return . W.peek+  case foc of+    Just w | w `elem` ws -> let (_:y:_) = dropWhile (/=w) $ cycle ws -- cannot fail to match+                            in windows $ W.focusWindow y+    _ -> windows . W.focusWindow . head $ ws  -- | Given a function which gets us a String, we try to raise a window with that classname, --   or we then interpret that String as a executable name.@@ -130,7 +151,34 @@  {- | 'raiseBrowser' and 'raiseEditor' grab $BROWSER and $EDITOR respectively and they either      take you to the specified program's window, or they try to run it. This is most useful-     if your variables are simple and look like 'firefox' or 'emacs'. -}+     if your variables are simple and look like \"firefox\" or \"emacs\". -} raiseBrowser, raiseEditor :: X () raiseBrowser = raiseVar getBrowser raiseEditor  = raiseVar getEditor++{- | If the window is found the window is focused and the third argument is called+     otherwise, the first argument is called+     See 'raiseMaster' for an example. -}+raiseAndDo :: X () -> Query Bool -> (Window -> X ())-> X ()+raiseAndDo f qry after = ifWindow qry (afterRaise `mappend` raiseHook) f+    where afterRaise = ask >>= (>> idHook) . liftX . after++{- | If a window matching the second arugment is found, the window is focused and the third argument is called;+     otherwise, the first argument is called. -}+runOrRaiseAndDo :: String -> Query Bool -> (Window -> X ()) -> X ()+runOrRaiseAndDo = raiseAndDo . safeSpawnProg++{- | if the window is found the window is focused and set to master+     otherwise, the first argument is called.++     > raiseMaster (runInTerm \"-title ghci\"  \"zsh -c \'ghci\'\") (title =? \"ghci\") -}+raiseMaster :: X () -> Query Bool -> X ()+raiseMaster raisef thatUserQuery = raiseAndDo raisef thatUserQuery (\_ -> windows W.swapMaster)++{- |  If the window is found the window is focused and set to master+      otherwise, action is run.++      > runOrRaiseMaster \"firefox\" (className =? \"Firefox\"))+  -}+runOrRaiseMaster :: String -> Query Bool -> X ()+runOrRaiseMaster run query = runOrRaiseAndDo run query (\_ -> windows W.swapMaster)
+ XMonad/Actions/WindowMenu.hs view
@@ -0,0 +1,71 @@+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.WindowMenu+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- Uses "XMonad.Actions.GridSelect" to display a number of actions related to+-- window management in the center of the focused window. Actions include: Closing,+-- maximizing, minimizing and shifting the window to another workspace.+--+-- Note: For maximizing and minimizing to actually work, you will need+-- to integrate "XMonad.Layout.Maximize" and "XMonad.Layout.Minimize" into your+-- setup.  See the documentation of those modules for more information.+--+-----------------------------------------------------------------------------++module XMonad.Actions.WindowMenu (+                             -- * Usage+                             -- $usage+                             windowMenu+                              ) where++import XMonad+import qualified XMonad.StackSet as W+import XMonad.Actions.GridSelect+import XMonad.Layout.Maximize+import XMonad.Layout.Minimize+import XMonad.Util.XUtils (fi)++-- $usage+--+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- >    import XMonad.Actions.WindowMenu+--+-- Then add a keybinding, e.g.+--+-- >    , ((modm,               xK_o ), windowMenu)++windowMenu :: X ()+windowMenu = withFocused $ \w -> do+    tags <- asks (workspaces . config)+    Rectangle x y wh ht <- getSize w+    Rectangle sx sy swh sht <- gets $ screenRect . W.screenDetail . W.current . windowset+    let originFractX = (fi x - fi sx + fi wh / 2) / fi swh+        originFractY = (fi y - fi sy + fi ht / 2) / fi sht+        gsConfig = defaultGSConfig+                    { gs_originFractX = originFractX+                    , gs_originFractY = originFractY }+        actions = [ ("Cancel menu", return ())+                  , ("Close"      , kill)+                  , ("Maximize"   , sendMessage $ maximizeRestore w)+                  , ("Minimize"   , sendMessage $ MinimizeWin w)+                  ] +++                  [ ("Move to " ++ tag, windows $ W.shift tag)+                    | tag <- tags ]+    runSelectedAction gsConfig actions++getSize :: Window -> X (Rectangle)+getSize w = do+  d  <- asks display+  wa <- io $ getWindowAttributes d w+  let x = fi $ wa_x wa+      y = fi $ wa_y wa+      wh = fi $ wa_width wa+      ht = fi $ wa_height wa+  return (Rectangle x y wh ht)
XMonad/Actions/WindowNavigation.hs view
@@ -5,6 +5,8 @@ --                          Devin Mullins <me@twifkak.com> -- Maintainer  :  Devin Mullins <me@twifkak.com> -- License     :  BSD3-style (see LICENSE)+-- Stability   :  unstable+-- Portability :  unportable -- -- This is a rewrite of "XMonad.Layout.WindowNavigation".  WindowNavigation -- lets you assign keys to move up\/down\/left\/right, based on actual cartesian@@ -34,11 +36,11 @@                                        withWindowNavigationKeys,                                        WNAction(..),                                        go, swap,-                                       Direction(..)+                                       Direction2D(..)                                        ) where  import XMonad-import XMonad.Hooks.ManageDocks (Direction(..))+import XMonad.Util.Types (Direction2D(..)) import qualified XMonad.StackSet as W  import Control.Applicative ((<$>))@@ -84,15 +86,15 @@ --  - manageHook to draw window decos?  withWindowNavigation :: (KeySym, KeySym, KeySym, KeySym) -> XConfig l -> IO (XConfig l)-withWindowNavigation (u,l,d,r) conf =-    withWindowNavigationKeys [ ((modMask conf              , u), WNGo   U),-                               ((modMask conf              , l), WNGo   L),-                               ((modMask conf              , d), WNGo   D),-                               ((modMask conf              , r), WNGo   R),-                               ((modMask conf .|. shiftMask, u), WNSwap U),-                               ((modMask conf .|. shiftMask, l), WNSwap L),-                               ((modMask conf .|. shiftMask, d), WNSwap D),-                               ((modMask conf .|. shiftMask, r), WNSwap R) ]+withWindowNavigation (u,l,d,r) conf@XConfig{modMask=modm} =+    withWindowNavigationKeys [ ((modm              , u), WNGo   U),+                               ((modm              , l), WNGo   L),+                               ((modm              , d), WNGo   D),+                               ((modm              , r), WNGo   R),+                               ((modm .|. shiftMask, u), WNSwap U),+                               ((modm .|. shiftMask, l), WNSwap L),+                               ((modm .|. shiftMask, d), WNSwap D),+                               ((modm .|. shiftMask, r), WNSwap R) ]                              conf  withWindowNavigationKeys :: [((KeyMask, KeySym), WNAction)] -> XConfig l -> IO (XConfig l)@@ -104,7 +106,7 @@   where fromWNAction posRef (WNGo dir)   = go   posRef dir         fromWNAction posRef (WNSwap dir) = swap posRef dir -data WNAction = WNGo Direction | WNSwap Direction+data WNAction = WNGo Direction2D | WNSwap Direction2D  type WNState = Map WorkspaceId Point @@ -113,10 +115,10 @@ -- 2. get target windowrect -- 3. focus window -- 4. set new position-go :: IORef WNState -> Direction -> X ()+go :: IORef WNState -> Direction2D -> X () go = withTargetWindow W.focusWindow -swap :: IORef WNState -> Direction -> X ()+swap :: IORef WNState -> Direction2D -> X () swap = withTargetWindow swapWithFocused   where swapWithFocused targetWin winSet =             case W.peek winSet of@@ -128,7 +130,7 @@         mapWindows'' f (W.Stack focused up down) = W.Stack (f focused) (map f up) (map f down)         swapWin win1 win2 win = if win == win1 then win2 else if win == win2 then win1 else win -withTargetWindow :: (Window -> WindowSet -> WindowSet) -> IORef WNState -> Direction -> X ()+withTargetWindow :: (Window -> WindowSet -> WindowSet) -> IORef WNState -> Direction2D -> X () withTargetWindow adj posRef dir = fromCurrentPoint posRef $ \win pos -> do     targets <- filter ((/= win) . fst) <$> navigableTargets pos dir     whenJust (listToMaybe targets) $ \(targetWin, targetRect) -> do@@ -153,7 +155,7 @@     currentWindow <- gets (W.peek . windowset)     currentRect <- maybe (Rectangle 0 0 0 0) snd <$> windowRect (fromMaybe root currentWindow) -    wsid <- gets (W.tag . W.workspace . W.current . windowset)+    wsid <- gets (W.currentTag . windowset)     mp <- M.lookup wsid <$> io (readIORef posRef)      return $ maybe (middleOf currentRect) (`inside` currentRect) mp@@ -162,7 +164,7 @@  setPosition :: IORef WNState -> Point -> Rectangle -> X () setPosition posRef oldPos newRect = do-    wsid <- gets (W.tag . W.workspace . W.current . windowset)+    wsid <- gets (W.currentTag . windowset)     io $ modifyIORef posRef $ M.insert wsid (oldPos `inside` newRect)  inside :: Point -> Rectangle -> Point@@ -175,12 +177,12 @@ midPoint :: Position -> Dimension -> Position midPoint pos dim = pos + fromIntegral dim `div` 2 -navigableTargets :: Point -> Direction -> X [(Window, Rectangle)]+navigableTargets :: Point -> Direction2D -> X [(Window, Rectangle)] navigableTargets point dir = navigable dir point <$> windowRects  -- Filters and sorts the windows in terms of what is closest from the Point in--- the Direction.-navigable :: Direction -> Point -> [(Window, Rectangle)] -> [(Window, Rectangle)]+-- the Direction2D.+navigable :: Direction2D -> Point -> [(Window, Rectangle)] -> [(Window, Rectangle)] navigable d pt = sortby d . filter (inr d pt . snd)  -- Produces a list of normal-state windows, on any screen. Rectangles are@@ -197,7 +199,7 @@  -- Modified from droundy's implementation of WindowNavigation: -inr :: Direction -> Point -> Rectangle -> Bool+inr :: Direction2D -> Point -> Rectangle -> Bool inr D (Point px py) (Rectangle rx ry w h) = px >= rx && px < rx + fromIntegral w &&                                                         py < ry + fromIntegral h inr U (Point px py) (Rectangle rx ry w _) = px >= rx && px < rx + fromIntegral w &&@@ -207,7 +209,7 @@ inr L (Point px py) (Rectangle rx ry w h) =             px > rx + fromIntegral w &&                                             py >= ry && py < ry + fromIntegral h -sortby :: Direction -> [(a,Rectangle)] -> [(a,Rectangle)]+sortby :: Direction2D -> [(a,Rectangle)] -> [(a,Rectangle)] sortby D = sortBy $ comparing (rect_y . snd) sortby R = sortBy $ comparing (rect_x . snd) sortby U = reverse . sortby D
+ XMonad/Actions/WithAll.hs view
@@ -0,0 +1,54 @@+-----------------------------------------------------------------------------+-- |+-- Module       : XMonad.Actions.WithAll+-- License      : BSD3-style (see LICENSE)+-- Stability    : unstable+-- Portability  : unportable+--+-- Provides functions for performing a given action on all windows of+-- the current workspace.+-----------------------------------------------------------------------------++module XMonad.Actions.WithAll (+    -- * Usage+    -- $usage+    sinkAll, withAll,+    withAll', killAll) where++import Data.Foldable hiding (foldr)++import XMonad+import XMonad.Core+import XMonad.Operations+import XMonad.StackSet++-- $usage+--+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Actions.WithAll+--+-- then add a keybinding; for example:+--+--     , ((modm .|. shiftMask, xK_t), sinkAll)+--+-- For detailed instructions on editing your key bindings, see+-- "XMonad.Doc.Extending#Editing_key_bindings".++-- | Un-float all floating windows on the current workspace.+sinkAll :: X ()+sinkAll = withAll' sink++-- | Apply a function to all windows on the current workspace.+withAll' :: (Window -> WindowSet -> WindowSet) -> X ()+withAll' f = windows $ \ws -> let all' = integrate' . stack . workspace . current $ ws+                              in foldr f ws all'++-- | Execute an 'X' action for each window on the current workspace.+withAll :: (Window -> X ()) -> X()+withAll f = withWindowSet $ \ws -> let all' = integrate' . stack . workspace . current $ ws+                                   in forM_ all' f++-- | Kill all the windows on the current workspace.+killAll :: X()+killAll = withAll killWindow
+ XMonad/Actions/WorkspaceCursors.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module       : XMonad.Actions.WorkspaceCursors+-- Copyright    : (c) 2009 Adam Vogt <vogt.adam@gmail.com>+-- License      : BSD+--+-- Maintainer   : Adam Vogt+-- Stability    : unstable+-- Portability  : unportable+--+-- Like "XMonad.Actions.Plane" for an arbitrary number of dimensions.+-----------------------------------------------------------------------------++module XMonad.Actions.WorkspaceCursors+    (+    -- * Usage+    -- $usage++     focusDepth+    ,makeCursors+    ,toList+    ,workspaceCursors++    ,WorkspaceCursors+    ,getFocus++    -- * Modifying the focus+    ,modifyLayer+    ,modifyLayer'+    ,shiftModifyLayer,shiftLayer++    -- * Functions to pass to 'modifyLayer'+    ,focusNth'+    ,noWrapUp,noWrapDown++    -- * Todo+    -- $todo+    ) where++import qualified XMonad.StackSet as W++import XMonad.Actions.FocusNth(focusNth')+import XMonad.Layout.LayoutModifier(ModifiedLayout(..),+                                    LayoutModifier(handleMess, redoLayout))+import XMonad(Typeable, Message, WorkspaceId, X, XState(windowset),+              fromMessage, sendMessage, windows, gets)+import Control.Monad((<=<), guard, liftM, liftM2, when)+import Control.Applicative((<$>))+import Data.Foldable(Foldable(foldMap), toList)+import Data.Maybe(fromJust, listToMaybe)+import Data.Monoid(Monoid(mappend, mconcat))+import Data.Traversable(sequenceA)++-- $usage+--+-- Here is an example config:+--+-- > import XMonad+-- > import XMonad.Actions.WorkspaceCursors+-- > import XMonad.Hooks.DynamicLog+-- > import XMonad.Util.EZConfig+-- > import qualified XMonad.StackSet as W+-- >+-- > main = do+-- >     x <- xmobar conf+-- >     xmonad x+-- >+-- > conf = additionalKeysP defaultConfig+-- >        { layoutHook = workspaceCursors myCursors $ layoutHook defaultConfig+-- >        , workspaces = toList myCursors } $+-- >        [("M-"++shift++control++[k], f direction depth)+-- >          | (f,shift) <- zip [modifyLayer,shiftModifyLayer] ["","S-"]+-- >          , (direction,control) <- zip [W.focusUp',W.focusDown'] ["C-",""]+-- >          , (depth,k) <- zip (reverse [1..focusDepth myCursors]) "asdf"]+-- >        ++ moreKeybindings+-- >+-- > moreKeybindings = []+-- >+-- > myCursors = makeCursors $ map (map (\x -> [x])) [ "1234", "abc", "xyz"]+-- > -- myCursors = makeCursors [["wsA","wsB","wsC"],["-alpha-","-beta-","-gamma-"],["x","y"]]+++-- $todo+--+-- * Find and document how to raise the allowable length of arguments:+--   restoring xmonad's state results in: @xmonad: executeFile: resource+--   exhausted (Argument list too long)@ when you specify more than about 50+--   workspaces. Or change it such that workspaces are created when you try to+--   view it.+--+-- * Function for pretty printing for DynamicLog that groups workspaces by+-- common prefixes+--+-- * Examples of adding workspaces to the cursors, having them appear multiple+--   times for being able to show jumping to some n'th multiple workspace++-- | makeCursors requires a nonempty string, and each sublist must be nonempty+makeCursors ::  [[String]] -> Cursors String+makeCursors [] = error "Workspace Cursors cannot be empty"+makeCursors a = concat . reverse <$> foldl addDim x xs+    where x = end $ map return $ head a+          xs = map (map return) $ tail a+          -- this could probably be simplified, but this true:+          -- toList . makeCursors == map (concat . reverse) . sequence . reverse . map (map (:[]))+          -- the strange order is used because it makes the regular M-1..9+          -- bindings change the prefixes first++addDim ::  (Monoid a) => Cursors a -> [a] -> Cursors a+addDim prev prefixes = Cons . fromJust . W.differentiate+            $ map ((<$> prev) . mappend) prefixes++end :: [a] -> Cursors a+end = Cons . fromJust . W.differentiate . map End++data Cursors a+    = Cons (W.Stack (Cursors a))+    | End a deriving (Eq,Show,Read,Typeable)++instance Foldable Cursors where+    foldMap f (End x) = f x+    foldMap f (Cons (W.Stack x y z)) = foldMap f x `mappend` mconcat (map (foldMap f) $ reverse y ++ z)++instance Functor Cursors where+    fmap f (End a) = End $ f a+    fmap f (Cons (W.Stack x y z)) = Cons $ W.Stack (fmap f x) (fmap (fmap f) y) (fmap (fmap f) z)++changeFocus ::  (Cursors t -> Bool) -> Cursors t -> [Cursors t]+changeFocus p (Cons x) = do+    choose <- chFocus p x+    foc    <- changeFocus p $ W.focus choose+    return . Cons $ choose { W.focus = foc }+changeFocus p x = guard (p x) >> return x++chFocus :: (a -> Bool) -> W.Stack a -> [W.Stack a]+chFocus p st = filter (p . W.focus) $ zipWith const (iterate W.focusDown' st) (W.integrate st)++getFocus ::  Cursors b -> b+getFocus (Cons x) = getFocus $ W.focus x+getFocus (End x) = x++-- This could be made more efficient, if the fact that the suffixes are grouped+focusTo ::  (Eq t) => t -> Cursors t -> Maybe (Cursors t)+focusTo x = listToMaybe . filter ((x==) . getFocus) . changeFocus (const True)++-- | non-wrapping version of 'W.focusUp''+noWrapUp ::  W.Stack t -> W.Stack t+noWrapUp (W.Stack t (l:ls) rs) = W.Stack l ls (t:rs)+noWrapUp x@(W.Stack _ []   _ ) = x++-- | non-wrapping version of 'W.focusDown''+noWrapDown ::  W.Stack t -> W.Stack t+noWrapDown = reverseStack . noWrapUp . reverseStack+    where reverseStack (W.Stack t ls rs) = W.Stack t rs ls++focusDepth ::  Cursors t -> Int+focusDepth (Cons x) = 1 + focusDepth (W.focus x)+focusDepth (End  _) = 0++descend :: Monad m =>(W.Stack (Cursors a) -> m (W.Stack (Cursors a)))-> Int-> Cursors a-> m (Cursors a)+descend f 1 (Cons x) = Cons `liftM` f x+descend f n (Cons x) | n > 1 = liftM Cons $ descend f (pred n) `onFocus` x+descend _ _ x = return x++onFocus :: (Monad m) => (a1 -> m a1) -> W.Stack a1 -> m (W.Stack a1)+onFocus f st = (\x -> st { W.focus = x}) `liftM` f (W.focus st)++-- | @modifyLayer@ is used to change the focus at a given depth+modifyLayer :: (W.Stack (Cursors String) -> W.Stack (Cursors String)) -> Int -> X ()+modifyLayer f depth = modifyCursors (descend (return . f) depth)++-- | @shiftModifyLayer@ is the same as 'modifyLayer', but also shifts the+-- currently focused window to the new workspace+shiftModifyLayer :: (W.Stack (Cursors String) -> W.Stack (Cursors WorkspaceId))-> Int-> X ()+shiftModifyLayer f = modifyLayer' $ \st -> do+    let st' = f st+    windows $ W.shift $ getFocus (Cons st')+    return st'++-- | @shiftLayer@ is the same as 'shiftModifyLayer', but the focus remains on+-- the current workspace.+shiftLayer :: (W.Stack (Cursors String) -> W.Stack (Cursors WorkspaceId))-> Int-> X ()+shiftLayer f = modifyLayer' $ \st -> do+    windows $ W.shift $ getFocus $ Cons $ f st+    return st++-- | example usages are 'shiftLayer' and 'shiftModifyLayer'+modifyLayer' :: (W.Stack (Cursors String) -> X (W.Stack (Cursors String))) -> Int -> X ()+modifyLayer' f depth = modifyCursors (descend f depth)++modifyCursors ::  (Cursors String -> X (Cursors String)) -> X ()+modifyCursors = sendMessage . ChangeCursors . (liftM2 (>>) updateXMD return <=<)++data WorkspaceCursors a = WorkspaceCursors (Cursors String)+    deriving (Typeable,Read,Show)++-- | The state is stored in the 'WorkspaceCursors' layout modifier. Put this as+-- your outermost modifier, unless you want different cursors at different+-- times (using "XMonad.Layout.MultiToggle")+workspaceCursors :: Cursors String -> l a -> ModifiedLayout WorkspaceCursors l a+workspaceCursors = ModifiedLayout . WorkspaceCursors++data ChangeCursors = ChangeCursors { unWrap :: Cursors String -> X (Cursors String) }+    deriving (Typeable)++instance Message ChangeCursors++updateXMD ::  Cursors WorkspaceId -> X ()+updateXMD cs = do+    changed <- gets $ (getFocus cs /=) . W.currentTag . windowset+    when changed $ windows $ W.greedyView $ getFocus cs++instance LayoutModifier WorkspaceCursors a where+    redoLayout (WorkspaceCursors cs) _ _ arrs = do+        cws <- gets $ W.currentTag . windowset+        return (arrs,WorkspaceCursors <$> focusTo cws cs)++    handleMess (WorkspaceCursors cs) m =+        sequenceA $ fmap WorkspaceCursors . ($ cs) . unWrap <$> fromMessage m
XMonad/Config/Arossato.hs view
@@ -90,8 +90,7 @@                                 map show [7 .. 9 :: Int]          , logHook            = myDynLog xmobar -- REMOVE this line if you do not have xmobar installed!          , manageHook         = newManageHook-         , layoutHook         = eventHook ServerMode $-                                avoidStruts $+         , layoutHook         = avoidStruts $                                 decorated        |||                                 noBorders mytabs |||                                 otherLays@@ -99,6 +98,7 @@          , normalBorderColor  = "white"          , focusedBorderColor = "black"          , keys               = newKeys+         , handleEventHook    = serverModeEventHook          , focusFollowsMouse  = False          }     where
+ XMonad/Config/Azerty.hs view
@@ -0,0 +1,48 @@+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}++-----------------------------------------------------------------------------+-- |+-- Module       : XMonad.Config.Azerty+-- Copyright    : (c) Devin Mullins <me@twifkak.com>+-- License      : BSD+--+-- Maintainer   : Devin Mullins <me@twifkak.com>+-- Stability    : stable+-- Portability  : unportable+--+-- This module fixes some of the keybindings for the francophone among you who+-- use an AZERTY keyboard layout. Config stolen from TeXitoi's config on the+-- wiki.++module XMonad.Config.Azerty (+    -- * Usage+    -- $usage+    azertyConfig, azertyKeys+    ) where++import XMonad+import qualified XMonad.StackSet as W++import qualified Data.Map as M++-- $usage+-- To use this module, start with the following @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad+-- > import XMonad.Config.Azerty+-- >+-- > main = xmonad azertyConfig+--+-- If you prefer, an azertyKeys function is provided which you can use as so:+--+-- > import qualified Data.Map as M+-- > main = xmonad someConfig { keys = \c -> azertyKeys c `M.union` keys someConfig c }++azertyConfig = defaultConfig { keys = \c -> azertyKeys c `M.union` keys defaultConfig c }++azertyKeys conf@(XConfig {modMask = modm}) = M.fromList $+    [((modm, xK_semicolon), sendMessage (IncMasterN (-1)))]+    +++    [((m .|. modm, k), windows $ f i)+        | (i, k) <- zip (workspaces conf) [0x26,0xe9,0x22,0x27,0x28,0x2d,0xe8,0x5f,0xe7,0xe0],+          (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
XMonad/Config/Desktop.hs view
@@ -7,31 +7,173 @@ -- License      : BSD -- -- Maintainer   : Spencer Janssen <spencerjanssen@gmail.com>+-- Stability    :  unstable+-- Portability  :  unportable -- -- This module provides a config suitable for use with a desktop -- environment such as KDE or GNOME.-+----------------------------------------------------------------------------- module XMonad.Config.Desktop (++    -- | Several basic integration settings are common to all of xmonad's+    -- desktop integration configurations. The specific desktop environment+    -- (DE) modules like "XMonad.Config.Gnome" use this module's+    -- @desktopConfig@ to set up basic communication between xmonad and+    -- the DE via a subset of the Extended Window Manager Hints (EWMH)+    -- specification. Extra xmonad settings unique to specific DE's are+    -- added by overriding or modifying @desktopConfig@ fields in the+    -- same way that @defaultConfig@ is customized in @~\/.xmonad/xmonad.hs@.+    --+    -- For more information about EWMH see:+    --+    -- <http://standards.freedesktop.org/wm-spec/wm-spec-latest.html>+    --+    -- See also: "XMonad.Hooks.EwmhDesktops", "XMonad.Hooks.ManageDocks",+    -- "XMonad.Util.EZConfig".+     -- * Usage-    -- -- $usage+    -- $usage+     desktopConfig,++    -- * Customizing a desktop config+    -- $customizing++    -- ** Modifying layouts, manageHook, or key bindings+    -- $layouts     desktopLayoutModifiers++    -- ** Modifying the logHook+    -- $logHook++    -- ** Modifying the handleEventHook+    -- $eventHook++    -- ** Modifying the startupHook+    -- $startupHook     ) where  import XMonad import XMonad.Config (defaultConfig) import XMonad.Hooks.ManageDocks import XMonad.Hooks.EwmhDesktops+import XMonad.Util.Cursor  import qualified Data.Map as M -desktopConfig = defaultConfig-    { logHook    = ewmhDesktopsLogHook-    , layoutHook = desktopLayoutModifiers $ layoutHook defaultConfig-    , manageHook = manageHook defaultConfig <+> manageDocks-    , keys       = \c -> desktopKeys c `M.union` keys defaultConfig c }+-- $usage+-- While this document describes how to configure xmonad, you also need+-- to set up your Desktop Environment (DE) and display manager to use+-- xmonad as its window manager. For DE and distro specific tips on+-- how to do so, see the xmonad wiki:+--+-- <http://haskell.org/haskellwiki/Xmonad>+--+-- To configure xmonad for use with a DE or with DE tools like panels+-- and pagers, in place of @defaultConfig@ in your @~\/.xmonad/xmonad.hs@,+-- use @desktopConfig@ or one of the other desktop configs from the+-- @XMonad.Config@ namespace. The following setup and customization examples+-- work the same way for the other desktop configs as for @desktopConfig@.+-- If you are using a specific DE config, import its module instead, and+-- use its config in place of @desktopConfig@ in the following examples.+--+-- > import XMonad+-- > import XMonad.Config.Desktop+-- >+-- > main = xmonad desktopConfig+--+-- @desktopConfig@ is an 'XConfig' that configures xmonad to+-- ignore and leave room for dock type windows like panels and trays, adds+-- the default key binding to toggle panel visibility, and activates basic+-- EWMH support. It also sets a prettier root window mouse pointer. +-- $customizing+-- To customize a desktop config, modify its fields as is illustrated with+-- @defaultConfig@ in the \"Extending xmonad\" section of "XMonad.Doc.Extending".++-- $layouts+-- See also "XMonad.Util.EZConfig" for more options for modifying key bindings.+-- To add to layouts, manageHook or key bindings use something like the following+-- to combine your modifications with the desktop config settings:+--+-- > import XMonad+-- > import XMonad.Config.Desktop+-- > import XMonad.Layout.Tabbed+-- > import XMonad.Util.EZConfig (additionalKeys)+-- >+-- > main =+-- >   xmonad $ desktopConfig {+-- >     -- add manage hooks while still ignoring panels and using default manageHooks+-- >       manageHook = myManageHook <+> manageHook desktopConfig+-- >+-- >     -- add a fullscreen tabbed layout that does not avoid covering+-- >     -- up desktop panels before the desktop layouts+-- >     , layoutHook = simpleTabbed ||| layoutHook desktopConfig+-- >     }+-- >     -- add a screenshot key to the default desktop bindings+-- >     `additionalKeys` [ ((mod4Mask, xK_F8), spawn "scrot") ]+--+-- To replace the desktop layouts with your own choices, but still+-- allow toggling panel visibility, use 'desktopLayoutModifiers' to+-- modify your layouts:+--+-- >  , layoutHook = desktopLayoutModifiers $ simpleTabbed ||| Tall 1 0.03 0.5+--+-- @desktopLayoutModifiers@ modifies a layout to avoid covering docks, panels,+-- etc. that set the @_NET_WM_STRUT_PARTIAL@ property.+-- See also "XMonad.Hooks.ManageDocks".++-- $logHook+-- To add to the logHook while still sending workspace and window information+-- to DE apps use something like:+--+-- >  , logHook = myLogHook >> logHook desktopConfig+--+-- Or for more elaborate logHooks you can use @do@:+--+-- >  , logHook = do+-- >        dynamicLogWithPP xmobarPP+-- >        updatePointer (Relative 0.9 0.9)+-- >        logHook desktopConfig+--++-- $eventHook+-- To customize xmonad's event handling while still having it respond+-- to EWMH events from pagers, task bars, etc. add to your imports:+--+-- > import Data.Monoid+--+-- and use 'Data.Monoid.mappend' to combine event hooks (right to left application like @\<+\>@)+--+-- >  , handleEventHook = mappend myEventHooks (handleEventHook desktopConfig)+--+-- or 'Data.Monoid.mconcat' (like @composeAll@)+--+-- >  , handleEventHook = mconcat+-- >        [ myMouseHandler+-- >        , myMessageHandler+-- >        , handleEventHook desktopConfig ]+--++-- $startupHook+-- To run the desktop startupHook, plus add further actions to be run each+-- time xmonad starts or restarts, use '>>' to combine actions as in the+-- logHook example, or something like:+--+-- >  , startupHook = do+-- >        startupHook desktopConfig+-- >        spawn "xmonad-restart.sh"+-- >        adjustEventInput+--++desktopConfig = ewmh defaultConfig+    { startupHook     = setDefaultCursor xC_left_ptr+    , layoutHook      = desktopLayoutModifiers $ layoutHook defaultConfig+    , manageHook      = manageHook defaultConfig <+> manageDocks+    , keys            = \c -> desktopKeys c `M.union` keys defaultConfig c }+ desktopKeys (XConfig {modMask = modm}) = M.fromList $     [ ((modm, xK_b), sendMessage ToggleStruts) ] -desktopLayoutModifiers layout = avoidStruts $ ewmhDesktopsLayout layout+desktopLayoutModifiers layout = avoidStruts layout+
XMonad/Config/Droundy.hs view
@@ -22,7 +22,7 @@ import XMonad.Layout.Named ( named ) import XMonad.Layout.LayoutCombinators import XMonad.Layout.Square ( Square(Square) )-import XMonad.Layout.WindowNavigation ( Navigate(Move,Swap,Go), Direction(U,D,R,L),+import XMonad.Layout.WindowNavigation ( Navigate(Move,Swap,Go), Direction2D(U,D,R,L),                                         windowNavigation ) import XMonad.Layout.BoringWindows ( boringWindows, markBoring, clearBoring,                                      focusUp, focusDown )@@ -40,11 +40,10 @@ import XMonad.Actions.DynamicWorkspaces ( withNthWorkspace, withWorkspace,                                           selectWorkspace, renameWorkspace, removeWorkspace ) import XMonad.Actions.CycleWS ( moveTo, WSType( HiddenNonEmptyWS ),-                                WSDirection( Prev, Next) )+                                Direction1D( Prev, Next) )  import XMonad.Hooks.ManageDocks ( avoidStruts, manageDocks )-import XMonad.Hooks.EwmhDesktops ( ewmhDesktopsLogHook,-                                   ewmhDesktopsLayout )+import XMonad.Hooks.EwmhDesktops ( ewmh )  myXPConfig :: XPConfig myXPConfig = defaultXPConfig {font="-*-lucida-medium-r-*-*-14-*-*-*-*-*-*-*"@@ -95,7 +94,7 @@     , ((modMask x .|. controlMask .|. shiftMask, xK_Left), sendMessage $ Move L)     , ((modMask x .|. controlMask .|. shiftMask, xK_Up), sendMessage $ Move U)     , ((modMask x .|. controlMask .|. shiftMask, xK_Down), sendMessage $ Move D)- +     , ((0, xK_F2  ), spawn "gnome-terminal") -- %! Launch gnome-terminal     , ((0, xK_F3  ), shellPrompt myXPConfig) -- %! Launch program     , ((0, xK_F11   ), spawn "ksnapshot") -- %! Take snapshot@@ -112,16 +111,16 @@     , ((modMask x, xK_space), sendMessage Toggle)      ]- +     ++     zip (zip (repeat $ modMask x) [xK_F1..xK_F12]) (map (withNthWorkspace W.greedyView) [0..])     ++     zip (zip (repeat (modMask x .|. shiftMask)) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..]) -config = defaultConfig+config = ewmh defaultConfig          { borderWidth = 1 -- Width of the window border in pixels.          , XMonad.workspaces = ["mutt","iceweasel"]-         , layoutHook = ewmhDesktopsLayout $ showWName $ workspaceDir "~" $+         , layoutHook = showWName $ workspaceDir "~" $                         boringWindows $ smartBorders $ windowNavigation $                         maximizeVertical $ toggleLayouts Full $ avoidStruts $                         named "tabbed" mytab |||@@ -131,7 +130,6 @@                                                 ****//* combineTwo Square mytab mytab) --   |||                         --mosaic 0.25 0.5          , manageHook = manageHook defaultConfig <+> manageDocks -- add panel-handling-         , logHook = ewmhDesktopsLogHook -- actually, no logging here, just other stuff          , terminal = "xterm" -- The preferred terminal program.          , normalBorderColor = "#222222" -- Border color for unfocused windows.          , focusedBorderColor = "#00ff00" -- Border color for focused windows.@@ -142,12 +140,12 @@ mytab = tabbed CustomShrink defaultTheme  instance Shrinker CustomShrink where-    shrinkIt shr s | Just s' <- dropFromHead " " s = shrinkIt shr s' -    shrinkIt shr s | Just s' <- dropFromTail " " s = shrinkIt shr s' -    shrinkIt shr s | Just s' <- dropFromTail "- Iceweasel" s = shrinkIt shr s' -    shrinkIt shr s | Just s' <- dropFromTail "- KPDF" s = shrinkIt shr s' -    shrinkIt shr s | Just s' <- dropFromHead "file://" s = shrinkIt shr s' -    shrinkIt shr s | Just s' <- dropFromHead "http://" s = shrinkIt shr s' +    shrinkIt shr s | Just s' <- dropFromHead " " s = shrinkIt shr s'+    shrinkIt shr s | Just s' <- dropFromTail " " s = shrinkIt shr s'+    shrinkIt shr s | Just s' <- dropFromTail "- Iceweasel" s = shrinkIt shr s'+    shrinkIt shr s | Just s' <- dropFromTail "- KPDF" s = shrinkIt shr s'+    shrinkIt shr s | Just s' <- dropFromHead "file://" s = shrinkIt shr s'+    shrinkIt shr s | Just s' <- dropFromHead "http://" s = shrinkIt shr s'     shrinkIt _ s | n > 9 = s : map cut [2..(halfn-3)] ++ shrinkIt shrinkText s                  where n = length s                        halfn = n `div` 2@@ -176,7 +174,7 @@                       s { windowset = until ((Just w ==) . W.peek)                                       W.focusUp $ windowset s }                   | otherwise =-                      let t = W.tag $ W.workspace $ W.current $ windowset s+                      let t = W.currentTag $ windowset s                       in s { windowset = until ((Just w ==) . W.peek)                              W.focusUp $ copyWindow w t $ windowset s }               has _ Nothing         = False
XMonad/Config/Gnome.hs view
@@ -7,22 +7,28 @@ -- License      : BSD -- -- Maintainer   : Spencer Janssen <spencerjanssen@gmail.com>+-- Stability    :  unstable+-- Portability  :  unportable -- -- This module provides a config suitable for use with the GNOME desktop -- environment.  module XMonad.Config.Gnome (     -- * Usage-    -- -- $usage+    -- $usage     gnomeConfig,-    gnomeRun+    gnomeRun,+    gnomeRegister     ) where  import XMonad import XMonad.Config.Desktop+import XMonad.Util.Run (safeSpawn)  import qualified Data.Map as M +import System.Environment (getEnvironment)+ -- $usage -- To use this module, start with the following @~\/.xmonad\/xmonad.hs@: --@@ -30,11 +36,13 @@ -- > import XMonad.Config.Gnome -- > -- > main = xmonad gnomeConfig--- +--+-- For examples of how to further customize @gnomeConfig@ see "XMonad.Config.Desktop".  gnomeConfig = desktopConfig     { terminal = "gnome-terminal"-    , keys     = \c -> gnomeKeys c `M.union` keys desktopConfig c }+    , keys     = \c -> gnomeKeys c `M.union` keys desktopConfig c+    , startupHook = gnomeRegister >> startupHook desktopConfig }  gnomeKeys (XConfig {modMask = modm}) = M.fromList $     [ ((modm, xK_p), gnomeRun)@@ -53,3 +61,22 @@         setClientMessageEvent e rw gnome_panel 32 panel_run 0         sendEvent dpy rw False structureNotifyMask e         sync dpy False++-- | Register xmonad with gnome. 'dbus-send' must be in the $PATH with which+-- xmonad is started.+--+-- This action reduces a delay on startup only only if you have configured+-- gnome-session>=2.26: to start xmonad with a command as such:+--+-- > gconftool-2 -s /desktop/gnome/session/required_components/windowmanager xmonad --type string+gnomeRegister :: MonadIO m => m ()+gnomeRegister = io $ do+    x <- lookup "DESKTOP_AUTOSTART_ID" `fmap` getEnvironment+    whenJust x $ \sessionId -> safeSpawn "dbus-send"+            ["--session"+            ,"--print-reply=string"+            ,"--dest=org.gnome.SessionManager"+            ,"/org/gnome/SessionManager"+            ,"org.gnome.SessionManager.RegisterClient"+            ,"string:xmonad"+            ,"string:"++sessionId]
XMonad/Config/Kde.hs view
@@ -7,14 +7,17 @@ -- License      : BSD -- -- Maintainer   : Spencer Janssen <spencerjanssen@gmail.com>+-- Stability    :  unstable+-- Portability  :  unportable -- -- This module provides a config suitable for use with the KDE desktop -- environment.  module XMonad.Config.Kde (     -- * Usage-    -- -- $usage-    kdeConfig+    -- $usage+    kdeConfig,+    kde4Config     ) where  import XMonad@@ -29,13 +32,26 @@ -- > import XMonad.Config.Kde -- > -- > main = xmonad kdeConfig--- +--+-- For KDE 4, replace 'kdeConfig' with 'kde4Config'+--+-- For examples of how to further customize @kdeConfig@ see "XMonad.Config.Desktop". + kdeConfig = desktopConfig     { terminal = "konsole"     , keys     = \c -> kdeKeys c `M.union` keys desktopConfig c } +kde4Config = desktopConfig+    { terminal = "konsole"+    , keys     = \c -> kde4Keys c `M.union` keys desktopConfig c }+ kdeKeys (XConfig {modMask = modm}) = M.fromList $     [ ((modm,               xK_p), spawn "dcop kdesktop default popupExecuteCommand")     , ((modm .|. shiftMask, xK_q), spawn "dcop kdesktop default logout")+    ]++kde4Keys (XConfig {modMask = modm}) = M.fromList $+    [ ((modm,               xK_p), spawn "krunner")+    , ((modm .|. shiftMask, xK_q), spawn "dbus-send --print-reply --dest=org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout int32:1 int32:0 int32:1")     ]
− XMonad/Config/PlainConfig.hs
@@ -1,528 +0,0 @@-{-# LANGUAGE -  FlexibleInstances, -  FlexibleContexts, -  MultiParamTypeClasses, -  ExistentialQuantification -  #-}------------------------------------------------------------------------------ |--- Module      :  XMonad.Config.PlainConfig--- Copyright   :  Braden Shepherdson <Braden.Shepherdson@gmail.com>--- License     :  BSD3--- --- Maintainer  :  Braden Shepherdson <Braden.Shepherdson@gmail.com>------ Proof-of-concept (but usable) plain-text configuration file--- parser, for use instead of xmonad.hs. Does not require recompilation,--- allowing xmonad to be free of the GHC dependency.--------------------------------------------------------------------------------module XMonad.Config.PlainConfig-    (-     -- * Introduction-     -- $usage--     -- * Supported Layouts-     -- $layouts--     -- * Support Key Bindings-     -- $keys--     -- * Other Notes-     -- $notes--     -- * Example Config File-     -- $example--     plainConfig ,readConfig, checkConfig-    )-where---import XMonad-import System.Exit--import qualified XMonad.StackSet as W-import qualified Data.Map        as M-import Data.List-import Data.Maybe (isJust,fromJust)-import Data.Char (isSpace)-----import Control.Monad-import Control.Monad.Error-import Control.Monad.Identity--import Control.Arrow ((&&&))--import Text.ParserCombinators.ReadP--import System.IO-import Control.Exception (bracket)--import XMonad.Util.EZConfig (mkKeymap)------ $usage--- The @xmonad.hs@ file is very minimal when used with PlainConfig.--- It typically contains only the following:------ > module Main where--- > import XMonad--- > import XMonad.Config.PlainConfig (plainConfig)--- > main = plainConfig------ The 'plainConfig' function parses @~\/.xmonad\/xmonad.conf@, --- the format of which is described below.----- $layouts--- Only 'Tall', 'Wide' and 'Full' are supported at present.------ $keys--- --- Key bindings are specified as a pair of an arbitrary EZConfig and --- one of the following:------ @   Name                     Haskell equivalent                                          Default binding(s)@--- --- * @spawn \<cmd\>           spawn \"\<cmd\>\"                                               none@--- --- * @kill                  kill                                                        M-S-c@--- --- * @nextLayout            sendMessage NextLayout                                      M-\<Space\>@--- --- * @refresh               refresh                                                     M-S-\<Space\>@--- --- * @focusDown             windows W.focusDown                                         M-\<Tab\>, M-j@--- --- * @focusUp               windows W.focusUp                                           M-k@--- --- * @focusMaster           windows W.focusMaster                                       M-m@--- --- * @swapDown              windows W.swapDown                                          M-S-j@--- --- * @swapUp                windows W.swapUp                                            M-S-k@--- --- * @swapMaster            windows W.swapMaster                                        M-\<Return\>@--- --- * @shrink                sendMessage Shrink                                          M-h@--- --- * @expand                sendMessage Expand                                          M-l@--- --- * @sink                  withFocused $ windows . W.sink                              M-t@--- --- * @incMaster             sendMessage (IncMasterN 1)                                  M-,@--- --- * @decMaster             sendMessage (IncMasterN (-1))                               M-.@--- --- * @quit                  io $ exitWith ExitSuccess                                   M-S-q@--- --- * @restart               broadcastMessageReleaseResources >> restart \"xmonad\" True   M-q@--- ----- $notes--- Submaps are allowed.--- These settings override the defaults. Changes made here will be used over--- the default bindings for those keys.----- $example--- An example @~\/.xmonad\/xmonad.conf@ file follows:------ @modMask       = 3@------ @numlockMask   = 2@------ @borderWidth   = 1@------ @normalBorderColor    	=   #dddddd@------ @focusedBorderColor      =   #00ff00@------ @terminal=urxvt@------ @workspaces=[\"1: IRC\",\"2: Web\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]@------ @focusFollowsMouse=True@------ @layouts=[\"Tall\",\"Full\",\"Wide\"]@------ @key=(\"M-x t\", \"spawn xmessage Test\")@------ @manageHook=(ClassName \"MPlayer\"       , \"float\"  )@------ @manageHook=(ClassName \"Gimp\"          , \"float\"  )@------ @manageHook=(Resource  \"desktop_window\", \"ignore\" )@------ @manageHook=(Resource  \"kdesktop\"      , \"ignore\" )@------ @manageHook=(Resource  \"gnome-panel\"   , \"ignore\" )@--------------------------------------------------------------------------------- Several functions for parsing the key-value file. --------------------------------------------------------------------------parseKVBy :: Char -> ReadP (String,String)-parseKVBy sep = do-  skipSpaces -  k <- munch1 (\x -> x /= ' ' && x /= sep) -  skipSpaces-  char kvSep-  skipSpaces-  v <- munch1 (\x -> x /= ' ') --or EOS -  return (k,v)--parseKVVBy :: Char -> ReadP (String,String)-parseKVVBy sep = do-  skipSpaces -  k <- munch1 (\x -> x /= ' ' && x /= sep) -  skipSpaces-  char kvSep-  skipSpaces-  v <- munch1 (const True) -- until EOS-  return (k,v)---kvSep :: Char-kvSep = '='--parseKV, parseKVV :: ReadP (String,String)-parseKV  = parseKVBy  kvSep-parseKVV = parseKVVBy kvSep----readKV :: String -> Integer -> RC (String,String)-readKV s ln = case readP_to_S parseKV s of-                [((k,v),"")] -> return (k,v) --single, correct parse-                []           -> throwError [(ln,"No parse")]-                _           -> do-                  case readP_to_S parseKVV s of-                    [((k,v),"")] -> return (k,v) --single, correct parse-                    []           -> throwError [(ln,"No parse")]-                    xs           -> throwError [(ln,"Ambiguous parse: "-                                                 ++ show xs)]----isComment :: String -> Bool-isComment = not . null . readP_to_S parseComment -  where parseComment = skipSpaces >> char '#' >> return ()-    -- null means failed parse, so _not_ a comment.---isBlank :: String -> Bool-isBlank = null . filter (not . isSpace)---type RC = ErrorT [(Integer,String)] Identity--instance Error [(Integer,String)] where-    noMsg  = [(-1, "Unknown error.")]-    strMsg s = [(-1, s)]---parseFile :: [String] -> RC (XConfig Layout)-parseFile ss = parseLines baseConfig theLines-  where theLines = filter (not . liftM2 (||) isComment isBlank . snd) -                   $ zip [1..] ss-        ---parseLines :: XConfig Layout -> [(Integer,String)] -> RC (XConfig Layout)-parseLines = foldM parse---parse :: XConfig Layout -> (Integer, String) -> RC (XConfig Layout)-parse xc (ln,s) = do-  (k,v) <- readKV s ln-  case M.lookup k commands of-    Nothing -> throwError [(ln,"Unknown command: "++k)]-    Just f  -> f v ln xc------------------------------------------------------------------------ Now the semantic parts, that convert from the relevant     ----- key-value entries to values in an XConfig                  -----------------------------------------------------------------------type Command = String -> Integer -> XConfig Layout -> RC (XConfig Layout)--commands :: M.Map String Command-commands = M.fromList $ -           [("modMask"             , cmd_modMask           )-           ,("numlockMask"         , cmd_numlockMask       )-           ,("normalBorderColor"   , cmd_normalBorderColor )-           ,("focusedBorderColor"  , cmd_focusedBorderColor)-           ,("terminal"            , cmd_terminal          )-           ,("workspaces"          , cmd_workspaces        )-           ,("focusFollowsMouse"   , cmd_focusFollowsMouse )-           ,("layouts"             , cmd_layouts           )-           ,("key"                 , cmd_key               )-           ,("manageHook"          , cmd_manageHook        )-           ,("borderWidth"         , cmd_borderWidth       )-           ]----- | Behind-the-scenes helper for both 'cmd_modMask' and 'cmd_numlockMask'.-genericModKey :: (KeyMask -> XConfig Layout) -> Command-genericModKey f s ln _ = do-  x <- rcRead s ln :: RC Integer-  case lookup x (zip [1..] [mod1Mask,mod2Mask,mod3Mask,mod4Mask,mod5Mask]) of-    Just y  -> return $ f y-    Nothing -> throwError [(ln,"Invalid mod key number: "++ show x)]-  ---- | Reads the mod key modifier number.-cmd_modMask :: Command-cmd_modMask s ln xc = genericModKey (\k -> xc{modMask = k}) s ln xc---- | Reads the numlock key modifier number.-cmd_numlockMask :: Command-cmd_numlockMask s ln xc = genericModKey (\k -> xc{numlockMask = k}) s ln xc----- | Reads the border width.-cmd_borderWidth :: Command-cmd_borderWidth s ln xc = do-  w <- rcRead s ln-  return $ xc { borderWidth = w }----- | Reads the colors but just keeps them as RRGGBB Strings.-cmd_normalBorderColor, cmd_focusedBorderColor :: Command-cmd_normalBorderColor  s _ xc = return $ xc{ normalBorderColor  = s } -cmd_focusedBorderColor s _ xc = return $ xc{ focusedBorderColor = s }----- | Reads the terminal. It is just a String, no parsing.-cmd_terminal :: Command-cmd_terminal s _ xc = return $ xc{ terminal = s }----- | Reads the workspace tag list. This is given as a Haskell [String].-cmd_workspaces :: Command-cmd_workspaces s ln xc = rcRead s ln >>= \x -> return xc{ workspaces = x }----- | Reads the focusFollowsMouse, as a Haskell Bool.-cmd_focusFollowsMouse :: Command-cmd_focusFollowsMouse s ln xc = rcRead s ln >>= -                                \x -> return xc{focusFollowsMouse = x}----- | The list known layouts, mapped by name.---   An easy location for improvement is to add more contrib layouts here.-layouts :: M.Map String (Layout Window)-layouts = M.fromList-          [("Tall", Layout (Tall 1 (3/100) (1/2)))-          ,("Wide", Layout (Mirror (Tall 1 (3/100) (1/2))))-          ,("Full", Layout Full)-          ]----- | Expects a [String], the strings being layout names. Quotes required.---   Draws from the `layouts' list above.-cmd_layouts :: Command-cmd_layouts s ln xc = do-  xs <- rcRead s ln -- read the list of strings-  let ls = map (id &&& (flip M.lookup) layouts) xs-  when (null ls) $ throwError [(ln,"Empty layout list")]-  case filter (not . isJust . snd) ls of-    [] -> return $ xc{ layoutHook = foldr1 -                       (\(Layout l) (Layout r) -> -                            Layout (l ||| r)) (map (fromJust . snd) ls) -                     }-    ys -> throwError $ map (\(x,_) -> (ln, "Unknown layout: "++ x)) ys------ | A Map from names to key binding actions.-key_actions :: M.Map String (X ())-key_actions = M.fromList-              [("kill"            , kill                   )-              ,("nextLayout"      , sendMessage NextLayout )-              --,("prevLayout"      , sendMessage PrevLayout )-              --,("resetLayout"     , setLayout $ XMonad.layoutHook conf)-              ,("refresh"         , refresh                )-              ,("focusDown"       , windows W.focusDown    )-              ,("focusUp"         , windows W.focusUp      )-              ,("focusMaster"     , windows W.focusMaster  )-              ,("swapMaster"      , windows W.swapMaster   )-              ,("swapDown"        , windows W.swapDown     )-              ,("swapUp"          , windows W.swapUp       )-              ,("shrink"          , sendMessage Shrink     )-              ,("expand"          , sendMessage Expand     )-              ,("sink"            , withFocused $ windows . W.sink)-              ,("incMaster"       , sendMessage (IncMasterN   1))-              ,("decMaster"       , sendMessage (IncMasterN (-1)))-              ,("quit"            , io $ exitWith ExitSuccess)-              ,("restart"         , broadcastMessage ReleaseResources -                                      >> restart "xmonad" True)-              ]----- | Expects keys as described in the preamble, as ---   (\"EZConfig key name\", \"action name\"), ---   eg. (\"M-S-t\", \"spawn thunderbird\")---   One key per "key=" line.-cmd_key :: Command-cmd_key s ln xc = do-  (k,v) <- rcRead s ln-  if "spawn " `isPrefixOf` v-    then return $ xc { -                      keys = \c -> M.union (mkKeymap c -                                            [(k, spawn (drop 6 v))]-                                           ) ((keys xc) c) -                     }-    else do-          case M.lookup v key_actions of-            Nothing -> throwError [(ln, "Unknown key action \"" ++ v ++ "\"")]-            Just ac -> return $ -                       xc { keys = \c -> M.union (mkKeymap c [(k, ac)])-                                   ((keys xc) c) -                          }------ | Map of names to actions for 'ManageHook's.-manageHook_actions :: M.Map String ManageHook-manageHook_actions = M.fromList -                     [("float"  , doFloat  )-                     ,("ignore" , doIgnore )-                     ]----- | Parses 'ManageHook's in the form given in the preamble.---   eg. (ClassName \"MPlayer\", \"float\")-cmd_manageHook :: Command-cmd_manageHook s ln xc = do-  (k,v) <- rcRead s ln-  let q = parseQuery k-  if "toWorkspace " `isPrefixOf` v-    then return $ xc { manageHook = manageHook xc <+> -                       (q --> doShift (drop 12 v))-                     }-    else case M.lookup v manageHook_actions of-           Nothing -> throwError [(ln, "Unknown ManageHook action \"" -                                   ++ v ++ "\"")]-           Just ac -> return $ xc { manageHook = manageHook xc <+> (q --> ac) }------ | Core of the ManageHook expression parser.---   Taken from Roman Cheplyaka's WindowProperties-parseQuery :: Property -> Query Bool-parseQuery (Title s)       = title =? s-parseQuery (ClassName s)   = className =? s-parseQuery (Resource s)    = resource =? s-parseQuery (And p q)       = parseQuery p <&&> parseQuery q-parseQuery (Or  p q)       = parseQuery p <&&> parseQuery q-parseQuery (Not p)         = not `fmap` parseQuery p-parseQuery (Const b)       = return b----- | Property constructors are quite self-explaining.---   Taken from Roman Cheplyaka's WindowProperties-data Property = Title String-              | ClassName String-              | Resource String-              | And Property Property  -              | Or  Property Property-              | Not Property-              | Const Bool-              deriving (Read, Show)------ | A wrapping of the read function into the RC monad.-rcRead :: (Read a) => String -> Integer -> RC a-rcRead s ln = case reads s of -                [(x,"")] -> return x-                _        -> throwError [(ln, "Failed to parse value")]------ | The standard Config.hs 'defaultConfig', with the layout wrapped.-baseConfig :: XConfig Layout-baseConfig = defaultConfig{ layoutHook = Layout (layoutHook defaultConfig) }------ | Core function that attempts to parse @~\/.xmonad\/xmonad.conf@-readConfig :: IO (Maybe (XConfig Layout))-readConfig = do-  dir <- getXMonadDir-  cs <- bracket (openFile (dir++"/xmonad.conf") ReadMode)-             (\h -> hClose h) -- vv force the lazy IO-             (\h -> (lines `fmap` hGetContents h) >>= \ss -> -                    length ss `seq` return ss)-  let xce = runIdentity $ runErrorT $ parseFile cs-  case xce of-    Left es  -> mapM_ (\(ln,e) -> -                           putStrLn $ "readConfig error: line "++show ln++-                                        ": "++ e) es -                >> return Nothing-    Right xc -> return $ Just xc----- | Attempts to run readConfig, and checks if it failed.-checkConfig :: IO Bool-checkConfig = isJust `fmap` readConfig----{-  REMOVED: It was for debugging, and causes an 'orphaned instances'-             warning to boot.------ | Reads in the config, and then prints the resulting XConfig-dumpConfig :: IO ()-dumpConfig = readConfig >>= print---instance Show (XConfig Layout) where-    show x = "XConfig { "-             ++ "normalBorderColor = "++ normalBorderColor x ++", "-             ++ "focusedBorderColor = "++ focusedBorderColor x++", "-             ++ "terminal = "++ terminal x ++", "-             ++ "workspaces = "++ show (workspaces x) ++", "-             ++ "numlockMask = "++ show (numlockMask x) ++", "-             ++ "modMask = "++ show (modMask x) ++", "-             ++ "borderWidth = "++ show (borderWidth x) ++", "-             ++ "focusFollowsMouse = "++ show (focusFollowsMouse x) ++", "-             ++ "layouts = "++ show (layoutHook x) ++" }"---}---- | Handles the unwrapping of the Layout. Intended for use as---   @main = plainConfig@-plainConfig :: IO ()-plainConfig = do-  conf <- readConfig-  case conf of-    (Just xc@XConfig{layoutHook= (Layout l)}) -> -        xmonad (xc{ layoutHook = l })-    Nothing                                   -> -        spawn $ "xmessage Failed to read xmonad.conf. See xmonad.errors."-
XMonad/Config/Sjanssen.hs view
@@ -1,5 +1,5 @@ {-# OPTIONS_GHC -fno-warn-missing-signatures #-}-module XMonad.Config.Sjanssen (sjanssenConfig) where+module XMonad.Config.Sjanssen (sjanssenConfig, sjanssenConfigXmobar) where  import XMonad hiding (Tall(..)) import qualified XMonad.StackSet as W@@ -10,41 +10,51 @@ import XMonad.Layout.NoBorders import XMonad.Hooks.DynamicLog hiding (xmobar) import XMonad.Hooks.ManageDocks+import XMonad.Hooks.ManageHelpers (isFullscreen, doFullFloat)+import XMonad.Hooks.EwmhDesktops import XMonad.Prompt-import XMonad.Prompt.Shell-import XMonad.Util.Run (spawnPipe)+import XMonad.Actions.SpawnOn +import XMonad.Layout.LayoutScreens+import XMonad.Layout.TwoPane+ import qualified Data.Map as M-import System.IO (hPutStrLn) +sjanssenConfigXmobar = statusBar "exec xmobar" sjanssenPP strutkey =<< sjanssenConfig+ where+    strutkey (XConfig {modMask = modm}) = (modm, xK_b)+ sjanssenConfig = do-    xmobar <- spawnPipe "xmobar"-    return $ defaultConfig-        { terminal = "urxvtc"+    sp <- mkSpawner+    return . ewmh $ defaultConfig+        { terminal = "exec urxvt"         , workspaces = ["irc", "web"] ++ map show [3 .. 9 :: Int]-        , logHook = dynamicLogWithPP $ sjanssenPP { ppOutput = hPutStrLn xmobar }         , mouseBindings = \(XConfig {modMask = modm}) -> M.fromList $                 [ ((modm, button1), (\w -> focus w >> mouseMoveWindow w))                 , ((modm, button2), (\w -> focus w >> windows W.swapMaster))                 , ((modm.|. shiftMask, button1), (\w -> focus w >> mouseResizeWindow w)) ]-        , keys = \c -> mykeys c `M.union` keys defaultConfig c-        , layoutHook = modifiers layouts-        , manageHook = composeAll [className =? x --> doF (W.shift w)+        , keys = \c -> mykeys sp c `M.union` keys defaultConfig c+        , layoutHook  = modifiers layouts+        , manageHook  = composeAll [className =? x --> doShift w                                     | (x, w) <- [ ("Firefox", "web")-                                                , ("Ktorrent", "7")]]-                       <+> manageHook defaultConfig <+> manageDocks+                                                , ("Ktorrent", "7")+                                                , ("Amarokapp", "7")]]+                        <+> manageHook defaultConfig <+> manageDocks <+> manageSpawn sp+                        <+> (isFullscreen --> doFullFloat)         }  where     tiled     = HintedTile 1 0.03 0.5 TopLeft     layouts   = (tiled Tall ||| (tiled Wide ||| Full)) ||| tabbed shrinkText myTheme-    modifiers = avoidStruts . smartBorders+    modifiers = smartBorders -    mykeys (XConfig {modMask = modm, workspaces = ws}) = M.fromList $-        [((modm,               xK_p     ), shellPrompt myPromptConfig)+    mykeys sp (XConfig {modMask = modm}) = M.fromList $+        [((modm,               xK_p     ), shellPromptHere sp myPromptConfig)+        ,((modm .|. shiftMask, xK_Return), spawnHere sp =<< asks (terminal . config))         ,((modm .|. shiftMask, xK_c     ), kill1)         ,((modm .|. shiftMask .|. controlMask, xK_c     ), kill)-        ,((modm .|. shiftMask, xK_0     ), windows $ \w -> foldr copy w ws)-        ,((modm,               xK_b     ), sendMessage ToggleStruts)+        ,((modm .|. shiftMask, xK_0     ), windows $ copyToAll)+        ,((modm,               xK_z     ), layoutScreens 2 $ TwoPane 0.5 0.5)+        ,((modm .|. shiftMask, xK_z     ), rescreen)         ]      myFont = "xft:Bitstream Vera Sans Mono:pixelsize=10"@@ -52,4 +62,6 @@     myPromptConfig = defaultXPConfig                         { position = Top                         , font = myFont+                        , showCompletionOnTab = True+                        , historyFilter = deleteConsecutive                         , promptBorderWidth = 0 }
XMonad/Config/Xfce.hs view
@@ -6,14 +6,16 @@ -- Copyright    : (c) Ivan Miljenovic <Ivan.Miljenovic@gmail.com> -- License      : BSD ----- Maintainer   : Ivan Miljenovic <Ivan.Miljenovic@gmail.com>+-- Maintainer   :  none+-- Stability    :  unstable+-- Portability  :  unportable -- -- This module provides a config suitable for use with the Xfce desktop -- environment.  module XMonad.Config.Xfce (     -- * Usage-    -- -- $usage+    -- $usage     xfceConfig     ) where @@ -29,7 +31,8 @@ -- > import XMonad.Config.Xfce -- > -- > main = xmonad xfceConfig--- +--+-- For examples of how to further customize @xfceConfig@ see "XMonad.Config.Desktop".  xfceConfig = desktopConfig     { terminal = "Terminal"
XMonad/Doc/Configuring.hs view
@@ -49,16 +49,25 @@ that this file can contain arbitrary Haskell code, which means that you have quite a lot of flexibility in configuring xmonad. -NOTE for users of previous versions (< 0.5) of xmonad: this is a major-change in the way xmonad is configured.  Prior to version 0.5,-configuring xmonad required editing an xmonad source file called-Config.hs, recompiling xmonad, and then restarting.  From version 0.5-onwards, however, you should NOT edit this file.  All you have to do-is edit xmonad.hs and restart with @mod-q@; xmonad does the-recompiling itself.  The format of the configuration file has also-changed; it is now simpler and much shorter, only requiring you to-list those settings which are different from the defaults.+HISTORICAL NOTE regarding upgrading from versions (< 0.5) of xmonad+or using old documentation: +xmonad-0.5 delivered a major change in the way xmonad is configured.  Prior+to version 0.5, configuring xmonad required editing a source file called+Config.hs, manually recompiling xmonad, and then restarting.  From+version 0.5 onwards, however, you should NOT edit this file or manually+compile with ghc --make.  All you have to do is edit xmonad.hs and restart+with @mod-q@; xmonad does the recompiling itself. The format of the+configuration file also changed with version 0.5; enabling simpler and+much shorter xmonad.hs files that only require listing those settings which+are different from the defaults.++While the complicated template.hs (man/xmonad.hs) files listing all default+settings are still provided for reference, once you wish to make substantial+changes to your configuration, the template.hs style configuration is not+recommended. It is fine to use top-level definitions to organize your+xmonad.hs, but wherever possible it is better to leave out settings that+simply duplicate defaults. -}  {- $example@@ -90,8 +99,8 @@  As an alternative, you can copy the template @xmonad.hs@ file (found either in the @man@ directory, if you have the xmonad source, or on-the xmonad wiki at-@http:\/\/haskell.org\/haskellwiki\/Xmonad\/Config_archive\/Template_xmonad.hs@)+the xmonad wiki config archive at+<http://haskell.org/haskellwiki/Xmonad/Config_archive>) into your @~\/.xmonad\/@ directory.  This template file contains all the default settings spelled out, and you should be able to simply change the ones you would like to change.@@ -106,18 +115,14 @@ #Checking_whether_your_xmonad.hs_is_correct#  After changing your configuration, it is a good idea to check that it-is syntactically and type correct.  You can do this easily by loading-your configuration file in the Haskell interpreter:+is syntactically and type correct.  You can do this easily by using an xmonad+flag: ->    $ ghci ~/.xmonad/xmonad.hs->    GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help->    Loading package base ... linking ... done.->    Ok, modules loaded: Main.->->    Prelude Main> :t main->    main :: IO ()+>    $ xmonad --recompile+>    $ -Ok, looks good.+If there is no output, your xmonad.hs has no errors.  If there are errors, they+will be printed to the console.  Patch them up and try again.  Note, however, that if you skip this step and try restarting xmonad with errors in your xmonad.hs, it's not the end of the world; xmonad@@ -139,15 +144,8 @@ related to your layouts, you may need to hit @mod-shift-space@ after restarting to see the changes take effect.)  If something goes wrong, the previous (default) settings will be used.  Note this requires that-GHC and xmonad are in your @$PATH@. If GHC isn't in your path, you can-still compile @xmonad.hs@ yourself:-->    $ cd ~/.xmonad->    $ /path/to/ghc --make xmonad.hs->    $ ls->    xmonad    xmonad.hi xmonad.hs xmonad.o--When you hit @mod-q@, this newly compiled xmonad will be used.+GHC and xmonad are in the @$PATH@ in the environment from which xmonad+is started.  -} 
XMonad/Doc/Extending.hs view
@@ -116,82 +116,176 @@ See "XMonad.Doc.Extending#Editing_key_bindings" for instructions on how to edit your key bindings. -* "XMonad.Actions.Commands": running internal xmonad actions-  interactively.+* "XMonad.Actions.Commands":+    Allows you to run internal xmonad commands (X () actions) using+    a dmenu menu in addition to key bindings.  Requires dmenu and+    the Dmenu XMonad.Actions module. -* "XMonad.Actions.ConstrainedResize": an aspect-ratio-constrained-  window resizing mode.+* "XMonad.Actions.ConstrainedResize":+    Lets you constrain the aspect ratio of a floating+    window (by, say, holding shift while you resize).+    Useful for making a nice circular XClock window. -* "XMonad.Actions.CopyWindow": duplicating windows on multiple-  workspaces.+* "XMonad.Actions.CopyWindow":+    Provides bindings to duplicate a window on multiple workspaces,+    providing dwm-like tagging functionality. -* "XMonad.Actions.CycleSelectedLayouts": bind a key to cycle through a-  particular subset of your layouts.+* "XMonad.Actions.CycleRecentWS":+    Provides bindings to cycle through most recently used workspaces+    with repeated presses of a single key (as long as modifier key is+    held down). This is similar to how many window managers handle+    window switching. -* "XMonad.Actions.CycleWS": move between workspaces in various ways.+* "XMonad.Actions.CycleSelectedLayouts":+    This module allows to cycle through the given subset of layouts. -* "XMonad.Actions.DeManage": cease management of a window without-  unmapping it.+* "XMonad.Actions.CycleWS":+    Provides bindings to cycle forward or backward through the list of+    workspaces, to move windows between workspaces, and to cycle+    between screens. Replaces the former XMonad.Actions.RotView. -* "XMonad.Actions.DwmPromote": dwm-like master window swapping.+* "XMonad.Actions.CycleWindows":+    Provides bindings to cycle windows up or down on the current workspace+    stack while maintaining focus in place. -* "XMonad.Actions.DynamicWorkspaces": add, delete, and rename workspaces.+* "XMonad.Actions.DeManage":+    This module provides a method to cease management of a window+    without unmapping it. "XMonad.Hooks.ManageDocks" is a+    more automated solution if your panel supports it. -* "XMonad.Actions.FindEmptyWorkspace": find an empty workspace.+* "XMonad.Actions.DwmPromote":+    Dwm-like swap function for xmonad.+    Swaps focused window with the master window. If focus is in the+    master, swap it with the next window in the stack. Focus stays in the+    master. -* "XMonad.Actions.FlexibleManipulate": move\/resize windows without-  warping the mouse.+* "XMonad.Actions.DynamicWorkspaces":+    Provides bindings to add and delete workspaces.  Note that you may only+    delete a workspace that is already empty. -* "XMonad.Actions.FlexibleResize": resize windows from any corner.+* "XMonad.Actions.FindEmptyWorkspace":+    Find an empty workspace. -* "XMonad.Actions.FloatKeys": move\/resize floating windows with-  keybindings.+* "XMonad.Actions.FlexibleManipulate":+    Move and resize floating windows without warping the mouse. -* "XMonad.Actions.FocusNth": focus the nth window on the screen.+* "XMonad.Actions.FlexibleResize":+    Resize floating windows from any corner. -* "XMonad.Actions.MouseGestures": bind mouse gestures to actions.+* "XMonad.Actions.FloatKeys":+    Move and resize floating windows. -* "XMonad.Actions.MouseResize": use with-  "XMonad.Layout.WindowArranger" to resize windows with the mouse when-  using a floating layout.+* "XMonad.Layout.FloatSnap":+    Move and resize floating windows using other windows and the edge of the+    screen as guidelines. -* "XMonad.Actions.NoBorders": forcibly remove borders from a window.-  Not to be confused with "XMonad.Layout.NoBorders".+* "XMonad.Actions.FocusNth":+    Focus the nth window of the current workspace. -* "XMonad.Actions.PerWorkspaceKeys": configure keybindings-  per-workspace.+* "XMonad.Actions.GridSelect":+    GridSelect displays items(e.g. the opened windows) in a 2D grid and lets+    the user select from it with the cursor/hjkl keys or the mouse. -* "XMonad.Actions.Promote": An action to move the focused window to-  the master pane, or swap the master with the next window.+* "XMonad.Actions.MessageFeedback":+    Alternative to 'XMonad.Operations.sendMessage' that provides knowledge+    of whether the message was handled, and utility functions based on+    this facility. -* "XMonad.Actions.RotSlaves": rotate non-master windows.+* "XMonad.Actions.MouseGestures":+    Support for simple mouse gestures. -* "XMonad.Actions.Search": provide helpful functions for easily-  running web searchs.+* "XMonad.Actions.MouseResize":+    A layout modifier to resize windows with the mouse by grabbing the+    window's lower right corner. -* "XMonad.Actions.SimpleDate": display the date in a popup menu.+* "XMonad.Actions.NoBorders":+    This module provides helper functions for dealing with window borders. -* "XMonad.Actions.SinkAll": sink all floating windows.+* "XMonad.Actions.OnScreen":+    Control workspaces on different screens (in xinerama mode). -* "XMonad.Actions.Submap": create key submaps, i.e. the ability to-  bind actions to key sequences rather than being limited to single-  key combinations.+* "XMonad.Actions.PerWorkspaceKeys":+    Define key-bindings on per-workspace basis. -* "XMonad.Actions.SwapWorkspaces": swap workspace tags.+* "XMonad.Actions.PhysicalScreens":+    Manipulate screens ordered by physical location instead of ID -* "XMonad.Actions.TagWindows": tag windows and select by tag.+* "XMonad.Actions.Plane":+    This module has functions to navigate through workspaces in a bidimensional+    manner. -* "XMonad.Actions.UpdatePointer": mouse-follows-focus.+* "XMonad.Actions.Promote":+    Alternate promote function for xmonad. -* "XMonad.Actions.Warp": warp the pointer.+* "XMonad.Actions.RandomBackground":+    An action to start terminals with a random background color -* "XMonad.Actions.WindowBringer": bring windows to you, and you to-  windows.+* "XMonad.Actions.RotSlaves":+    Rotate all windows except the master window and keep the focus in+    place. -* "XMonad.Actions.WindowGo": travel to windows based on various-  criteria; conditionally start a program if a window does not exist,-  or travel to that window if it does.+* "XMonad.Actions.Search":+    A module for easily running Internet searches on web sites through xmonad.+    Modeled after the handy Surfraw CLI search tools at <https://secure.wikimedia.org/wikipedia/en/wiki/Surfraw>. +* "XMonad.Actions.SimpleDate":+    An example external contrib module for XMonad.+    Provides a simple binding to dzen2 to print the date as a popup menu.++* "XMonad.Actions.SinkAll":+    (Deprecated) Provides a simple binding that pushes all floating windows on the+    current workspace back into tiling. Instead, use the more general+    "XMonad.Actions.WithAll"++* "XMonad.Actions.SpawnOn":+    Provides a way to modify a window spawned by a command(e.g shift it to the workspace+    it was launched on) by using the _NET_WM_PID property that most windows set on creation.++* "XMonad.Actions.Submap":+    A module that allows the user to create a sub-mapping of key bindings.++* "XMonad.Actions.SwapWorkspaces":+    Lets you swap workspace tags, so you can keep related ones next to+    each other, without having to move individual windows.++* "XMonad.Actions.TagWindows":+    Functions for tagging windows and selecting them by tags.++* "XMonad.Actions.TopicSpace":+    Turns your workspaces into a more topic oriented system.++* "XMonad.Actions.UpdateFocus":+    Updates the focus on mouse move in unfocused windows.++* "XMonadContrib.UpdatePointer":+    Causes the pointer to follow whichever window focus changes to.++* "XMonad.Actions.Warp":+    Warp the pointer to a given window or screen.++* "XMonad.Actions.WindowBringer":+    dmenu operations to bring windows to you, and bring you to windows.+    That is to say, it pops up a dmenu with window names, in case you forgot+    where you left your XChat.++* "XMonad.Actions.WindowGo":+    Defines a few convenient operations for raising (traveling to) windows based on XMonad's Query+    monad, such as 'runOrRaise'.++* "XMonad.Actions.WindowMenu":+    Uses "XMonad.Actions.GridSelect" to display a number of actions related to+    window management in the center of the focused window.++* "XMonad.Actions.WindowNavigation":+    Experimental rewrite of "XMonad.Layout.WindowNavigation".++* "XMonad.Actions.WithAll":+    Provides functions for performing a given action on all windows of+    the current workspace.++* "XMonad.Actions.WorkspaceCursors":+    Like "XMonad.Actions.Plane" for an arbitrary number of dimensions.+ -}  {- $configs@@ -202,14 +296,27 @@ configuration; you can also simply import them and use them as your own configuration, possibly with some modifications. + * "XMonad.Config.Arossato"+    This module specifies my xmonad defaults. -* "XMonad.Config.Dons"+* "XMonad.Config.Azerty"+    Fixes some keybindings for users of French keyboard layouts. -* "XMonad.Config.Droundy"+* "XMonad.Config.Desktop"+    This module provides core desktop environment settings used+    in the Gnome, Kde, and Xfce config configs. It is also useful+    for people using other environments such as lxde, or using+    tray or panel applications without full desktop environments. +* "XMonad.Config.Gnome"++* "XMonad.Config.Kde"+ * "XMonad.Config.Sjanssen" +* "XMonad.Config.Xfce"+ -}  {- $hooks@@ -236,35 +343,80 @@   See "XMonad.Doc.Extending#The_log_hook_and_external_status_bars" for more   information. +* 'XMonad.Core.handleEventHook': this hook is called on all events handled+  by xmonad, thus it is extremely powerful. See "Graphics.X11.Xlib.Extras"+  and xmonad source and development documentation for more details.+ Here is a list of the modules found in @XMonad.Hooks@: +* "XMonad.Hooks.DynamicHooks":+    One-shot and permanent ManageHooks that can be updated at runtime.+ * "XMonad.Hooks.DynamicLog": for use with 'XMonad.Core.logHook'; send   information about xmonad's state to standard output, suitable for   putting in a status bar of some sort. See   "XMonad.Doc.Extending#The_log_hook_and_external_status_bars". -* "XMonad.Hooks.EventHook": a hook to handle X events at the layout level.+* "XMonad.Hooks.EwmhDesktops":+    Makes xmonad use the EWMH hints to tell panel applications about its+    workspaces and the windows therein. It also allows the user to interact+    with xmonad by clicking on panels and window lists. -* "XMonad.Hooks.EwmhDesktops": support for pagers in panel applications.+* "XMonad.Hooks.FadeInactive":+    Makes XMonad set the _NET_WM_WINDOW_OPACITY atom for inactive windows,+    which causes those windows to become slightly translucent if something+    like xcompmgr is running -* "XMonad.Hooks.ManageDocks": handle DOCK and STRUT windows (such as-  status bars) appropriately, by de-managing them and creating-  appropriate gaps so as not to place other windows covering them.+* "XMonad.Hooks.FloatNext":+    Hook and keybindings for automatically sending the next+    spawned window(s) to the floating layer. +* "XMonad.Hooks.InsertPosition":+    Configure where new windows should be added and which window should be+    focused.++* "XMonad.Hooks.ManageDocks":+    This module provides tools to automatically manage 'dock' type programs,+    such as gnome-panel, kicker, dzen, and xmobar.+ * "XMonad.Hooks.ManageHelpers": provide helper functions to be used   in @manageHook@. -* "XMonad.Hooks.ServerMode": example use of "XMonad.Hooks.EventHook".+* "XMonad.Hooks.Place":+    Automatic placement of floating windows. -* "XMonad.Hooks.SetWMName": set the WM name.  Useful when e.g. running-  Java GUI programs.+* "XMonad.Hooks.RestoreMinimized":+    Lets you restore minimized windows (see "XMonad.Layout.Minimize")+    by selecting them on a taskbar (listens for _NET_ACTIVE_WINDOW+    and WM_CHANGE_STATE). -* "XMonad.Hooks.UrgencyHook": configure an action to occur when a window-  sets the urgent flag.+* "XMonad.Hooks.Script":+    Provides a simple interface for running a ~\/.xmonad\/hooks script with the+    name of a hook. -* "XMonad.Hooks.XPropManage": match on XProperties in your-  'XMonad.Core.manageHook'.+* "XMonad.Hooks.ServerMode": Allows sending commands to a running xmonad process. +* "XMonad.Hooks.SetCursor":+    Set a default mouse cursor on startup.++* "XMonad.Hooks.SetWMName":+    Sets the WM name to a given string, so that it could be detected using+    _NET_SUPPORTING_WM_CHECK protocol.  May be useful for making Java GUI+    programs work.++* "XMonad.Hooks.UrgencyHook":+    UrgencyHook lets you configure an action to occur when a window demands+    your attention. (In traditional WMs, this takes the form of \"flashing\"+    on your \"taskbar.\" Blech.)++* "XMonad.Hooks.WorkspaceByPos":+    Useful in a dual-head setup: Looks at the requested geometry of+    new windows and moves them to the workspace of the non-focused+    screen if necessary.++* "XMonad.Hooks.XPropManage":+    A ManageHook matching on XProperties.+ -}  {- $layouts@@ -274,7 +426,8 @@ three columns, and so on.  You will also find modules which provide facilities for combining-different layouts, such as "XMonad.Layout.Combo", or+different layouts, such as "XMonad.Layout.Combo", "XMonad.Layout.ComboP",+"XMonad.Layout.LayoutBuilder", "XMonad.Layout.SubLayouts", or "XMonad.Layout.LayoutCombinators".  Layouts can be also modified with layout modifiers. A general@@ -284,109 +437,297 @@ For more information on using those modules for customizing your 'XMonad.Core.layoutHook' see "XMonad.Doc.Extending#Editing_the_layout_hook". -* "XMonad.Layout.Accordion": put non-focused windows in ribbons at the-  top and bottom of the screen.+* "XMonad.Layout.Accordion":+    LayoutClass that puts non-focused windows in ribbons at the top and bottom+    of the screen. -* "XMonad.Layout.Circle": an elliptical, overlapping layout.+* "XMonad.Layout.AutoMaster":+    Provides layout modifier AutoMaster. It separates screen in two parts -+    master and slave. Size of slave area automatically changes depending on+    number of slave windows. -* "XMonad.Layout.Combo": combine multiple layouts into one.+* "XMonad.Layout.BorderResize":+    This layout modifier will allow to resize windows by dragging their+    borders with the mouse. However, it only works in layouts or modified+    layouts that react to the SetGeometry message.+    "XMonad.Layout.WindowArranger" can be used to create such a setup.+    BorderResize is probably most useful in floating layouts. -* "XMonad.Layout.Decoration": decorated layouts.+* "XMonad.Layout.BoringWindows":+    BoringWindows is an extension to allow windows to be marked boring -* "XMonad.Layout.DecorationMadness": some examples of decorated layouts.+* "XMonad.Layout.CenteredMaster":+    Two layout modifiers. centerMaster places master window at center,+    on top of all other windows, which are managed by base layout.+    topRightMaster is similar, but places master window in top right corner+    instead of center. -* "XMonad.Layout.Dishes": stack extra windows underneath the master windows.+* "XMonad.Layout.Circle":+    Circle is an elliptical, overlapping layout. -* "XMonad.Layout.DragPane": split the screen into two windows with a-  draggable divider.+* "XMonad.Layout.Column":+    Provides Column layout that places all windows in one column. Windows+    heights are calculated from equation: H1/H2 = H2/H3 = ... = q, where q is+    given. With Shrink/Expand messages you can change the q value. -* "XMonad.Layout.DwmStyle": windows decorated in a dwm-like style.+* "XMonad.Layout.Combo":+    A layout that combines multiple layouts. -* "XMonad.Layout.Grid": put windows in a square grid.+* "XMonad.Layout.ComboP":+    A layout that combines multiple layouts and allows to specify where to put+    new windows. -* "XMonad.Layout.HintedTile": gapless tiled layout that attempts to-  obey window size hints.+* "XMonad.Layout.Cross":+    A Cross Layout with the main window in the center. -* "XMonad.Layout.IM": a layout for multi-window instant message clients.+* "XMonad.Layout.Decoration":+    A layout modifier and a class for easily creating decorated+    layouts. -* "XMonad.Layout.LayoutCombinators": general layout combining.+* "XMonad.Layout.DecorationMadness":+    A collection of decorated layouts: some of them may be nice, some+    usable, others just funny. -* "XMonad.Layout.LayoutHints": make layouts respect window size hints.+* "XMonad.Layout.Dishes":+    Dishes is a layout that stacks extra windows underneath the master+    windows. -* "XMonad.Layout.LayoutModifier": a general framework for creating-  layout \"modifiers\"; useful for creating new layout modules.+* "XMonad.Layout.DragPane":+    Layouts that splits the screen either horizontally or vertically and+    shows two windows.  The first window is always the master window, and+    the other is either the currently focused window or the second window in+    layout order. See also "XMonad.Layout.MouseResizableTall" -* "XMonad.Layout.LayoutScreens": divide the screen into multiple-  virtual \"screens\".+* "XMonad.Layout.DwmStyle":+    A layout modifier for decorating windows in a dwm like style. -* "XMonad.Layout.MagicFocus": automagically put the focused window in-  the master area.+* "XMonad.Layout.FixedColumn":+    A layout much like Tall, but using a multiple of a window's minimum+    resize amount instead of a percentage of screen to decide where to+    split. This is useful when you usually leave a text editor or+    terminal in the master pane and like it to be 80 columns wide. -* "XMonad.Layout.Magnifier": increase the size of the focused window+* "XMonad.Layout.Gaps":+    Create manually-sized gaps along edges of the screen which will not+    be used for tiling, along with support for toggling gaps on and+    off. You probably want "XMonad.Hooks.ManageDocks". -* "XMonad.Layout.Maximize": temporarily maximize the focused window.+* "XMonad.Layout.Grid":+    A simple layout that attempts to put all windows in a square grid. -* "XMonad.Layout.MosaicAlt": give each window a specified relative-  amount of screen space.+* "XMonad.Layout.GridVariants":+    Two layouts: one is a variant of the Grid layout that allows the+    desired aspect ratio of windows to be specified.  The other is like+    Tall but places a grid with fixed number of rows and columns in the+    master area and uses an aspect-ratio-specified layout for the+    slaves. -* "XMonad.Layout.MultiToggle": dynamically apply and unapply layout-  transformers.+* "XMonad.Layout.HintedGrid":+    A not so simple layout that attempts to put all windows in a square grid+    while obeying their size hints. -* "XMonad.Layout.Named": change the names of layouts (as reported by-  e.g. "XMonad.Hooks.DynamicLog").+* "XMonad.Layout.HintedTile":+    A gapless tiled layout that attempts to obey window size hints,+    rather than simply ignoring them. -* "XMonad.Layout.NoBorders": display windows without borders.+* "XMonad.Layout.IM":+    Layout modfier suitable for workspace with multi-windowed instant messenger+    (like Psi or Tkabber). -* "XMonad.Layout.PerWorkspace": configure layouts on a per-workspace basis.+* "XMonad.Layout.IndependentScreens":+    Utility functions for simulating independent sets of workspaces on+    each screen (like dwm's workspace model), using internal tags to+    distinguish workspaces associated with each screen. -* "XMonad.Layout.Reflect": reflect any layout vertically or horizontally.+* "XMonad.Layout.LayoutBuilder":+    A layout combinator that sends a specified number of windows to one rectangle+    and the rest to another. -* "XMonad.Layout.ResizableTile": tiled layout allowing you to change-  width and height of windows.+* "XMonad.Layout.LayoutCombinators":+    The "XMonad.Layout.LayoutCombinators" module provides combinators+    for easily combining multiple layouts into one composite layout, as+    well as a way to jump directly to any particular layout (say, with+    a keybinding) without having to cycle through other layouts to get+    to it. -* "XMonad.Layout.ResizeScreen": a layout modifier to change the screen-  geometry on one side.+* "XMonad.Layout.LayoutHints":+    Make layouts respect size hints. -* "XMonad.Layout.Roledex": a \"completely pointless layout which acts-  like Microsoft's Flip 3D\".+* "XMonad.Layout.LayoutModifier":+    A module for writing easy layout modifiers, which do not define a+    layout in and of themselves, but modify the behavior of or add new+    functionality to other layouts.  If you ever find yourself writing+    a layout which takes another layout as a parameter, chances are you+    should be writing a LayoutModifier instead! -* "XMonad.Layout.ScratchWorkspace": implements a scratch workspace-  which can be shown and hidden with keybindings.+    In case it is not clear, this module is not intended to help you+    configure xmonad, it is to help you write other extension modules.+    So get hacking! -* "XMonad.Layout.ShowWName": Show the name of the current workspace when switching.+* "XMonad.Layout.LayoutScreens":+    Divide a single screen into multiple screens. -* "XMonad.Layout.SimpleDecoration": add simple decorations to windows.+* "XMonad.Layout.LimitWindows":+    A layout modifier that limits the number of windows that can be shown. -* "XMonad.Layout.SimpleFloat": a basic floating layout.+* "XMonad.Layout.MagicFocus":+    Automagically put the focused window in the master area. -* "XMonad.Layout.Simplest": a basic, simple layout that just lays out-  all windows with a fullscreen geometry.  Used by-  "XMonad.Layout.Tabbed".+* "XMonad.Layout.Magnifier":+    Screenshot  :  <http://caladan.rave.org/magnifier.png>+    This is a layout modifier that will make a layout increase the size+    of the window that has focus. -* "XMonad.Layout.Spiral": Fibonacci spiral layout.+* "XMonad.Layout.Master":+    Layout modfier that adds a master window to another layout. -* "XMonad.Layout.Square": split the screen into a square area plus the rest.+* "XMonad.Layout.Maximize":+    Temporarily yanks the focused window out of the layout to mostly fill+    the screen. -* "XMonad.Layout.TabBarDecoration": add a bar of tabs to any layout.+* "XMonad.Layout.MessageControl":+    Provides message escaping and filtering facilities which+    help control complex nested layouts. -* "XMonad.Layout.Tabbed": a tabbed layout.+* "XMonad.Layout.Minimize":+    Makes it possible to minimize windows, temporarily removing them+    from the layout until they are restored. -* "XMonad.Layout.ThreeColumns": a layout with three columns instead of two.+* "XMonad.Layout.Monitor":+    Layout modfier for displaying some window (monitor) above other windows -* "XMonad.Layout.ToggleLayouts": toggle between two layouts.+* "XMonad.Layout.Mosaic":+    Based on MosaicAlt, but aspect ratio messages always change the aspect+    ratios, and rearranging the window stack changes the window sizes. -* "XMonad.Layout.TwoPane": split the screen horizontally and show two-  windows.+* "XMonad.Layout.MosaicAlt":+    A layout which gives each window a specified amount of screen space+    relative to the others. Compared to the 'Mosaic' layout, this one+    divides the space in a more balanced way. -* "XMonad.Layout.WindowArranger": make any layout into a-  pseudo-floating layout by allowing you to move and resize windows.+* "XMonad.Layout.MouseResizableTile":+    A layout in the spirit of "XMonad.Layout.ResizableTile", but with the option+    to use the mouse to adjust the layout. -* "XMonad.Layout.WindowNavigation": navigate around a workspace-  directionally instead of using mod-j\/k.+* "XMonad.Layout.MultiToggle":+    Dynamically apply and unapply transformers to your window layout. This can+    be used to rotate your window layout by 90 degrees, or to make the+    currently focused window occupy the whole screen (\"zoom in\") then undo+    the transformation (\"zoom out\"). -* "XMonad.Layout.WorkspaceDir": set the current working directory in a-  workspace.+* "XMonad.Layout.Named":+    A module for assigning a name to a given layout. +* "XMonad.Layout.NoBorders":+    Make a given layout display without borders.  This is useful for+    full-screen or tabbed layouts, where you don't really want to waste a+    couple of pixels of real estate just to inform yourself that the visible+    window has focus.++* "XMonad.Layout.NoFrillsDecoration":+    Most basic version of decoration for windows without any additional+    modifications. In contrast to "XMonad.Layout.SimpleDecoration" this will+    result in title bars that span the entire window instead of being only the+    length of the window title.++* "XMonad.Layout.OneBig":+    Places one (master) window at top left corner of screen, and other (slave)+    windows at the top.++* "XMonad.Layout.PerWorkspace":+    Configure layouts on a per-workspace basis: use layouts and apply+    layout modifiers selectively, depending on the workspace.++* "XMonad.Layout.Reflect":+    Reflect a layout horizontally or vertically.++* "XMonad.Layout.ResizableTile":+    More useful tiled layout that allows you to change a width\/height of window.+    See also "XMonad.Layout.MouseResizableTile".++* "XMonad.Layout.ResizeScreen":+    A layout transformer to have a layout respect a given screen+    geometry. Mostly used with "Decoration" (the Horizontal and the+    Vertical version will react to SetTheme and change their dimension+    accordingly.++* "XMonad.Layout.Roledex":+    This is a completely pointless layout which acts like Microsoft's Flip 3D++* "XMonad.Layout.ShowWName":+    This is a layout modifier that will show the workspace name++* "XMonad.Layout.SimpleDecoration":+    A layout modifier for adding simple decorations to the windows of a+    given layout. The decorations are in the form of ion-like tabs+    for window titles.++* "XMonad.Layout.SimpleFloat":+    A basic floating layout.++* "XMonad.Layout.Simplest":+    A very simple layout. The simplest, afaik. Used as a base for+    decorated layouts.++* "XMonad.Layout.SimplestFloat":+    A basic floating layout like SimpleFloat but without the decoration.++* "XMonad.Layout.Spacing":+    Add a configurable amount of space around windows.++* "XMonad.Layout.Spiral":+    A spiral tiling layout.++* "XMonad.Layout.Square":+    A layout that splits the screen into a square area and the rest of the+    screen.+    This is probably only ever useful in combination with+    "XMonad.Layout.Combo".+    It sticks one window in a square region, and makes the rest+    of the windows live with what's left (in a full-screen sense).++* "XMonad.Layout.StackTile":+    A stacking layout, like dishes but with the ability to resize master pane.+    Mostly useful on small screens.++* "XMonad.Layout.SubLayouts":+    A layout combinator that allows layouts to be nested.++* "XMonad.Layout.TabBarDecoration":+    A layout modifier to add a bar of tabs to your layouts.++* "XMonad.Layout.Tabbed":+    A tabbed layout for the Xmonad Window Manager++* "XMonad.Layout.ThreeColumns":+    A layout similar to tall but with three columns. With 2560x1600 pixels this+    layout can be used for a huge main window and up to six reasonable sized+    slave windows.++* "XMonad.Layout.ToggleLayouts":+    A module to toggle between two layouts.++* "XMonad.Layout.TwoPane":+    A layout that splits the screen horizontally and shows two windows.  The+    left window is always the master window, and the right is either the+    currently focused window or the second window in layout order.++* "XMonad.Layout.WindowArranger":+    This is a pure layout modifier that will let you move and resize+    windows with the keyboard in any layout.++* "XMonad.Layout.WindowNavigation":+    WindowNavigation is an extension to allow easy navigation of a workspace.+    See also "XMonad.Actions.WindowNavigation".++* "XMonad.Layout.WorkspaceDir":+    WorkspaceDir is an extension to set the current directory in a workspace.+    Actually, it sets the current directory in a layout, since there's no way I+    know of to attach a behavior to a workspace.  This means that any terminals+    (or other programs) pulled up in that workspace (with that layout) will+    execute in that working directory.  Sort of handy, I think.+    Note this extension requires the 'directory' package to be installed.+ -}  {- $prompts@@ -400,39 +741,69 @@  These are the available prompts: -* "XMonad.Prompt.AppendFile": append lines of text to a file.+* "XMonad.Prompt.AppLauncher":+    A module for launch applicationes that receive parameters in the command+    line. The launcher call a prompt to get the parameters. -* "XMonad.Prompt.Directory": prompt for a directory.+* "XMonad.Prompt.AppendFile":+    A prompt for appending a single line of text to a file.  Useful for+    keeping a file of notes, things to remember for later, and so on---+    using a keybinding, you can write things down just about as quickly+    as you think of them, so it doesn't have to interrupt whatever else+    you're doing.+    Who knows, it might be useful for other purposes as well! -* "XMonad.Prompt.DirExec": put a bunch of scripts you want in a-  directory, then choose from among them with this prompt.+* "XMonad.Prompt.DirExec":+    A directory file executables prompt for XMonad. This might be useful if you+    don't want to have scripts in your PATH environment variable (same+    executable names, different behavior) - otherwise you might want to use+    "XMonad.Prompt.Shell" instead - but you want to have easy access to these+    executables through the xmonad's prompt. -* "XMonad.Prompt.Email": an example of "XMonad.Prompt.Input", send-  simple short e-mails from a prompt.+* "XMonad.Prompt.Directory":+    A directory prompt for XMonad -* "XMonad.Prompt.Input": useful for building general actions requiring-  input from a prompt.+* "XMonad.Prompt.Email":+    A prompt for sending quick, one-line emails, via the standard GNU+    \'mail\' utility (which must be in your $PATH).  This module is+    intended mostly as an example of using "XMonad.Prompt.Input" to+    build an action requiring user input. -* "XMonad.Prompt.Layout": choose a layout from a prompt.+* "XMonad.Prompt.Input":+    A generic framework for prompting the user for input and passing it+    along to some other action. -* "XMonad.Prompt.Man": open man pages.+* "XMonad.Prompt.Layout":+    A layout-selection prompt for XMonad -* "XMonad.Prompt.RunOrRaise": choose a program, and run it if not-  already running, or raise its window if it is.+* "XMonad.Prompt.Man":+    A manual page prompt for XMonad window manager.+    TODO+    * narrow completions by section number, if the one is specified+    (like @\/etc\/bash_completion@ does) -* "XMonad.Prompt.Shell": run a shell command.+* "XMonad.Prompt.RunOrRaise":+    A prompt for XMonad which will run a program, open a file,+    or raise an already running program, depending on context. -* "XMonad.Prompt.Ssh": open an ssh connection.+* "XMonad.Prompt.Shell":+    A shell prompt for XMonad -* "XMonad.Prompt.Theme": choose a decoration theme.+* "XMonad.Prompt.Ssh":+    A ssh prompt for XMonad -* "XMonad.Prompt.Window": choose an open window.+* "XMonad.Prompt.Theme":+    A prompt for changing the theme of the current workspace -* "XMonad.Prompt.Workspace": choose a workspace.+* "XMonad.Prompt.Window":+    xprompt operations to bring windows to you, and bring you to windows. -* "XMonad.Prompt.XMonad": perform various xmonad actions by choosing-  one from a prompt.+* "XMonad.Prompt.Workspace":+    A workspace prompt for XMonad +* "XMonad.Prompt.XMonad":+    A prompt for running XMonad commands+ Usually a prompt is called by some key binding. See "XMonad.Doc.Extending#Editing_key_bindings", which includes examples of adding some prompts.@@ -450,13 +821,17 @@  A non complete list with a brief description: +* "XMonad.Util.Cursor": configure the default cursor/pointer glyph.+ * "XMonad.Util.CustomKeys": configure key bindings (see   "XMonad.Doc.Extending#Editing_key_bindings"). -* "XMonad.Util.Dmenu": a dmenu binding.+* "XMonad.Util.Dmenu":+    A convenient binding to dmenu.+    Requires the process-1.0 package -* "XMonad.Util.Dzen" "XMonad.Util.Dmenu" provide useful functions for-  running dzen as a xmonad status bar and dmenu as a program launcher;+* "XMonad.Util.Dzen":+    Handy wrapper for dzen. Requires dzen >= 0.2.4.  * "XMonad.Util.EZConfig": configure key bindings easily, including a   parser for writing key bindings in "M-C-x" style.@@ -464,38 +839,68 @@ * "XMonad.Util.Font": A module for abstracting a font facility over   Core fonts and Xft -* "XMonad.Util.Invisible": a wrapper data type to store layout state-  which should not be persisted across restarts.+* "XMonad.Util.Invisible":+    A data type to store the layout state -* "XMonad.Util.Loggers": a collection of loggers that can be used in-  conjunction with "XMonad.Hooks.DynamicLog".+* "XMonad.Util.Loggers":+    A collection of simple logger functions and formatting utilities+    which can be used in the 'XMonad.Hooks.DynamicLog.ppExtras' field of+    a pretty-printing status logger format. See "XMonad.Hooks.DynamicLog"+    for more information. -* "XMonad.Util.NamedWindows": associate windows with their X titles.-  Used by, e.g. "XMonad.Layout.Tabbed".+* "XMonad.Util.NamedActions":+    A wrapper for keybinding configuration that can list the available+    keybindings. -* "XMonad.Util.Run": a collection of functions for running external-  processes.+* "XMonad.Util.NamedScratchpad":+    Like "XMonad.Util.Scratchpad" toggle windows to and from the current+    workspace. Supports several arbitrary applications at the same time. -* "XMonad.Util.Scratchpad": hotkey-launched floating terminal window.+* "XMonad.Util.NamedWindows":+    This module allows you to associate the X titles of windows with+    them. -* "XMonad.Util.Themes": a collection of themes to be used with-  floating layouts.+* "XMonad.Util.Paste":+    A module for sending key presses to windows. This modules provides generalized+    and specialized functions for this task. -* "XMonad.Util.Timer": set up a timer to handle deferred events.+* "XMonad.Util.Replace":+    Implements a @--replace@ flag outside of core. -* "XMonad.Util.WindowProperties": an EDSL for specifying and matching-  on window properties.+* "XMonad.Util.Run":+    This modules provides several commands to run an external process.+    It is composed of functions formerly defined in "XMonad.Util.Dmenu" (by+    Spencer Janssen), "XMonad.Util.Dzen" (by glasser\@mit.edu) and+    XMonad.Util.RunInXTerm (by Andrea Rossato). -* "XMonad.Util.WorkspaceCompare": general combinators for sorting-  workspaces in various ways, used by several other modules which need-  to sort workspaces (e.g. "XMonad.Hooks.DynamicLog").+* "XMonad.Util.Scratchpad":+    Very handy hotkey-launched toggleable floating terminal window. -* "XMonad.Util.XSelection" provide utilities for using the mouse-  selection;+* "XMonad.Util.StringProp":+    Internal utility functions for storing Strings with the root window.+    Used for global state like IORefs with string keys, but more latency,+    persistent between xmonad restarts. -* "XMonad.Util.XUtils" and "XMonad.Util.Font" are libraries for-  accessing Xlib and XFT function in a convenient way.+* "XMonad.Util.Themes":+    A (hopefully) growing collection of themes for decorated layouts. +* "XMonad.Util.Timer":+    A module for setting up timers++* "XMonad.Util.Types":+    Miscellaneous commonly used types.++* "XMonad.Util.WindowProperties":+    EDSL for specifying window properties; various utilities related to window+    properties.++* "XMonad.Util.XSelection":+    A module for accessing and manipulating X Window's mouse selection (the buffer used in copy and pasting).+    'getSelection' and 'putSelection' are adaptations of Hxsel.hs and Hxput.hs from the XMonad-utils++* "XMonad.Util.XUtils":+    A module for painting on the screen+ -}  --------------------------------------------------------------------------------@@ -527,9 +932,9 @@  and provide an appropriate definition of @myKeys@, such as: ->    myKeys x =->             [ ((modMask x, xK_F12), xmonadPrompt defaultXPConfig)->             , ((modMask x, xK_F3 ), shellPrompt  defaultXPConfig)+> myKeys conf@(XConfig {XMonad.modMask = modm}) =+>             [ ((modm, xK_F12), xmonadPrompt defaultXPConfig)+>             , ((modm, xK_F3 ), shellPrompt  defaultXPConfig) >             ]  This particular definition also requires importing "XMonad.Prompt",@@ -540,7 +945,7 @@  For a list of the names of particular keys (such as xK_F12, and so on), see-<http://hackage.haskell.org/packages/archive/X11/1.4.1/doc/html/Graphics-X11-Types.html>.+<http://hackage.haskell.org/packages/archive/X11/latest/doc/html/Graphics-X11-Types.html>  Usually, rather than completely redefining the key bindings, as we did above, we want to simply add some new bindings and\/or remove existing@@ -551,8 +956,9 @@ {- $keyAdding #Adding_key_bindings# -Adding key bindings can be done in different ways. The type signature-of 'XMonad.Core.XConfig.keys' is:+Adding key bindings can be done in different ways. See the end of this+section for the easiest ways. The type signature of+'XMonad.Core.XConfig.keys' is:  >    keys :: XConfig Layout -> M.Map (ButtonMask,KeySym) (X ()) @@ -571,9 +977,9 @@ For instance, if you have defined some additional key bindings like these: ->    myKeys x =->             [ ((modMask x, xK_F12), xmonadPrompt defaultXPConfig)->             , ((modMask x, xK_F3 ), shellPrompt  defaultXPConfig)+>    myKeys conf@(XConfig {XMonad.modMask = modm}) =+>             [ ((modm, xK_F12), xmonadPrompt defaultXPConfig)+>             , ((modm, xK_F3 ), shellPrompt  defaultXPConfig) >             ]  then you can create a new key bindings map by joining the default one@@ -604,9 +1010,9 @@ > >    newKeys x = M.union (keys defaultConfig x) (M.fromList (myKeys x)) >->    myKeys x =->             [ ((modMask x, xK_F12), xmonadPrompt defaultXPConfig)->             , ((modMask x, xK_F3 ), shellPrompt  defaultXPConfig)+>    myKeys conf@(XConfig {XMonad.modMask = modm}) =+>             [ ((modm, xK_F12), xmonadPrompt defaultXPConfig)+>             , ((modm, xK_F3 ), shellPrompt  defaultXPConfig) >             ]  There are much simpler ways to accomplish this, however, if you are@@ -632,8 +1038,8 @@ > >    keysToRemove :: XConfig Layout ->    [((KeyMask, KeySym),X ())] >    keysToRemove x =->             [ ((modMask x              , xK_q ), return ())->             , ((modMask x .|. shiftMask, xK_q ), return ())+>             [ ((modm              , xK_q ), return ())+>             , ((modm .|. shiftMask, xK_q ), return ()) >             ]  As you can see, it doesn't matter what actions we associate with the@@ -648,8 +1054,8 @@ > >    keysToRemove :: XConfig Layout -> [(KeyMask, KeySym)] >    keysToRemove x =->             [ (modMask x              , xK_q )->             , (modMask x .|. shiftMask, xK_q )+>             [ (modm              , xK_q )+>             , (modm .|. shiftMask, xK_q ) >             ]  Another even simpler possibility is the use of some of the utilities@@ -669,23 +1075,23 @@ >    delKeys x  = foldr M.delete           (defKeys x) (toRemove x) >    newKeys x  = foldr (uncurry M.insert) (delKeys x) (toAdd    x) >    -- remove some of the default key bindings->    toRemove x =->        [ (modMask x              , xK_j     )->        , (modMask x              , xK_k     )->        , (modMask x              , xK_p     )->        , (modMask x .|. shiftMask, xK_p     )->        , (modMask x .|. shiftMask, xK_q     )->        , (modMask x              , xK_q     )+>    toRemove XConfig{modMask = modm} =+>        [ (modm              , xK_j     )+>        , (modm              , xK_k     )+>        , (modm              , xK_p     )+>        , (modm .|. shiftMask, xK_p     )+>        , (modm .|. shiftMask, xK_q     )+>        , (modm              , xK_q     ) >        ] ++->        -- I want modMask .|. shiftMask 1-9 to be free!->        [(shiftMask .|. modMask x, k) | k <- [xK_1 .. xK_9]]+>        -- I want modm .|. shiftMask 1-9 to be free!+>        [(shiftMask .|. modm, k) | k <- [xK_1 .. xK_9]] >    -- These are my personal key bindings->    toAdd x   =->        [ ((modMask x              , xK_F12   ), xmonadPrompt defaultXPConfig )->        , ((modMask x              , xK_F3    ), shellPrompt  defaultXPConfig )+>    toAdd XConfig{modMask = modm} =+>        [ ((modm              , xK_F12   ), xmonadPrompt defaultXPConfig )+>        , ((modm              , xK_F3    ), shellPrompt  defaultXPConfig ) >        ] ++->        -- Use modMask .|. shiftMask .|. controlMask 1-9 instead->        [( (m .|. modMask x, k), windows $ f i)+>        -- Use modm .|. shiftMask .|. controlMask 1-9 instead+>        [( (m .|. modm, k), windows $ f i) >         | (i, k) <- zip (workspaces x) [xK_1 .. xK_9] >        ,  (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask .|. controlMask)] >        ]@@ -694,6 +1100,8 @@ module; take a look at the 'XMonad.Util.CustomKeys.customKeys' function in particular. +NOTE: modm is defined as the modMask you defined (or left as the default) in+your config. -}  {- $mouse
XMonad/Hooks/DynamicHooks.hs view
@@ -53,21 +53,21 @@ -- You must include this @dynHooksRef@ value when using the functions in this -- module: ----- > xmonad { keys = myKeys `Data.Map.union` Data.Map.fromList --- >                   [((modMask conf, xK_i), oneShotHook dynHooksRef --- >                    "FFlaunchHook" (className =? "firefox") (doShift "3") +-- > xmonad { keys = myKeys `Data.Map.union` Data.Map.fromList+-- >                   [((modm, xK_i), oneShotHook dynHooksRef+-- >                    "FFlaunchHook" (className =? "firefox") (doShift "3") -- >                    >> spawn "firefox")--- >                   ,((modMask conf, xK_u), addDynamicHook dynHooksRef +-- >                   ,((modm, xK_u), addDynamicHook dynHooksRef -- >                     (className =? "example" --> doFloat))--- >                   ,((modMask conf, xK_y), updatePermanentHook dynHooksRef+-- >                   ,((modm, xK_y), updatePermanentHook dynHooksRef -- >                     (const idHook))) ]  -- resets the permanent hook. --  data DynamicHooks = DynamicHooks     { transients :: [(Query Bool, ManageHook)]     , permanent  :: ManageHook }-       + -- | Creates the 'IORef' that stores the dynamically created 'ManageHook's. initDynamicHooks :: IO (IORef DynamicHooks) initDynamicHooks = newIORef (DynamicHooks { transients = [],@@ -80,7 +80,7 @@ -- doFloat and doIgnore are idempotent. -- | Master 'ManageHook' that must be in your @xmonad.hs@ 'ManageHook'. dynamicMasterHook :: IORef DynamicHooks -> ManageHook-dynamicMasterHook ref = return True --> +dynamicMasterHook ref = return True -->                   (ask >>= \w -> liftX (do   dh <- io $ readIORef ref   (Endo f)  <- runQuery (permanent dh) w@@ -99,7 +99,7 @@  -- | Modifies the permanent 'ManageHook' with an arbitrary function. updateDynamicHook :: IORef DynamicHooks -> (ManageHook -> ManageHook) -> X ()-updateDynamicHook ref f = +updateDynamicHook ref f =     io $ modifyIORef ref $ \dh -> dh { permanent = f (permanent dh) }  @@ -108,10 +108,10 @@ -- -- > className =? "example" --> doFloat ----- you must call 'oneShotHook' as +-- you must call 'oneShotHook' as -- -- > oneShotHook dynHooksRef (className =? "example) doFloat--- +-- oneShotHook :: IORef DynamicHooks -> Query Bool -> ManageHook -> X () oneShotHook ref q a =   io $ modifyIORef ref
XMonad/Hooks/DynamicLog.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE FlexibleContexts #-}+ ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Hooks.DynamicLog@@ -23,19 +25,22 @@     -- * Drop-in loggers     dzen,     xmobar,+    statusBar,     dynamicLog,-    dynamicLogDzen,-    dynamicLogXmobar,     dynamicLogXinerama,      -- * Build your own formatter     dynamicLogWithPP,     dynamicLogString,-    PP(..), defaultPP, dzenPP, xmobarPP, sjanssenPP, byorgeyPP,+    PP(..), defaultPP, +    -- * Example formatters+    dzenPP, xmobarPP, sjanssenPP, byorgeyPP,+     -- * Formatting utilities-    wrap, pad, shorten,-    xmobarColor, dzenColor, dzenEscape,+    wrap, pad, trim, shorten,+    xmobarColor, xmobarStrip,+    dzenColor, dzenEscape, dzenStrip,      -- * Internal formatting functions     pprWindowSet,@@ -50,6 +55,8 @@ -- Useful imports -- import XMonad+import Control.Monad+import Data.Char ( isSpace ) import Data.Maybe ( isJust, catMaybes ) import Data.List import qualified Data.Map as M@@ -72,21 +79,17 @@ -- >    import XMonad.Hooks.DynamicLog -- -- If you just want a quick-and-dirty status bar with zero effort, try--- the 'dzen' function, which sets up a dzen status bar with a default--- format:------ > main = dzen xmonad------ or, to use this with your own custom xmonad configuration,+-- the 'xmobar' or 'dzen' functions: ----- > main = dzen $ \conf -> xmonad $ conf { <your customizations> }+-- > main = xmonad =<< xmobar conf ----- Also you can use 'xmobar' function instead of 'dzen' in the examples above,--- if you have xmobar installed.+-- There is also 'statusBar' if you'd like to use another status bar, or would+-- like to use different formatting options.  The 'xmobar', 'dzen', and+-- 'statusBar' functions are preferred over the other options listed below, as+-- they take care of all the necessary plumbing -- no shell scripting required! ----- Alternatively, you can choose among several default status bar--- formats ('dynamicLog', 'dynamicLogDzen', 'dynamicLogXmobar', or--- 'dynamicLogXinerama') by simply setting your logHook to the+-- Alternatively, you can choose among several default status bar formats+-- ('dynamicLog' or 'dynamicLogXinerama') by simply setting your logHook to the -- appropriate function, for instance: -- -- > main = xmonad $ defaultConfig {@@ -139,69 +142,67 @@  ------------------------------------------------------------------------ --- | Run xmonad with a dzen status bar set to some nice defaults. Output--- is taken from the dynamicLogWithPP hook.+-- | Run xmonad with a dzen status bar set to some nice defaults. ----- > main = dzen xmonad+-- > main = xmonad =<< dzen conf -- -- The intent is that the above config file should provide a nice--- status bar with minimal effort.  If you want to customize your xmonad--- configuration while using this, you'll have to do something like------ > main = dzen $ \conf -> xmonad $ conf { <your customized settings...> }+-- status bar with minimal effort. -- -- If you wish to customize the status bar format at all, you'll have to--- use something like 'dynamicLogWithPP' instead.+-- use the 'statusBar' function instead. -- -- The binding uses the XMonad.Hooks.ManageDocks module to automatically -- handle screen placement for dzen, and enables 'mod-b' for toggling -- the menu bar. ---dzen ::-    (XConfig-       (ModifiedLayout AvoidStruts-          (Choose Tall (Choose (Mirror Tall) Full))) -> IO t) -> IO t-dzen f = do-  h <- spawnPipe ("dzen2" ++ " " ++ flags)-  f $ defaultConfig-           { logHook   = dynamicLogWithPP dzenPP-                          { ppOutput = hPutStrLn h }-           ,layoutHook = avoidStrutsOn [U] (layoutHook defaultConfig)-           ,keys       = \c -> toggleStrutsKey c `M.union` keys defaultConfig c-           ,manageHook = manageHook defaultConfig <+> manageDocks-           }+dzen :: LayoutClass l Window+     => XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))+dzen conf = statusBar ("dzen2 " ++ flags) dzenPP toggleStrutsKey conf  where     fg      = "'#a8a3f7'" -- n.b quoting     bg      = "'#3f3c6d'"     flags   = "-e 'onstart=lower' -w 400 -ta l -fg " ++ fg ++ " -bg " ++ bg  --- | Run xmonad with a xmobar status bar set to some nice defaults. Output--- is taken from the dynamicLogWithPP hook.+-- | Run xmonad with a xmobar status bar set to some nice defaults. ----- > main = xmobar xmonad+-- > main = xmonad =<< xmobar conf ----- This works pretty much the same as 'dzen' function above+-- This works pretty much the same as 'dzen' function above. ---xmobar ::-    (XConfig-       (ModifiedLayout AvoidStruts-          (Choose Tall (Choose (Mirror Tall) Full))) -> IO t) -> IO t-xmobar f = do-  h <- spawnPipe "xmobar"-  f $ defaultConfig-           { logHook    = dynamicLogWithPP xmobarPP { ppOutput = hPutStrLn h }-           , layoutHook = avoidStruts $ layoutHook defaultConfig-           , keys       = \c -> toggleStrutsKey c `M.union` keys defaultConfig c-           , manageHook = manageHook defaultConfig <+> manageDocks-           }+xmobar :: LayoutClass l Window+       => XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))+xmobar conf = statusBar "xmobar" xmobarPP toggleStrutsKey conf +-- | Modifies the given base configuration to launch the given status bar,+-- send status information to that bar, and allocate space on the screen edges+-- for the bar.+statusBar :: LayoutClass l Window+          => String    -- ^ the command line to launch the status bar+          -> PP        -- ^ the pretty printing options+          -> (XConfig Layout -> (KeyMask, KeySym))+                       -- ^ the desired key binding to toggle bar visibility+          -> XConfig l -- ^ the base config+          -> IO (XConfig (ModifiedLayout AvoidStruts l))+statusBar cmd pp k conf = do+    h <- spawnPipe cmd+    return $ conf+        { layoutHook = avoidStruts (layoutHook conf)+        , logHook = do+                        logHook conf+                        dynamicLogWithPP pp { ppOutput = hPutStrLn h }+        , manageHook = manageHook conf <+> manageDocks+        , keys       = liftM2 M.union keys' (keys conf)+        }+ where+    keys' = (`M.singleton` sendMessage ToggleStruts) . k+ -- | -- Helper function which provides ToggleStruts keybinding ---toggleStrutsKey :: XConfig t -> M.Map (KeyMask, KeySym) (X ())-toggleStrutsKey XConfig{modMask = modm} = M.fromList-        [ ((modm, xK_b ), sendMessage ToggleStruts) ]+toggleStrutsKey :: XConfig t -> (KeyMask, KeySym)+toggleStrutsKey XConfig{modMask = modm} = (modm, xK_b )  ------------------------------------------------------------------------ @@ -218,16 +219,6 @@ dynamicLog :: X () dynamicLog = dynamicLogWithPP defaultPP --- | An example log hook that emulates dwm's status bar, using colour--- codes printed to dzen.  Requires dzen. Workspaces, xinerama,--- layouts and the window title are handled.-dynamicLogDzen :: X ()-dynamicLogDzen = dynamicLogWithPP dzenPP---- | These are good defaults to be used with the xmobar status bar.-dynamicLogXmobar :: X ()-dynamicLogXmobar = dynamicLogWithPP xmobarPP- -- | Format the current status using the supplied pretty-printing format, --   and write it to stdout. dynamicLogWithPP :: PP -> X ()@@ -269,7 +260,7 @@ pprWindowSet :: WorkspaceSort -> [Window] -> PP -> WindowSet -> String pprWindowSet sort' urgents pp s = sepBy (ppWsSep pp) . map fmt . sort' $             map S.workspace (S.current s : S.visible s) ++ S.hidden s-   where this     = S.tag (S.workspace (S.current s))+   where this     = S.currentTag s          visibles = map (S.tag . S.workspace) (S.visible s)           fmt w = printer pp (S.tag w)@@ -313,6 +304,11 @@ pad :: String -> String pad = wrap " " " " +-- | Trim leading and trailing whitespace from a string.+trim :: String -> String+trim = f . f+    where f = reverse . dropWhile isSpace+ -- | Limit a string to a certain length, adding "..." if truncated. shorten :: Int -> String -> String shorten n xs | length xs < n = xs@@ -343,6 +339,20 @@ dzenEscape :: String -> String dzenEscape = concatMap (\x -> if x == '^' then "^^" else [x]) +-- | Strip dzen formatting or commands. Useful to remove ppHidden+--   formatting in ppUrgent field. For example:+--+-- >     , ppHidden          = dzenColor "gray20" "" . wrap "(" ")"+-- >     , ppUrgent          = dzenColor "dark orange" "" .  dzenStrip+dzenStrip :: String -> String+dzenStrip = strip [] where+    strip keep x+      | null x              = keep+      | "^^" `isPrefixOf` x = strip (keep ++ "^") (drop 2 x)+      | '^' == head x       = strip keep (drop 1 . dropWhile (/= ')') $ x)+      | otherwise           = let (good,x') = span (/= '^') x+                              in strip (keep ++ good) x'+ -- | Use xmobar escape codes to output a string with given foreground --   and background colors. xmobarColor :: String  -- ^ foreground color: a color name, or #rrggbb format@@ -354,6 +364,21 @@  -- ??? add an xmobarEscape function? +-- | Strip xmobar markup. Useful to remove ppHidden color from ppUrgent+--   field. For example:+--+-- >     , ppHidden          = xmobarColor "gray20" "" . wrap "<" ">"+-- >     , ppUrgent          = xmobarColor "dark orange" "" .  xmobarStrip+xmobarStrip :: String -> String+xmobarStrip = strip [] where+    strip keep x+      | null x                 = keep+      | "<fc="  `isPrefixOf` x = strip keep (drop 1 . dropWhile (/= '>') $ x)+      | "</fc>" `isPrefixOf` x = strip keep (drop 5  x)+      | '<' == head x          = strip (keep ++ "<") (tail x)+      | otherwise              = let (good,x') = span (/= '<') x+                                 in strip (keep ++ good) x'+ -- | The 'PP' type allows the user to customize the formatting of --   status information. data PP = PP { ppCurrent :: WorkspaceId -> String@@ -426,13 +451,14 @@                , ppExtras          = []                } --- | Settings to emulate dwm's statusbar, dzen only.+-- | Settings to emulate dwm's statusbar, dzen only. Uses dzenStrip in+-- ppUrgent. dzenPP :: PP dzenPP = defaultPP { ppCurrent  = dzenColor "white" "#2b4f98" . pad                      , ppVisible  = dzenColor "black" "#999999" . pad                      , ppHidden   = dzenColor "black" "#cccccc" . pad                      , ppHiddenNoWindows = const ""-                     , ppUrgent   = dzenColor "red" "yellow"+                     , ppUrgent   = dzenColor "red" "yellow" . dzenStrip                      , ppWsSep    = ""                      , ppSep      = ""                      , ppLayout   = dzenColor "black" "#cccccc" .@@ -450,6 +476,7 @@ xmobarPP = defaultPP { ppCurrent = xmobarColor "yellow" "" . wrap "[" "]"                      , ppTitle   = xmobarColor "green"  "" . shorten 40                      , ppVisible = wrap "(" ")"+                     , ppUrgent = xmobarColor "red" "yellow"                      }  -- | The options that sjanssen likes to use with xmobar, as an
− XMonad/Hooks/EventHook.hs
@@ -1,108 +0,0 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- for deriving Typeable-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}---------------------------------------------------------------------------------- |--- Module      :  XMonad.Hooks.EventHook--- Copyright   :  (c) 2007 Andrea Rossato--- License     :  BSD-style (see xmonad/LICENSE)------ Maintainer  :  andrea.rossato@unibz.it--- Stability   :  unstable--- Portability :  unportable------ A layout modifier that implements an event hook at the layout level.------ Since it operates at the 'Workspace' level, it will install itself--- on the first current 'Workspace' and will broadcast a 'Message' to--- all other 'Workspace's not to handle events.--------------------------------------------------------------------------------module XMonad.Hooks.EventHook-    ( -- * Usage-      -- $usage--      -- * Writing a hook-      -- $hook-      EventHook (..)-    , eventHook-    , HandleEvent-    ) where--import Control.Applicative ((<$>))-import Data.Maybe--import XMonad-import XMonad.StackSet (StackSet (..), Screen (..), Workspace (..))---- $usage--- You can use this module with the following in your--- @~\/.xmonad\/xmonad.hs@:------ > import XMonad.Hooks.EventHook------ Then edit your @layoutHook@ by adding the 'eventHook':------ > layoutHook = eventHook EventHookExample $ avoidStruts $ simpleTabbed ||| Full ||| etc..------ and then:------ > main = xmonad defaultConfig { layoutHook = myLayouts }------ For more detailed instructions on editing the layoutHook see:------ "XMonad.Doc.Extending#Editing_the_layout_hook"---- $hook--- Writing a hook is very simple.------ This is a basic example to log all events:------ > data EventHookExample = EventHookExample deriving ( Show, Read )--- > instance EventHook EventHookExample where--- >     handleEvent _ e = io $ hPutStrLn stderr . show $ e --return ()------ This is an 'EventHook' to log mouse button events:------ > data EventHookButton = EventHookButton deriving ( Show, Read )--- > instance EventHook EventHookButton where--- >    handleEvent _ (ButtonEvent {ev_window = w}) = do--- >         io $ hPutStrLn stderr $ "This is a button event on window " ++ (show w)--- >    handleEvent _ _ = return ()------ Obviously you can compose event hooks:------ > layoutHook = eventHook EventHookButton $ eventHook EventHookExample $ avoidStruts $ simpleTabbed ||| Full ||| etc..--eventHook :: EventHook eh => eh -> l a -> (HandleEvent eh l) a-eventHook = HandleEvent Nothing True--class (Read eh, Show eh) => EventHook eh where-    handleEvent :: eh -> Event -> X ()-    handleEvent _ _ = return ()--data HandleEvent eh l a = HandleEvent (Maybe WorkspaceId) Bool eh (l a) deriving ( Show, Read )--data EventHandleMsg = HandlerOff deriving ( Typeable )-instance Message EventHandleMsg--instance (EventHook eh, LayoutClass l a) => LayoutClass (HandleEvent eh l) a where-    runLayout (Workspace i (HandleEvent Nothing True eh l) ms) r = do-      broadcastMessage HandlerOff-      iws       <- (tag . workspace . current) <$> gets windowset-      (wrs, ml) <- runLayout (Workspace i l ms) r-      return (wrs, Just $ HandleEvent (Just iws) True eh (fromMaybe l ml))--    runLayout (Workspace i (HandleEvent mi b eh l) ms) r = do-      (wrs, ml) <- runLayout (Workspace i l ms) r-      return (wrs, Just $ HandleEvent mi b eh (fromMaybe l ml))--    handleMessage (HandleEvent i True eh l) m-        | Just HandlerOff <- fromMessage m = return . Just $ HandleEvent i False eh l-        | Just e          <- fromMessage m = handleMessage l (SomeMessage e) >>= \ml ->-                                             handleEvent eh e >>-                                             maybe (return Nothing) (\l' -> return . Just $ HandleEvent i True eh l') ml-    handleMessage (HandleEvent i b eh l) m = handleMessage l m >>=-                                             maybe (return Nothing) (\l' -> return . Just $ HandleEvent i b    eh l')--    description (HandleEvent _ _ _ l) = description l
XMonad/Hooks/EwmhDesktops.hs view
@@ -15,14 +15,17 @@ module XMonad.Hooks.EwmhDesktops (     -- * Usage     -- $usage-    EwmhDesktopsHook,+    ewmh,+    ewmhDesktopsStartup,     ewmhDesktopsLogHook,     ewmhDesktopsLogHookCustom,-    ewmhDesktopsLayout+    ewmhDesktopsEventHook     ) where +import Codec.Binary.UTF8.String (encode) import Data.List import Data.Maybe+import Data.Monoid  import XMonad import Control.Monad@@ -30,7 +33,6 @@  import XMonad.Hooks.SetWMName import XMonad.Util.WorkspaceCompare-import XMonad.Hooks.EventHook  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:@@ -38,34 +40,29 @@ -- > import XMonad -- > import XMonad.Hooks.EwmhDesktops -- >--- > myLogHook :: X ()--- > myLogHook = ewmhDesktopsLogHook--- >--- > myLayoutHook = ewmhDesktopsLayout $ avoidStruts $ layoutHook defaultConfig--- >--- > main = xmonad defaultConfig { layoutHook = myLayouts, logHook = myLogHook }------ 'avoidStruts' is used to automatically leave space for dock programs, and--- can be found in 'XMonad.Hooks.ManageDocks'.------ For more detailed instructions on editing the layoutHook see:------ "XMonad.Doc.Extending#The_log_hook_and_external_status_bars"------ For more detailed instructions on editing the layoutHook see:+-- > main = xmonad $ ewmh defaultConfig ----- "XMonad.Doc.Extending#Editing_the_layout_hook"+-- You may also be interested in 'avoidStruts' from XMonad.Hooks.ManageDocks.  +-- | Add EWMH functionality to the given config.  See above for an example.+ewmh :: XConfig a -> XConfig a+ewmh c = c { startupHook     = startupHook c +++ ewmhDesktopsStartup+           , handleEventHook = handleEventHook c +++ ewmhDesktopsEventHook+           , logHook         = logHook c +++ ewmhDesktopsLogHook }+ where x +++ y = mappend x y +-- |+-- Initializes EwmhDesktops and advertises EWMH support to the X+-- server+ewmhDesktopsStartup :: X ()+ewmhDesktopsStartup = setSupported  -- | -- Notifies pagers and window lists, such as those in the gnome-panel -- of the current state of workspaces and windows. ewmhDesktopsLogHook :: X () ewmhDesktopsLogHook = ewmhDesktopsLogHookCustom id-- -- | -- Generalized version of ewmhDesktopsLogHook that allows an arbitrary -- user-specified function to transform the workspace list (post-sorting)@@ -74,34 +71,34 @@     sort' <- getSortByIndex     let ws = f $ sort' $ W.workspaces s -    setSupported-     -- Number of Workspaces     setNumberOfDesktops (length ws)      -- Names thereof     setDesktopNames (map W.tag ws) -    -- Current desktop-    let curr = fromJust $ elemIndex (W.tag (W.workspace (W.current s))) $ map W.tag ws--    setCurrentDesktop curr-     -- all windows, with focused windows last     let wins =  nub . concatMap (maybe [] (\(W.Stack x l r)-> reverse l ++ r ++ [x]) . W.stack) $ ws     setClientList wins -    -- Per window Desktop-    -- To make gnome-panel accept our xinerama stuff, we display-    -- all visible windows on the current desktop.-    forM_ (W.current s : W.visible s) $ \x ->-        forM_ (W.integrate' (W.stack (W.workspace x))) $ \win -> do-            setWindowDesktop win curr+    -- Current desktop+    case (elemIndex (W.currentTag s) $ map W.tag ws) of+      Nothing -> return ()+      Just curr -> do+        setCurrentDesktop curr +        -- Per window Desktop+        -- To make gnome-panel accept our xinerama stuff, we display+        -- all visible windows on the current desktop.+        forM_ (W.current s : W.visible s) $ \x ->+            forM_ (W.integrate' (W.stack (W.workspace x))) $ \win -> do+                setWindowDesktop win curr+     forM_ (W.hidden s) $ \w ->-        let wn = fromJust $ elemIndex (W.tag w) (map W.tag ws) in-        forM_ (W.integrate' (W.stack w)) $ \win -> do-            setWindowDesktop win wn+        case elemIndex (W.tag w) (map W.tag ws) of+          Nothing -> return ()+          Just wn -> forM_ (W.integrate' (W.stack w)) $ \win -> do+                         setWindowDesktop win wn      setActiveWindow @@ -117,13 +114,8 @@ -- --  * _NET_ACTIVE_WINDOW (activate another window, changing workspace if needed) ---ewmhDesktopsLayout :: layout a -> HandleEvent EwmhDesktopsHook layout a-ewmhDesktopsLayout = eventHook EwmhDesktopsHook--data EwmhDesktopsHook = EwmhDesktopsHook deriving ( Show, Read )-instance EventHook EwmhDesktopsHook where-	handleEvent _ e@ClientMessageEvent {} = do handle e-	handleEvent _ _ = return ()+ewmhDesktopsEventHook :: Event -> X All+ewmhDesktopsEventHook e = handle e >> return (All True)  handle :: Event -> X () handle ClientMessageEvent {@@ -138,6 +130,7 @@        a_d <- getAtom "_NET_WM_DESKTOP"        a_aw <- getAtom "_NET_ACTIVE_WINDOW"        a_cw <- getAtom "_NET_CLOSE_WINDOW"+       a_ignore <- mapM getAtom ["XMONAD_TIMER"]        if  mt == a_cd then do                let n = fromIntegral (head d)                if 0 <= n && n < length ws then@@ -151,10 +144,14 @@         else if mt == a_aw then do                windows $ W.focusWindow w         else if mt == a_cw then do-               windows $ W.focusWindow w-               kill-        else trace $ "Unknown ClientMessageEvent " ++ show mt-handle _ = undefined -- does not happen, as otherwise ewmhDesktopsHook would not match+               killWindow w+        else if mt `elem` a_ignore then do+           return ()+        else do+          -- The Message is unknown to us, but that is ok, not all are meant+          -- to be handled by the window manager+          return ()+handle _ = return ()   setNumberOfDesktops :: (Integral a) => a -> X ()@@ -177,8 +174,7 @@     r <- asks theRoot     a <- getAtom "_NET_DESKTOP_NAMES"     c <- getAtom "UTF8_STRING"-    let names' = map (fromIntegral.fromEnum) $-            concatMap (++['\0']) names+    let names' = map fromIntegral $ concatMap ((++[0]) . encode) names     io $ changeProperty8 dpy r a c propModeReplace names'  setClientList :: [Window] -> X ()
XMonad/Hooks/FadeInactive.hs view
@@ -15,12 +15,18 @@ module XMonad.Hooks.FadeInactive (     -- * Usage     -- $usage-    fadeInactiveLogHook+    setOpacity,+    isUnfocused,+    fadeIn,+    fadeOut,+    fadeIf,+    fadeInactiveLogHook,+    fadeOutLogHook     ) where  import XMonad import qualified XMonad.StackSet as W-import Control.Monad (forM_)+import Control.Monad  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:@@ -30,11 +36,11 @@ -- > -- > myLogHook :: X () -- > myLogHook = fadeInactiveLogHook fadeAmount--- >     where fadeAmount = 0xdddddddd+-- >     where fadeAmount = 0.8 -- > -- > main = xmonad defaultConfig { logHook = myLogHook } ----- fadeAmount can be any integer+-- fadeAmount can be any rational between 0 and 1. -- you will need to have xcompmgr <http://freedesktop.org/wiki/Software/xapps> -- or something similar for this to do anything --@@ -46,30 +52,43 @@ -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" --- |--- sets the opacity of a window-setOpacity :: Window -> Integer -> X ()+-- | Converts a percentage to the format required for _NET_WM_WINDOW_OPACITY+rationalToOpacity :: Integral a => Rational -> a+rationalToOpacity perc+    | perc < 0 || perc > 1 = round perc -- to maintain backwards-compatability+    | otherwise = round $ perc * 0xffffffff++-- | sets the opacity of a window+setOpacity :: Window -> Rational -> X () setOpacity w t = withDisplay $ \dpy -> do     a <- getAtom "_NET_WM_WINDOW_OPACITY"     c <- getAtom "CARDINAL"-    io $ changeProperty32 dpy w a c propModeReplace [fromIntegral t]+    io $ changeProperty32 dpy w a c propModeReplace [rationalToOpacity t] --- |--- fades a window out by setting the opacity-fadeOut :: Integer -> Window -> X ()-fadeOut amt = flip setOpacity amt+-- | fades a window out by setting the opacity+fadeOut :: Rational -> Window -> X ()+fadeOut = flip setOpacity --- |--- makes a window completely opaque+-- | makes a window completely opaque fadeIn :: Window -> X ()-fadeIn = flip setOpacity 0xffffffff+fadeIn = fadeOut 1 --- |--- lowers the opacity of inactive windows to the specified amount-fadeInactiveLogHook :: Integer -> X ()-fadeInactiveLogHook amt = withWindowSet $ \s ->-    forM_ (concatMap visibleWins $ W.current s : W.visible s) (fadeOut amt) >>-    withFocused fadeIn-        where-          visibleWins = maybe [] unfocused . W.stack . W.workspace-          unfocused (W.Stack _ l r) = l ++ r+-- | Fades a window by the specified amount if it satisfies the first query, otherwise+-- makes it opaque.+fadeIf :: Query Bool -> Rational -> Query Rational+fadeIf qry amt = qry >>= \b -> return $ if b then amt else 1++-- | sets the opacity of inactive windows to the specified amount+fadeInactiveLogHook :: Rational -> X ()+fadeInactiveLogHook = fadeOutLogHook . fadeIf isUnfocused++-- | returns True if the window doesn't have the focus.+isUnfocused :: Query Bool+isUnfocused = ask >>= \w -> liftX . gets $ maybe True (w /=) . W.peek . windowset++-- | fades out every window by the amount returned by the query.+fadeOutLogHook :: Query Rational -> X ()+fadeOutLogHook qry = withWindowSet $ \s -> do+    let visibleWins = (W.integrate' . W.stack . W.workspace . W.current $ s) +++                      concatMap (W.integrate' . W.stack . W.workspace) (W.visible s)+    forM_ visibleWins $ liftM2 (=<<) setOpacity (runQuery qry)
+ XMonad/Hooks/FloatNext.hs view
@@ -0,0 +1,157 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Hooks.FloatNext+-- Copyright   :  Quentin Moser <quentin.moser@unifr.ch>+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Quentin Moser <quentin.moser@unifr.ch>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Hook and keybindings for automatically sending the next+-- spawned window(s) to the floating layer.+--+-----------------------------------------------------------------------------++module XMonad.Hooks.FloatNext ( -- * Usage+                                -- $usage++                                -- * The hook+                                floatNextHook++                                -- * Actions+                              , floatNext+                              , toggleFloatNext+                              , floatAllNew+                              , toggleFloatAllNew++                                -- * Queries+                              , willFloatNext+                              , willFloatAllNew++                                -- * 'DynamicLog' utilities+                                -- $pp+                              , willFloatNextPP+                              , willFloatAllNewPP+                              , runLogHook ) where++import Prelude hiding (all)++import XMonad++import Control.Monad (join)+import Control.Applicative ((<$>))+import Control.Arrow (first, second)+import Control.Concurrent.MVar+import System.IO.Unsafe (unsafePerformIO)+++{- Helper functions -}++modifyMVar2 :: MVar a -> (a -> a) -> IO ()+modifyMVar2 v f = modifyMVar_ v (return . f)++_set :: ((a -> a) -> (Bool, Bool) -> (Bool, Bool)) -> a -> X ()+_set f b = io $ modifyMVar2 floatModeMVar (f $ const b)++_toggle :: ((Bool -> Bool) -> (Bool, Bool) -> (Bool, Bool)) -> X ()+_toggle f = io $ modifyMVar2 floatModeMVar (f not)++_get :: ((Bool, Bool) -> a) -> X a+_get f = io $ f <$> readMVar floatModeMVar++_pp :: ((Bool, Bool) -> Bool) -> String -> (String -> String) -> X (Maybe String)+_pp f s st = _get f >>= \b -> if b then return $ Just $ st s else return Nothing+++{- The current state is kept here -}++floatModeMVar :: MVar (Bool, Bool)+floatModeMVar = unsafePerformIO $ newMVar (False, False)+++-- $usage+-- This module provides actions (that can be set as keybindings)+-- to automatically send the next spawned window(s) to the floating+-- layer.+--+-- You can use it by including the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Hooks.FloatNext+--+-- and adding 'floatNextHook' to your 'ManageHook':+--+-- > myManageHook = floatNextHook <+> manageHook defaultConfig+--+-- The 'floatNext' and 'toggleFloatNext' functions can be used in key+-- bindings to float the next spawned window:+--+-- > , ((modm, xK_e), toggleFloatNext)+--+-- 'floatAllNew' and 'toggleFloatAllNew' are similar but float all+-- spawned windows until disabled again.+--+-- > , ((modm, xK_r), toggleFloatAllNew)+++-- | This 'ManageHook' will selectively float windows as set+-- by 'floatNext' and 'floatAllNew'.+floatNextHook :: ManageHook+floatNextHook = do (next, all) <- io $ takeMVar floatModeMVar+                   io $ putMVar floatModeMVar (False, all)+                   if next || all then doFloat else idHook+++-- | @floatNext True@ arranges for the next spawned window to be+-- sent to the floating layer, @floatNext False@ cancels it.+floatNext :: Bool -> X ()+floatNext = _set first++toggleFloatNext :: X ()+toggleFloatNext = _toggle first++-- | @floatAllNew True@ arranges for new windows to be+-- sent to the floating layer, @floatAllNew False@ cancels it+floatAllNew :: Bool -> X ()+floatAllNew = _set second++toggleFloatAllNew :: X ()+toggleFloatAllNew = _toggle second+++-- | Whether the next window will be set floating+willFloatNext :: X Bool+willFloatNext = _get fst++-- | Whether new windows will be set floating+willFloatAllNew :: X Bool+willFloatAllNew = _get snd+++-- $pp+-- The following functions are used to display the current+-- state of 'floatNext' and 'floatAllNew' in your+-- 'XMonad.Hooks.DynamicLog.dynamicLogWithPP'.+-- 'willFloatNextPP' and 'willFloatAllNewPP' should be added+-- to the 'XMonad.Hooks.DynamicLog.ppExtras' field of your+-- 'XMonad.Hooks.DynamicLog.PP'.+--+-- Use 'runLogHook' to refresh the output of your 'logHook', so+-- that the effects of a 'floatNext'/... will be visible+-- immediately:+--+-- > , ((modm, xK_e), toggleFloatNext >> runLogHook)+--+-- The @String -> String@ parameters to 'willFloatNextPP' and+-- 'willFloatAllNewPP' will be applied to their output, you+-- can use them to set the text color, etc., or you can just+-- pass them 'id'.++willFloatNextPP :: (String -> String) -> X (Maybe String)+willFloatNextPP = _pp fst "Next"++willFloatAllNewPP :: (String -> String) -> X (Maybe String)+willFloatAllNewPP = _pp snd "All"++runLogHook :: X ()+runLogHook = join $ asks $ logHook . config
+ XMonad/Hooks/InsertPosition.hs view
@@ -0,0 +1,74 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Hooks.InsertPosition+-- Copyright   :  (c) 2009 Adam Vogt+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  vogt.adam@gmail.com+-- Stability   :  unstable+-- Portability :  portable+--+-- Configure where new windows should be added and which window should be+-- focused.+--+-----------------------------------------------------------------------------++module XMonad.Hooks.InsertPosition (+    -- * Usage+    -- $usage+    insertPosition+    ,Focus(..), Position(..)+    ) where++import XMonad(ManageHook, MonadReader(ask))+import qualified XMonad.StackSet as W+import Control.Applicative((<$>))+import Data.Maybe(fromMaybe)+import Data.List(find)+import Data.Monoid(Endo(Endo))++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Hooks.InsertPosition+-- > xmonad defaultConfig { manageHook = insertPosition Master Newer <+> myManageHook }+--+-- You should you put the manageHooks that use 'doShift' to take effect+-- /before/ 'insertPosition', so that the window order will be consistent.+-- Because ManageHooks compose from right to left (like function composition+-- '.'), this means that 'insertPosition' should be the leftmost ManageHook.++data Position = Master | End | Above | Below+data Focus = Newer | Older++-- | insertPosition. A manage hook for placing new windows. XMonad's default is+-- the same as using: @insertPosition Above Newer@.+insertPosition :: Position -> Focus -> ManageHook+insertPosition pos foc = Endo . g <$> ask+  where+    g w = viewingWs w (updateFocus w . ins w . W.delete w)+    ins w = (\f ws -> fromMaybe id (W.focusWindow <$> W.peek ws) $ f ws) $+        case pos of+            Master -> W.insertUp w . W.focusMaster+            End    -> insertDown w . W.modify' focusLast'+            Above  -> W.insertUp w+            Below  -> insertDown w+    updateFocus =+        case foc of+            Older -> const id+            Newer -> W.focusWindow++-- | Modify the StackSet when the workspace containing w is focused+viewingWs :: (Eq a, Eq s, Eq i, Show i) =>a-> (W.StackSet i l a s sd -> W.StackSet i l a s sd)-> W.StackSet i l a s sd-> W.StackSet i l a s sd+viewingWs w f = do+    i <- W.tag . W.workspace . W.current+    ws <- find (elem w . W.integrate' . W.stack) . W.workspaces+    maybe id (fmap (W.view i . f) . W.view . W.tag) ws++-- | 'insertDown' and 'focusLast' belong in XMonad.StackSet?+insertDown :: (Eq a) => a -> W.StackSet i l a s sd -> W.StackSet i l a s sd+insertDown w = W.swapDown . W.insertUp w++focusLast' ::  W.Stack a -> W.Stack a+focusLast' st = let ws = W.integrate st+    in W.Stack (last ws) (tail $ reverse ws) []
XMonad/Hooks/ManageDocks.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE PatternGuards, FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS -fglasgow-exts #-}--- deriving Typeable+-- deriving Typeable for ghc-6.6 compatibility, which is retained in the core ----------------------------------------------------------------------------- -- | -- Module       : XMonad.Hooks.ManageDocks@@ -18,7 +18,12 @@     -- * Usage     -- $usage     manageDocks, checkDock, AvoidStruts, avoidStruts, avoidStrutsOn,-    ToggleStruts(..), Direction(..)+    ToggleStruts(..),+    SetStruts(..),+    module XMonad.Util.Types,++    -- for XMonad.Actions.FloatSnap+    calcGap     ) where  @@ -27,8 +32,10 @@ import Foreign.C.Types (CLong) import Control.Monad import XMonad.Layout.LayoutModifier+import XMonad.Util.Types+import XMonad.Util.WindowProperties (getProp32s) -import Data.List (delete)+import qualified Data.Set as S  -- $usage -- To use this module, add the following import to @~\/.xmonad\/xmonad.hs@:@@ -52,12 +59,12 @@ -- 'AvoidStruts' also supports toggling the dock gaps; add a keybinding -- similar to: ----- > ,((modMask x, xK_b     ), sendMessage ToggleStruts)+-- > ,((modm, xK_b     ), sendMessage ToggleStruts) -- -- If you have multiple docks, you can toggle their gaps individually. -- For example, to toggle only the top gap: ----- > ,((modMask x .|. controlMask, xK_t), sendMessage $ ToggleStrut U)+-- > ,((modm .|. controlMask, xK_t), sendMessage $ ToggleStrut U) -- -- Similarly, you can use 'D', 'L', and 'R' to individually toggle -- gaps on the bottom, left, or right.@@ -79,18 +86,6 @@ -- "XMonad.Doc.Extending#Editing_key_bindings". -- --- | An enumeration of the four cardinal directions\/sides of the---   screen.------   Ideally this would go in its own separate module in Util,---   but ManageDocks is angling for inclusion into the xmonad core,---   so keep the dependencies to a minimum.-data Direction = U   -- ^ Up\/top-               | D   -- ^ Down\/bottom-               | R   -- ^ Right-               | L   -- ^ Left-  deriving ( Read, Show, Eq, Ord, Enum, Bounded )- -- | Detects if the given window is of type DOCK and if so, reveals --   it, but does not manage it. If the window has the STRUT property --   set, adjust the gap accordingly.@@ -100,10 +95,9 @@ -- | Checks if a window is a DOCK or DESKTOP window checkDock :: Query Bool checkDock = ask >>= \w -> liftX $ do-    a <- getAtom "_NET_WM_WINDOW_TYPE"     dock <- getAtom "_NET_WM_WINDOW_TYPE_DOCK"     desk <- getAtom "_NET_WM_WINDOW_TYPE_DESKTOP"-    mbr <- getProp a w+    mbr <- getProp32s "_NET_WM_WINDOW_TYPE" w     case mbr of         Just [r] -> return $ elem (fromIntegral r) [dock, desk]         _        -> return False@@ -111,12 +105,10 @@ -- | Gets the STRUT config, if present, in xmonad gap order getStrut :: Window -> X [Strut] getStrut w = do-    spa <- getAtom "_NET_WM_STRUT_PARTIAL"-    sa  <- getAtom "_NET_WM_STRUT"-    msp <- getProp spa w+    msp <- getProp32s "_NET_WM_STRUT_PARTIAL" w     case msp of         Just sp -> return $ parseStrutPartial sp-        Nothing -> fmap (maybe [] parseStrut) $ getProp sa w+        Nothing -> fmap (maybe [] parseStrut) $ getProp32s "_NET_WM_STRUT" w  where     parseStrut xs@[_, _, _, _] = parseStrutPartial . take 12 $ xs ++ cycle [minBound, maxBound]     parseStrut _ = []@@ -126,13 +118,9 @@         [(L, l, ly1, ly2), (R, r, ry1, ry2), (U, t, tx1, tx2), (D, b, bx1, bx2)]     parseStrutPartial _ = [] --- | Helper to read a property-getProp :: Atom -> Window -> X (Maybe [CLong])-getProp a w = withDisplay $ \dpy -> io $ getWindowProperty32 dpy a w- -- | Goes through the list of windows and find the gap so that all --   STRUT settings are satisfied.-calcGap :: [Direction] -> X (Rectangle -> Rectangle)+calcGap :: S.Set Direction2D -> X (Rectangle -> Rectangle) calcGap ss = withDisplay $ \dpy -> do     rootw <- asks theRoot     -- We don't keep track of dock like windows, so we find all of them here@@ -145,7 +133,7 @@     wa <- io $ getWindowAttributes dpy rootw     let screen = r2c $ Rectangle (fi $ wa_x wa) (fi $ wa_y wa) (fi $ wa_width wa) (fi $ wa_height wa)     return $ \r -> c2r $ foldr (reduce screen) (r2c r) struts-  where careAbout (s,_,_,_) = s `elem` ss+  where careAbout (s,_,_,_) = s `S.member` ss  -- | Adjust layout automagically: don't cover up any docks, status --   bars, etc.@@ -156,39 +144,68 @@ --   etc. on the indicated sides of the screen.  Valid sides are U --   (top), D (bottom), R (right), or L (left). avoidStrutsOn :: LayoutClass l a =>-                 [Direction]+                 [Direction2D]               -> l a               -> ModifiedLayout AvoidStruts l a-avoidStrutsOn ss = ModifiedLayout (AvoidStruts ss)+avoidStrutsOn ss = ModifiedLayout $ AvoidStruts $ S.fromList ss -data AvoidStruts a = AvoidStruts [Direction] deriving ( Read, Show )+data AvoidStruts a = AvoidStruts (S.Set Direction2D) deriving ( Read, Show )  -- | Message type which can be sent to an 'AvoidStruts' layout --   modifier to alter its behavior. data ToggleStruts = ToggleStruts-                  | ToggleStrut Direction+                  | ToggleStrut Direction2D   deriving (Read,Show,Typeable)  instance Message ToggleStruts +-- | SetStruts is a message constructor used to set or unset specific struts,+-- regardless of whether or not the struts were originally set. Here are some+-- example bindings:+--+-- Show all gaps:+--+-- >   ,((modm .|. shiftMask  ,xK_b),sendMessage $ SetStruts [minBound .. maxBound] [])+--+-- Hide all gaps:+--+-- >   ,((modm .|. controlMask,xK_b),sendMessage $ SetStruts [] [minBound .. maxBound])+--+-- Show only upper and left gaps:+--+-- >   ,((modm .|. controlMask .|. shiftMask,xK_b),sendMessage $ SetStruts [U,L] [minBound .. maxBound])+--+-- Hide the bottom keeping whatever the other values were:+--+-- >   ,((modm .|. controlMask .|. shiftMask,xK_g),sendMessage $ SetStruts [] [D])+data SetStruts = SetStruts { addedStruts   :: [Direction2D]+                           , removedStruts :: [Direction2D] -- ^ These are removed from the currently set struts before 'addedStruts' are added.+                           }+  deriving (Read,Show,Typeable)++instance Message SetStruts+ instance LayoutModifier AvoidStruts a where     modifyLayout (AvoidStruts ss) w r = do         nr <- fmap ($ r) (calcGap ss)         runLayout w nr -    handleMess (AvoidStruts ss) m-        | Just ToggleStruts    <- fromMessage m = return $ Just $ AvoidStruts (toggleAll ss)-        | Just (ToggleStrut s) <- fromMessage m = return $ Just $ AvoidStruts (toggleOne s ss)-        | otherwise = return Nothing-      where toggleAll []   = [U,D,L,R]-            toggleAll _    = []-            toggleOne x xs | x `elem` xs = delete x xs-                           | otherwise   = x : xs+    pureMess (AvoidStruts ss) m+        | Just ToggleStruts    <- fromMessage m = Just $ AvoidStruts (toggleAll ss)+        | Just (ToggleStrut s) <- fromMessage m = Just $ AvoidStruts (toggleOne s ss)+        | Just (SetStruts n k) <- fromMessage m+        , let newSS = S.fromList n `S.union` (ss S.\\ S.fromList k)+        , newSS /= ss = Just $ AvoidStruts newSS+        | otherwise = Nothing+      where toggleAll x | S.null x = S.fromList [minBound .. maxBound]+                        | otherwise = S.empty+            toggleOne x xs | x `S.member` xs = S.delete x xs+                           | otherwise   = x `S.insert` xs   -- | (Direction, height\/width, initial pixel, final pixel). -type Strut = (Direction, CLong, CLong, CLong)+type Strut = (Direction2D, CLong, CLong, CLong)  -- | (Initial x pixel, initial y pixel, --    final x pixel, final y pixel).
XMonad/Hooks/ManageHelpers.hs view
@@ -25,10 +25,14 @@ -- >     }  module XMonad.Hooks.ManageHelpers (+    Side(..),     composeOne,     (-?>), (/=?), (<==?), (</=?), (-->>), (-?>>),+    isInProperty,     isKDETrayWindow,     isFullscreen,+    isDialog,+    pid,     transientTo,     maybeToDefinite,     MaybeManageHook,@@ -36,15 +40,27 @@     transience',     doRectFloat,     doFullFloat,-    doCenterFloat+    doCenterFloat,+    doSideFloat,+    doFloatAt,+    doFloatDep,+    doHideIgnore ) where  import XMonad import qualified XMonad.StackSet as W+import XMonad.Util.WindowProperties (getProp32s)  import Data.Maybe import Data.Monoid +import System.Posix (ProcessID)++-- | Denotes a side of a screen. @S@ stands for South, @NE@ for Northwest+-- etc. @C@ stands for Center.+data Side = SC | NC | CE | CW | SE | SW | NE | NW | C+    deriving (Read, Show, Eq)+ -- | A ManageHook that may or may not have been executed; the outcome is embedded in the Maybe type MaybeManageHook = Query (Maybe (Endo WindowSet)) -- | A grouping type, which can hold the outcome of a predicate Query.@@ -105,25 +121,36 @@ -- | A predicate to check whether a window is a KDE system tray icon. isKDETrayWindow :: Query Bool isKDETrayWindow = ask >>= \w -> liftX $ do-    dpy <- asks display-    kde_tray <- getAtom "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR"-    r <- io $ getWindowProperty32 dpy kde_tray w+    r <- getProp32s "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR" w     return $ case r of         Just [_] -> True         _ -> False +-- | Helper to check if a window property contains certain value.+isInProperty :: String -> String -> Query Bool+isInProperty p v = ask >>= \w -> liftX $ do+    va <- getAtom v+    r <- getProp32s p w+    return $ case r of+        Just xs -> fromIntegral va `elem` xs+        _ -> False+ -- | A predicate to check whether a window wants to fill the whole screen. -- See also 'doFullFloat'. isFullscreen :: Query Bool-isFullscreen = ask >>= \w -> liftX $ do-    dpy <- asks display-    state <- getAtom "_NET_WM_STATE"-    full <- getAtom "_NET_WM_STATE_FULLSCREEN"-    r <- io $ getWindowProperty32 dpy state w-    return $ case r of-        Just xs -> fromIntegral full `elem` xs-        _ -> False+isFullscreen = isInProperty "_NET_WM_STATE" "_NET_WM_STATE_FULLSCREEN" +-- | A predicate to check whether a window is a dialog.+isDialog :: Query Bool+isDialog = isInProperty "_NET_WM_WINDOW_TYPE" "_NET_WM_WINDOW_TYPE_DIALOG"++pid :: Query (Maybe ProcessID)+pid = ask >>= \w -> liftX $ do+    p <- getProp32s "_NET_WM_PID" w+    return $ case p of+        Just [x] -> Just (fromIntegral x)+        _        -> Nothing+ -- | A predicate to check whether a window is Transient. -- It holds the result which might be the window it is transient to -- or it might be 'Nothing'.@@ -160,8 +187,36 @@ doFullFloat :: ManageHook doFullFloat = doRectFloat $ W.RationalRect 0 0 1 1 +-- | Floats a new window using a rectangle computed as a function of+--   the rectangle that it would have used by default.+doFloatDep :: (W.RationalRect -> W.RationalRect) -> ManageHook+doFloatDep move = ask >>= \w -> doF . W.float w . move . snd =<< liftX (floatLocation w)++-- | Floats a new window with its original size, and its top left+--   corner at a specific point on the screen (both coordinates should+--   be in the range 0 to 1).+doFloatAt :: Rational -> Rational -> ManageHook+doFloatAt x y = doFloatDep move+  where+    move (W.RationalRect _ _ w h) = W.RationalRect x y w h++-- | Floats a new window with its original size on the specified side of a+-- screen+doSideFloat :: Side -> ManageHook+doSideFloat side = doFloatDep move+  where+    move (W.RationalRect _ _ w h) = W.RationalRect cx cy w h+      where cx =      if side `elem` [SC,C ,NC] then (1-w)/2+                 else if side `elem` [SW,CW,NW] then 0+                 else {- side `elem` [SE,CE,NE] -}   1-w+            cy =      if side `elem` [CE,C ,CW] then (1-h)/2+                 else if side `elem` [NE,NC,NW] then 0+                 else {- side `elem` [SE,SC,SW] -}   1-h+ -- | Floats a new window with its original size, but centered. doCenterFloat :: ManageHook-doCenterFloat = ask >>= \w -> doF . W.float w . center . snd =<< liftX (floatLocation w)-    where-    center (W.RationalRect _ _ w h) = W.RationalRect ((1-w)/2) ((1-h)/2) w h+doCenterFloat = doSideFloat C++-- | Hides window and ignores it.+doHideIgnore :: ManageHook+doHideIgnore = ask >>= \w -> liftX (hide w) >> doF (W.delete w)
+ XMonad/Hooks/Place.hs view
@@ -0,0 +1,460 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Hooks.Place+-- Copyright   :  Quentin Moser <quentin.moser@unifr.ch>+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Quentin Moser <quentin.moser@unifr.ch>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Automatic placement of floating windows.+--+-----------------------------------------------------------------------------++module XMonad.Hooks.Place   ( -- * Usage+                              -- $usage++                              -- * Placement actions+                              placeFocused+                            , placeHook++                              -- * Placement policies+                              -- $placements+                            , Placement+                            , smart+                            , simpleSmart+                            , fixed+                            , underMouse+                            , inBounds+                            , withGaps++                              -- * Others+                            , purePlaceWindow ) where+++import XMonad+import qualified XMonad.StackSet as S++import XMonad.Layout.WindowArranger+import XMonad.Actions.FloatKeys++import qualified Data.Map as M+import Data.Ratio ((%))+import Data.List (sortBy, minimumBy, partition)+import Data.Maybe (maybe, fromMaybe, catMaybes)+import Data.Monoid (Endo(..))+import Control.Monad (guard, join)+import Control.Monad.Trans (lift)++-- $usage+-- This module provides a 'ManageHook' that automatically places+-- floating windows at appropriate positions on the screen, as well+-- as an 'X' action to manually trigger repositioning.+--+-- You can use this module by including the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Hooks.Place+--+-- and adding 'placeHook' to your 'manageHook', for example:+--+-- > main = xmonad $ defaultConfig { manageHook = placeHook simpleSmart+-- >                                              <+> manageHook defaultConfig }+--+-- Note that 'placeHook' should be applied after most other hooks, especially hooks+-- such as 'doFloat' and 'doShift'. Since hooks combined with '<+>' are applied from+-- right to left, this means that 'placeHook' should be the /first/ hook in your chain.+--+-- You can also define a key to manually trigger repositioning with 'placeFocused' by+-- adding the following to your keys definition:+--+-- > , ((modm, xK_w), placeFocused simpleSmart)+--+-- Both 'placeHook' and 'placeFocused' take a 'Placement' parameter, which specifies+-- the placement policy to use (smart, under the mouse, fixed position, etc.). See+-- 'Placement' for a list of available policies.++++{- Placement policies -}++-- $placements+-- Placement policies determine how windows will be placed by 'placeFocused' and 'placeHook'.+--+-- A few examples:+--+-- * Basic smart placement+--+-- > myPlacement = simpleSmart+--+-- * Under the mouse (pointer at the top-left corner), but constrained+--   inside of the screen area+--+-- > myPlacement = inBounds (underMouse (0, 0))+--+-- * Smart placement with a preference for putting windows near+-- the center of the screen, and with 16px gaps at the top and bottom+-- of the screen where no window will be placed+--+-- > myPlacement = withGaps (16,0,16,0) (smart (0.5,0.5))+++-- | The type of placement policies+data Placement = Smart (Rational, Rational)+               | Fixed (Rational, Rational)+               | UnderMouse (Rational, Rational)+               | Bounds (Dimension, Dimension, Dimension, Dimension) Placement+                 deriving (Show, Read, Eq)+++-- | Try to place windows with as little overlap as possible+smart :: (Rational, Rational) -- ^ Where the window should be placed inside+                              -- the available area. See 'fixed'.+      -> Placement+smart = Smart++simpleSmart :: Placement+simpleSmart = inBounds $ smart (0,0)+++-- | Place windows at a fixed position+fixed :: (Rational, Rational) -- ^ Where windows should go.+                              --+                              --     * (0,0) -> top left of the screen+                              --+                              --     * (1,0) -> top right of the screen+                              --+                              --     * etc+      -> Placement+fixed = Fixed+++-- | Place windows under the mouse+underMouse :: (Rational, Rational) -- ^ Where the pointer should be relative to+                                   -- the window's frame; see 'fixed'.+           -> Placement+underMouse = UnderMouse+++-- | Apply the given placement policy, constraining the+-- placed windows inside the screen boundaries.+inBounds :: Placement -> Placement+inBounds = Bounds (0,0,0,0)+++-- | Same as 'inBounds', but allows specifying gaps along the screen's edges+withGaps :: (Dimension, Dimension, Dimension, Dimension)+         -- ^ top, right, bottom and left gaps+         -> Placement -> Placement+withGaps = Bounds++++{- Placement functions -}+++-- | Repositions the focused window according to a placement policy. Works for+-- both \"real\" floating windows and windows in a 'WindowArranger'-based+-- layout.+placeFocused :: Placement -> X ()+placeFocused p = withFocused $ \window -> do+                   info <- gets $ screenInfo . S.current . windowset+                   floats <- gets $ M.keys . S.floating . windowset++                   r'@(Rectangle x' y' _ _) <- placeWindow p window info floats++                     -- use X.A.FloatKeys if the window is floating, send+                     -- a WindowArranger message otherwise.+                   case elem window floats of+                     True -> keysMoveWindowTo (x', y') (0, 0) window+                     False -> sendMessage $ SetGeometry r'+++-- | Hook to automatically place windows when they are created.+placeHook :: Placement -> ManageHook+placeHook p = do window <- ask+                 r <- Query $ lift $ getWindowRectangle window+                 allRs <- Query $ lift $ getAllRectangles+                 pointer <- Query $ lift $ getPointer window++                 return $ Endo $ \theWS -> fromMaybe theWS $+                   do let currentRect = screenRect $ S.screenDetail $ S.current theWS+                          floats = M.keys $ S.floating theWS++                      guard(window `elem` floats )++                        -- Look for the workspace(s) on which the window is to be+                        -- spawned. Each of them also needs an associated screen+                        -- rectangle; for hidden workspaces, we use the current+                        -- workspace's screen.+                      let infos = filter ((window `elem`) . stackContents . S.stack . fst)+                                     $ [screenInfo $ S.current theWS]+                                        ++ (map screenInfo $ S.visible theWS)+                                        ++ zip (S.hidden theWS) (repeat currentRect)++                      guard(not $ null infos)++                      let (workspace, screen) = head infos+                          rs = catMaybes $ map (flip M.lookup allRs)+                               $ organizeClients workspace window floats+                          r' = purePlaceWindow p screen rs pointer r+                          newRect = r2rr screen r'+                          newFloats = M.insert window newRect (S.floating theWS)++                      return $ theWS { S.floating = newFloats }+++placeWindow :: Placement -> Window+            -> (S.Workspace WorkspaceId (Layout Window) Window, Rectangle)+                 -- ^ The workspace with reference to which the window should be placed,+                 -- and the screen's geometry.+            -> [Window]+                 -- ^ The list of floating windows.+            -> X Rectangle+placeWindow p window (ws, s) floats+  = do (r, rs, pointer) <- getNecessaryData window ws floats+       return $ purePlaceWindow p s rs pointer r+++-- | Compute the new position of a window according to a placement policy.+purePlaceWindow :: Placement -- ^ The placement strategy+                -> Rectangle -- ^ The screen+                -> [Rectangle] -- ^ The other visible windows+                -> (Position, Position) -- ^ The pointer's position.+                -> Rectangle -- ^ The window to be placed+                -> Rectangle+purePlaceWindow (Bounds (t,r,b,l) p') (Rectangle sx sy sw sh) rs p w+  = let s' = (Rectangle (sx + fi l) (sy + fi t) (sw - l - r) (sh - t - b))+    in checkBounds s' $ purePlaceWindow p' s' rs p w++purePlaceWindow (Fixed ratios) s _ _ w = placeRatio ratios s w++purePlaceWindow (UnderMouse (rx, ry)) _ _ (px, py) (Rectangle _ _ w h)+  = Rectangle (px - truncate (rx * fi w)) (py - truncate (ry * fi h)) w h++purePlaceWindow (Smart ratios) s rs _ w+  = placeSmart ratios s rs (rect_width w) (rect_height w)+++-- | Helper: Places a Rectangle at a fixed position indicated by two Rationals+-- inside another,+placeRatio :: (Rational, Rational) -> Rectangle -> Rectangle -> Rectangle+placeRatio (rx, ry) (Rectangle x1 y1 w1 h1) (Rectangle _ _ w2 h2)+  = Rectangle (scale rx x1 (x1 + fi w1 - fi w2))+              (scale ry y1 (y1 + fi h1 - fi h2))+              w2 h2+++-- | Helper: Ensures its second parameter is contained inside the first+-- by possibly moving it.+checkBounds :: Rectangle -> Rectangle -> Rectangle+checkBounds (Rectangle x1 y1 w1 h1) (Rectangle x2 y2 w2 h2)+  = Rectangle (max x1 (min (x1 + fi w1 - fi w2) x2))+              (max y1 (min (y1 + fi h1 - fi h2) y2))+              w2 h2++++++{- Utilities -}++scale :: (RealFrac a, Integral b) => a -> b -> b -> b+scale r n1 n2 = truncate $ r * fi n2 + (1 - r) * fi n1++fi :: (Integral a, Num b) => a -> b+fi = fromIntegral++r2rr :: Rectangle -> Rectangle -> S.RationalRect+r2rr (Rectangle x0 y0 w0 h0) (Rectangle x y w h)+  = S.RationalRect ((fi x-fi x0) % fi w0)+                   ((fi y-fi y0) % fi h0)+                   (fi w % fi w0)+                   (fi h % fi h0)++++{- Querying stuff -}++stackContents :: Maybe (S.Stack w) -> [w]+stackContents = maybe [] S.integrate++screenInfo :: S.Screen i l a sid ScreenDetail -> (S.Workspace i l a, Rectangle)+screenInfo (S.Screen { S.workspace = ws, S.screenDetail = (SD s)}) = (ws, s)++getWindowRectangle :: Window -> X Rectangle+getWindowRectangle window+  = do d <- asks display+       (_, x, y, w, h, _, _) <- io $ getGeometry d window++         -- We can't use the border width returned by+         -- getGeometry because it will be 0 if the+         -- window isn't mapped yet.+       b <- asks $ borderWidth . config++       return $ Rectangle x y (w + 2*b) (h + 2*b)++getAllRectangles :: X (M.Map Window Rectangle)+getAllRectangles = do ws <- gets windowset+                      let allWindows = join $ map (stackContents . S.stack)+                                         $ (S.workspace . S.current) ws+                                         : (map S.workspace . S.visible) ws+                                         ++ S.hidden ws+                      allRects <- mapM getWindowRectangle allWindows++                      return $ M.fromList $ zip allWindows allRects++organizeClients :: S.Workspace a b Window -> Window -> [Window] -> [Window]+organizeClients ws w floats+  = let (floatCs, layoutCs) = partition (`elem` floats) $ filter (/= w)+                              $ stackContents $ S.stack ws+    in reverse layoutCs ++ reverse floatCs+      -- About the ordering: the smart algorithm will overlap windows+      -- starting ith the head of the list. So:+      --  - we put the non-floating windows first since they'll+      --    probably be below the floating ones,+      --  - we reverse the lists, since the newer/more important+      --    windows are usually near the head.++getPointer :: Window -> X (Position, Position)+getPointer window = do d <- asks display+                       (_,_,_,x,y,_,_,_) <- io $ queryPointer d window+                       return (fi x,fi y)++-- | Return values are, in order: window's rectangle,+-- other windows' rectangles and pointer's coordinates.+getNecessaryData :: Window+                 -> S.Workspace WorkspaceId (Layout Window) Window+                 -> [Window]+                 -> X (Rectangle, [Rectangle], (Position, Position))+getNecessaryData window ws floats+  = do r <- getWindowRectangle window++       rs <- return (organizeClients ws window floats)+             >>= mapM getWindowRectangle++       pointer <- getPointer window++       return (r, rs, pointer)+++++{- Smart placement algorithm -}++-- | Alternate representation for rectangles.+data SmartRectangle a = SR+  { sr_x0, sr_y0 :: a -- ^ Top left coordinates, inclusive+  , sr_x1, sr_y1 :: a -- ^ Bottom right coorsinates, exclusive+  } deriving (Show, Eq)++r2sr :: Rectangle -> SmartRectangle Position+r2sr (Rectangle x y w h) = SR x y (x + fi w) (y + fi h)++sr2r :: SmartRectangle Position -> Rectangle+sr2r (SR x0 y0 x1 y1) = Rectangle x0 y0 (fi $ x1 - x0) (fi $ y1 - y0)++width :: Num a => SmartRectangle a -> a+width r = sr_x1 r - sr_x0 r++height :: Num a => SmartRectangle a -> a+height r = sr_y1 r - sr_y0 r++isEmpty :: Real a => SmartRectangle a -> Bool+isEmpty r = (width r <= 0) || (height r <= 0)++contains :: Real a => SmartRectangle a -> SmartRectangle a -> Bool+contains r1 r2 = sr_x0 r1 <= sr_x0 r2+                 && sr_y0 r1 <= sr_y0 r2+                 && sr_x1 r1 >= sr_x1 r2+                 && sr_y1 r1 >= sr_y1 r2+++-- | Main placement function+placeSmart :: (Rational, Rational) -- ^ point of the screen where windows+                                   -- should be placed first, if possible.+           -> Rectangle -- ^ screen+           -> [Rectangle] -- ^ other clients+           -> Dimension -- ^ width+           -> Dimension -- ^ height+           -> Rectangle+placeSmart (rx, ry) s@(Rectangle sx sy sw sh) rs w h+  = let free = map sr2r $ findSpace (r2sr s) (map r2sr rs) (fi w) (fi h)+    in position free (scale rx sx (sx + fi sw - fi w))+                     (scale ry sy (sy + fi sh - fi h))+                     w h++-- | Second part of the algorithm:+-- Chooses the best position in which to place a window,+-- according to a list of free areas and an ideal position for+-- the top-left corner.+-- We can't use semi-open surfaces for this, so we go back to+-- X11 Rectangles/Positions/etc instead.+position :: [Rectangle] -- ^ Free areas+         -> Position -> Position -- ^ Ideal coordinates+         -> Dimension -> Dimension -- ^ Width and height of the window+         -> Rectangle+position rs x y w h = minimumBy distanceOrder $ map closest rs+  where distanceOrder r1 r2+          = compare (distance (rect_x r1,rect_y r1) (x,y) :: Dimension)+                    (distance (rect_x r2,rect_y r2) (x,y) :: Dimension)+        distance (x1,y1) (x2,y2) = truncate $ (sqrt :: Double -> Double)+                                   $ fi $ (x1 - x2)^(2::Int)+                                        + (y1 - y2)^(2::Int)+        closest r = checkBounds r (Rectangle x y w h)+++-- | First part of the algorithm:+-- Tries to find an area in which to place a new+-- rectangle so that it overlaps as little as possible with+-- other rectangles already present. The first rectangles in+-- the list will be overlapped first.+findSpace :: Real a =>+             SmartRectangle a -- ^ The total available area+          -> [SmartRectangle a] -- ^ The parts already in use+          -> a -- ^ Width of the rectangle to place+          -> a -- ^ Height of the rectangle to place+          -> [SmartRectangle a]+findSpace total [] _ _ = [total]+findSpace total rs@(_:rs') w h+  = case filter largeEnough $ cleanup $ subtractRects total rs of+      [] -> findSpace total rs' w h+      as -> as+    where largeEnough r = width r >= w && height r >= h+++-- | Subtracts smaller rectangles from a total rectangle+-- , returning a list of remaining rectangular areas.+subtractRects :: Real a => SmartRectangle a+               -> [SmartRectangle a] -> [SmartRectangle a]+subtractRects total [] = [total]+subtractRects total (r:rs)+  = do total' <- subtractRects total rs+       filter (not . isEmpty)+                [ total' {sr_y1 = min (sr_y1 total') (sr_y0 r)} -- Above+                , total' {sr_x0 = max (sr_x0 total') (sr_x1 r)} -- Right+                , total' {sr_y0 = max (sr_y0 total') (sr_y1 r)} -- Below+                , total' {sr_x1 = min (sr_x1 total') (sr_x0 r)} -- Left+                ]+++-- | "Nubs" a list of rectangles, dropping all those that are+-- already contained in another rectangle of the list.+cleanup :: Real a => [SmartRectangle a] -> [SmartRectangle a]+cleanup rs = foldr dropIfContained [] $ sortBy sizeOrder rs++sizeOrder :: Real a => SmartRectangle a -> SmartRectangle a -> Ordering+sizeOrder r1 r2 | w1 < w2 = LT+                | w1 == w2 && h1 < h2 = LT+                | w1 == w2 && h1 == h2 = EQ+                | otherwise = GT+                where w1 = width r1+                      w2 = width r2+                      h1 = height r1+                      h2 = height r2++dropIfContained :: Real a => SmartRectangle a+                -> [SmartRectangle a] -> [SmartRectangle a]+dropIfContained r rs  = if any (`contains` r) rs+                        then rs+                        else r:rs
+ XMonad/Hooks/RestoreMinimized.hs view
@@ -0,0 +1,49 @@+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Hooks.RestoreMinimized+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- Lets you restore minimized windows (see "XMonad.Layout.Minimize")+-- by selecting them on a taskbar (listens for _NET_ACTIVE_WINDOW+-- and WM_CHANGE_STATE).+--+-----------------------------------------------------------------------------++module XMonad.Hooks.RestoreMinimized+    ( -- * Usage+      -- $usage+      RestoreMinimized (..)+    , restoreMinimizedEventHook+    ) where++import Data.Monoid+import Control.Monad(when)++import XMonad+import XMonad.Layout.Minimize++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Hooks.RestoreMinimized+-- >+-- > myHandleEventHook = restoreMinimizedEventHook+-- >+-- > main = xmonad defaultConfig { handleEventHook = myHandleEventHook }++data RestoreMinimized = RestoreMinimized deriving ( Show, Read )++restoreMinimizedEventHook :: Event -> X All+restoreMinimizedEventHook (ClientMessageEvent {ev_window = w,+                                                ev_message_type = mt}) = do+    a_aw <- getAtom "_NET_ACTIVE_WINDOW"+    a_cs <- getAtom "WM_CHANGE_STATE"+    when (mt == a_aw || mt == a_cs) $ do+        sendMessage (RestoreMinimizedWin w)+    return (All True)+restoreMinimizedEventHook _ = return (All True)
XMonad/Hooks/Script.hs view
@@ -43,7 +43,7 @@ -- >   ... -- >   } ----- Now, everytime the startup hook runs, the command+-- Now, every time the startup hook runs, the command -- @~\/.xmonad\/hooks startup@ will also.  -- | Execute a named script hook
XMonad/Hooks/ServerMode.hs view
@@ -59,45 +59,48 @@     ( -- * Usage       -- $usage       ServerMode (..)-    , eventHook+    , serverModeEventHook+    , serverModeEventHook'     ) where  import Control.Monad (when) import Data.List+import Data.Monoid import System.IO  import XMonad import XMonad.Actions.Commands-import XMonad.Hooks.EventHook  -- $usage -- You can use this module with the following in your -- @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Hooks.ServerMode------ Then edit your @layoutHook@ by adding the 'eventHook':------ > layoutHook = eventHook ServerMode $ avoidStruts $ simpleTabbed ||| Full ||| etc..------ and then:+-- > import XMonad.Actions.Commands ----- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- Then edit your @handleEventHook@ by adding the 'serverModeEventHook': ----- For more detailed instructions on editing the layoutHook see:+-- > main = xmonad defaultConfig { handleEventHook = serverModeEventHook } ----- "XMonad.Doc.Extending#Editing_the_layout_hook"  data ServerMode = ServerMode deriving ( Show, Read ) -instance EventHook ServerMode where-    handleEvent _ (ClientMessageEvent {ev_message_type = mt, ev_data = dt}) = do+-- | Executes a command of the list when receiving its index via a special ClientMessageEvent+-- (indexing starts at 1)+serverModeEventHook :: Event -> X All+serverModeEventHook = serverModeEventHook' defaultCommands++-- | serverModeEventHook' additionally takes an action to generate the list of+-- commands.+serverModeEventHook' :: X [(String,X ())] -> Event -> X All+serverModeEventHook' cmdAction (ClientMessageEvent {ev_message_type = mt, ev_data = dt}) = do         d <- asks display         a <- io $ internAtom d "XMONAD_COMMAND" False         when (mt == a && dt /= []) $ do-             cl <- defaultCommands+             cl <- cmdAction              let listOfCommands = map (uncurry (++)) . zip (map show ([1..] :: [Int])) . map ((++) " - " . fst)              case lookup (fromIntegral (head dt) :: Int) (zip [1..] cl) of-                  Just (c,_) -> runCommand' c-                  Nothing    -> mapM_ (io . hPutStrLn stderr) . listOfCommands $ cl-    handleEvent _ _ = return ()+                  Just (_,action) -> action+                  Nothing         -> mapM_ (io . hPutStrLn stderr) . listOfCommands $ cl+        return (All True)+serverModeEventHook' _ _ = return (All True)
XMonad/Hooks/UrgencyHook.hs view
@@ -53,12 +53,13 @@                                  -- * Stuff for your config file:                                  withUrgencyHook, withUrgencyHookC,                                  UrgencyConfig(..), urgencyConfig,-                                 SuppressWhen(..),-                                 focusUrgent,+                                 SuppressWhen(..), RemindWhen(..),+                                 focusUrgent, clearUrgents,                                  dzenUrgencyHook,-                                 DzenUrgencyHook(..), seconds,+                                 DzenUrgencyHook(..),                                  NoUrgencyHook(..),                                  FocusHook(..),+                                 minutes, seconds,                                  -- * Stuff for developers:                                  readUrgents, withUrgents,                                  StdoutUrgencyHook(..),@@ -69,15 +70,15 @@ import XMonad import qualified XMonad.StackSet as W -import XMonad.Hooks.EventHook import XMonad.Util.Dzen (dzenWithArgs, seconds) import XMonad.Util.NamedWindows (getName)+import XMonad.Util.Timer (TimerId, startTimer, handleTimer)  import Control.Applicative ((<$>)) import Control.Monad (when) import Data.Bits (testBit) import Data.IORef-import Data.List ((\\), delete)+import Data.List (delete) import Data.Maybe (listToMaybe, maybeToList) import qualified Data.Set as S import Foreign (unsafePerformIO)@@ -137,7 +138,7 @@ --    two parts: -- --      * The console app must send a ^G (bell). In bash, a helpful trick is---        @sleep 1; echo -e \'\a\'@.+--        @sleep 1; echo -e \'\\a\'@. -- --      * The terminal must convert the bell into UrgencyHint. --@@ -193,36 +194,32 @@ -- Hopefully you already read the section on how to configure xmonad. If not, -- hopefully you know where to find it. --- | This is the method to enable an urgency hook. It suppresses urgency status--- for windows that are currently visible. If you'd like to change that behavior,--- use 'withUrgencyHookC'.+-- | This is the method to enable an urgency hook. It uses the default+-- 'urgencyConfig' to control behavior. To change this, use 'withUrgencyHook'+-- instead. withUrgencyHook :: (LayoutClass l Window, UrgencyHook h) =>-                   h -> XConfig l -> XConfig (HandleEvent (WithUrgencyHook h) l)+                   h -> XConfig l -> XConfig l withUrgencyHook hook conf = withUrgencyHookC hook urgencyConfig conf --- | If you'd like to configure *when* to trigger the urgency hook, call this--- function with a custom 'UrgencyConfig'. Or, by example:+-- | This lets you modify the defaults set in 'urgencyConfig'. An example: -- -- > withUrgencyHookC dzenUrgencyHook { ... } urgencyConfig { suppressWhen = Focused } ----- (Don't type the @...@, you dolt.) See documentation on your options at 'SuppressWhen'.+-- (Don't type the @...@, you dolt.) See 'UrgencyConfig' for details on configuration. withUrgencyHookC :: (LayoutClass l Window, UrgencyHook h) =>-                    h -> UrgencyConfig -> XConfig l -> XConfig (HandleEvent (WithUrgencyHook h) l)+                    h -> UrgencyConfig -> XConfig l -> XConfig l withUrgencyHookC hook urgConf conf = conf {-        layoutHook = eventHook (WithUrgencyHook hook urgConf) $ layoutHook conf,+        handleEventHook = \e -> handleEvent (WithUrgencyHook hook urgConf) e >> handleEventHook conf e,         logHook = cleanupUrgents (suppressWhen urgConf) >> logHook conf     } --- | Global configuration, applicable to all types of 'UrgencyHook'.+-- | Global configuration, applied to all types of 'UrgencyHook'. See+-- 'urgencyConfig' for the defaults. data UrgencyConfig = UrgencyConfig-    { suppressWhen :: SuppressWhen -- ^ see 'SuppressWhen' for options+    { suppressWhen :: SuppressWhen -- ^ when to trigger the urgency hook+    , remindWhen   :: RemindWhen   -- ^ when to re-trigger the urgency hook     } deriving (Read, Show) --- | The default 'UrgencyConfig'. Use a variation of this in your config just--- as you use a variation of defaultConfig for your xmonad definition.-urgencyConfig :: UrgencyConfig-urgencyConfig = UrgencyConfig { suppressWhen = Visible }- -- | A set of choices as to /when/ you should (or rather, shouldn't) be notified of an urgent window. -- The default is 'Visible'. Prefix each of the following with \"don't bug me when\": data SuppressWhen = Visible  -- ^ the window is currently visible@@ -231,13 +228,40 @@                   | Never    -- ^ ... aww, heck, go ahead and bug me, just in case.                   deriving (Read, Show) +-- | A set of choices as to when you want to be re-notified of an urgent+-- window. Perhaps you focused on something and you miss the dzen popup bar. Or+-- you're AFK. Or you feel the need to be more distracted. I don't care.+--+-- The interval arguments are in seconds. See the 'minutes' helper.+data RemindWhen = Dont                    -- ^ triggering once is enough+                | Repeatedly Int Interval -- ^ repeat <arg1> times every <arg2> seconds+                | Every Interval          -- ^ repeat every <arg1> until the urgency hint is cleared+                deriving (Read, Show)++-- | A prettified way of multiplying by 60. Use like: @(5 `minutes`)@.+minutes :: Rational -> Rational+minutes secs = secs * 60++-- | The default 'UrgencyConfig'. suppressWhen = Visible, remindWhen = Dont.+-- Use a variation of this in your config just as you use a variation of+-- defaultConfig for your xmonad definition.+urgencyConfig :: UrgencyConfig+urgencyConfig = UrgencyConfig { suppressWhen = Visible, remindWhen = Dont }+ -- | Focuses the most recently urgent window. Good for what ails ya -- I mean, your keybindings. -- Example keybinding: ----- > , ((modMask              , xK_BackSpace), focusUrgent)+-- > , ((modm              , xK_BackSpace), focusUrgent) focusUrgent :: X () focusUrgent = withUrgents $ flip whenJust (windows . W.focusWindow) . listToMaybe +-- | Just makes the urgents go away.+-- Example keybinding:+--+-- > , ((modm .|. shiftMask, xK_BackSpace), clearUrgents)+clearUrgents :: X ()+clearUrgents = adjustUrgents (const []) >> adjustReminders (const [])+ -- | Stores the global set of all urgent windows, across workspaces. Not exported -- use -- 'readUrgents' or 'withUrgents' instead. {-# NOINLINE urgents #-}@@ -255,8 +279,36 @@ withUrgents :: ([Window] -> X a) -> X a withUrgents f = readUrgents >>= f -data WithUrgencyHook h = WithUrgencyHook h UrgencyConfig deriving (Read, Show)+adjustUrgents :: ([Window] -> [Window]) -> X ()+adjustUrgents f = io $ modifyIORef urgents f +type Interval = Rational++-- | An urgency reminder, as reified for 'RemindWhen'.+-- The last value is the countdown number, for 'Repeatedly'.+data Reminder = Reminder { timer     :: TimerId+                         , window    :: Window+                         , interval  :: Interval+                         , remaining :: Maybe Int+                         } deriving Eq++-- | Stores the list of urgency reminders.+{-# NOINLINE reminders #-}+reminders :: IORef [Reminder]+reminders = unsafePerformIO (newIORef [])++readReminders :: X [Reminder]+readReminders = io $ readIORef reminders++adjustReminders :: ([Reminder] -> [Reminder]) -> X ()+adjustReminders f = io $ modifyIORef reminders f++clearUrgency :: Window -> X ()+clearUrgency w = adjustUrgents (delete w) >> adjustReminders (filter $ (w /=) . window)++data WithUrgencyHook h = WithUrgencyHook h UrgencyConfig+    deriving (Read, Show)+ -- The Non-ICCCM Manifesto: -- Note: Some non-standard choices have been made in this implementation to -- account for the fact that things are different in a tiling window manager:@@ -269,42 +321,55 @@ -- ourselves, allowing us to clear urgency when a window is visible, and not to -- set urgency if a window is visible. If you have a better idea, please, let us -- know!-instance UrgencyHook h => EventHook (WithUrgencyHook h) where-    handleEvent wuh event =-      case event of-        PropertyEvent { ev_event_type = t, ev_atom = a, ev_window = w } -> do+handleEvent :: UrgencyHook h => WithUrgencyHook h -> Event -> X ()+handleEvent wuh event =+    case event of+      PropertyEvent { ev_event_type = t, ev_atom = a, ev_window = w } -> do           when (t == propertyNotify && a == wM_HINTS) $ withDisplay $ \dpy -> do               WMHints { wmh_flags = flags } <- io $ getWMHints dpy w               if (testBit flags urgencyHintBit) then do-                  -- Add to list of urgents.                   adjustUrgents (\ws -> if elem w ws then ws else w : ws)-                  -- Call the urgencyHook.                   callUrgencyHook wuh w-                else do-                  -- Remove from list of urgents.-                  adjustUrgents (delete w)-              -- Call logHook after IORef has been modified.-              userCode =<< asks (logHook . config)-        DestroyWindowEvent {ev_window = w} -> do-          adjustUrgents (delete w)-        _ ->-          return ()--adjustUrgents :: ([Window] -> [Window]) -> X ()-adjustUrgents f = io $ modifyIORef urgents f+                else+                  clearUrgency w+              userCodeDef () =<< asks (logHook . config) -- call *after* IORef has been modified+      DestroyWindowEvent {ev_window = w} ->+          clearUrgency w+      _ ->+          mapM_ handleReminder =<< readReminders+      where handleReminder reminder = handleTimer (timer reminder) event $ reminderHook wuh reminder  callUrgencyHook :: UrgencyHook h => WithUrgencyHook h -> Window -> X ()-callUrgencyHook (WithUrgencyHook hook UrgencyConfig { suppressWhen = sw }) w =-    whenX (not <$> shouldSuppress sw w)-          (userCode $ urgencyHook hook w)+callUrgencyHook (WithUrgencyHook hook UrgencyConfig { suppressWhen = sw, remindWhen = rw }) w =+    whenX (not <$> shouldSuppress sw w) $ do+        userCodeDef () $ urgencyHook hook w+        case rw of+            Repeatedly times int -> addReminder w int $ Just times+            Every int            -> addReminder w int Nothing+            Dont                 -> return () +addReminder :: Window -> Rational -> Maybe Int -> X ()+addReminder w int times = do+    timerId <- startTimer int+    let reminder = Reminder timerId w int times+    adjustReminders (\rs -> if w `elem` map window rs then rs else reminder : rs)++reminderHook :: UrgencyHook h => WithUrgencyHook h -> Reminder -> X (Maybe a)+reminderHook (WithUrgencyHook hook _) reminder = do+    case remaining reminder of+        Just x | x > 0 -> remind $ Just (x - 1)+        Just _         -> adjustReminders $ delete reminder+        Nothing        -> remind Nothing+    return Nothing+  where remind remaining' = do userCode $ urgencyHook hook (window reminder)+                               adjustReminders $ delete reminder+                               addReminder (window reminder) (interval reminder) remaining'+ shouldSuppress :: SuppressWhen -> Window -> X Bool shouldSuppress sw w = elem w <$> suppressibleWindows sw  cleanupUrgents :: SuppressWhen -> X ()-cleanupUrgents sw = do-    suppressibles <- suppressibleWindows sw-    adjustUrgents (\\ suppressibles)+cleanupUrgents sw = mapM_ clearUrgency =<< suppressibleWindows sw  suppressibleWindows :: SuppressWhen -> X [Window] suppressibleWindows Visible  = gets $ S.toList . mapped
+ XMonad/Hooks/WorkspaceByPos.hs view
@@ -0,0 +1,54 @@+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Hooks.WorkspaceByPos+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- Useful in a dual-head setup: Looks at the requested geometry of+-- new windows and moves them to the workspace of the non-focused+-- screen if necessary.+--+-----------------------------------------------------------------------------++module XMonad.Hooks.WorkspaceByPos (+    -- * Usage+    -- $usage+    workspaceByPos+    ) where++import XMonad+import qualified XMonad.StackSet as W+import XMonad.Util.XUtils (fi)++import Data.Maybe+import Control.Applicative((<$>))+import Control.Monad.Error ((<=<),guard,lift,runErrorT,throwError)++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Hooks.WorkspaceByPos+-- >+-- > myManageHook = workspaceByPos <+> manageHook defaultConfig+-- >+-- > main = xmonad defaultConfig { manageHook = myManageHook }++workspaceByPos :: ManageHook+workspaceByPos = (maybe idHook doShift <=< liftX . needsMoving) =<< ask++needsMoving :: Window -> X (Maybe WorkspaceId)+needsMoving w = withDisplay $ \d -> do+    -- only relocate windows with non-zero position+    wa <- io $ getWindowAttributes d w+    fmap (const Nothing `either` Just) . runErrorT $ do+        guard $ wa_x wa /= 0 || wa_y wa /= 0+        ws <- gets windowset+        sc <- lift $ fromMaybe (W.current ws)+                <$> pointScreen (fi $ wa_x wa) (fi $ wa_y wa)+        Just wkspc <- lift $ screenWorkspace (W.screen sc)+        guard $ W.currentTag ws /= wkspc+        return wkspc `asTypeOf` throwError ""
XMonad/Hooks/XPropManage.hs view
@@ -34,7 +34,7 @@ -- > import XMonad.Actions.TagWindows -- > import Data.List ----- > manageHook = xPropManageHook xPropMatches +-- > manageHook = xPropManageHook xPropMatches -- > -- > xPropMatches :: [XPropMatch] -- > xPropMatches = [ ([ (wM_CLASS, any ("gimp"==))], (\w -> float w >> return (W.shift "2")))@@ -71,7 +71,7 @@     where       propToHook (ms, f) = fmap and (mapM mkQuery ms) --> mkHook f       mkQuery (a, tf)    = fmap tf (getQuery a)-      mkHook func        = ask >>= Query . lift . fmap Endo . func +      mkHook func        = ask >>= Query . lift . fmap Endo . func  getProp :: Display -> Window -> Atom -> X ([String]) getProp d w p = do
XMonad/Layout/Accordion.hs view
@@ -7,7 +7,7 @@ -- License     :  BSD -- -- Maintainer  :  glasser@mit.edu--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- LayoutClass that puts non-focused windows in ribbons at the top and bottom@@ -30,8 +30,8 @@ -- -- Then edit your @layoutHook@ by adding the Accordion layout: ----- > myLayouts = Accordion ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = Accordion ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
+ XMonad/Layout/AutoMaster.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances, FlexibleContexts #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.AutoMaster+-- Copyright   :  (c) 2009 Ilya Portnov+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Provides layout modifier AutoMaster. It separates screen in two parts -+-- master and slave. Size of slave area automatically changes depending on+-- number of slave windows.+--+-----------------------------------------------------------------------------++module XMonad.Layout.AutoMaster (+                             -- * Usage+                             -- $usage+                             autoMaster+                            ) where+import Control.Monad++import XMonad+import qualified XMonad.StackSet as W+import XMonad.Layout.LayoutModifier++-- $usage+-- This module defines layout modifier named autoMaster. It separates+-- screen in two parts - master and slave. Master windows are arranged+-- in one row, in slave area underlying layout is run. Size of slave area+-- automatically increases when number of slave windows is increasing.+--+-- You can use this module by adding folowing in your @xmonad.hs@:+--+-- > import XMonad.Layout.AutoMaster+--+-- Then add layouts to your layoutHook:+--+-- > myLayoutHook = autoMaster 1 (1/100) Grid ||| ...+--+-- In this example, master area by default contains 1 window (you can+-- change this number in runtime with usual IncMasterN message), changing+-- slave area size with 1/100 on each Shrink/Expand message.++-- | Data type for layout modifier+data AutoMaster a = AutoMaster Int Float Float+    deriving (Read,Show)++instance LayoutModifier AutoMaster Window where+    modifyLayout (AutoMaster k bias _) = autoLayout k bias+    pureMess = autoMess++-- | Handle Shrink/Expand and IncMasterN messages+autoMess :: AutoMaster a -> SomeMessage -> Maybe (AutoMaster a)+autoMess (AutoMaster k bias delta) m = msum [fmap resize (fromMessage m),+                                             fmap incmastern (fromMessage m)]+    where incmastern (IncMasterN d) = AutoMaster (max 1 (k+d)) bias delta+          resize Expand = AutoMaster k (min ( 0.4)  $ bias+delta) delta+          resize Shrink = AutoMaster k (max (-0.4)  $ bias-delta) delta++-- | Main layout function+autoLayout :: (LayoutClass l Window) =>+              Int ->+              Float ->+              W.Workspace WorkspaceId (l Window) Window+              -> Rectangle+              -> X ([(Window, Rectangle)], Maybe (l Window))+autoLayout k bias wksp rect = do+    let stack = W.stack wksp+    let ws = W.integrate' stack+    let n = length ws+    if null ws then+        runLayout wksp rect+        else do+          if (n<=k) then+              return ((divideRow rect ws),Nothing)+              else do+              let master = take k ws+              let filtStack = stack >>= W.filter (\w -> not (w `elem` master))+              wrs <- runLayout (wksp {W.stack = filtStack}) (slaveRect rect n bias)+              return ((divideRow (masterRect rect n bias) master) ++ (fst wrs),+                      snd wrs)++-- | Calculates height of master area, depending on number of windows.+masterHeight :: Int -> Float -> Float+masterHeight n bias = (calcHeight n) + bias+    where calcHeight :: Int -> Float+          calcHeight 1 = 1.0+          calcHeight m = if (m<9) then (43/45) - (fromIntegral m)*(7/90) else (1/3)++-- | Rectangle for master area+masterRect :: Rectangle -> Int -> Float -> Rectangle+masterRect (Rectangle sx sy sw sh) n bias = Rectangle sx sy sw h+    where h = round $ (fromIntegral sh)*(masterHeight n bias)++-- | Rectangle for slave area+slaveRect :: Rectangle -> Int -> Float -> Rectangle+slaveRect (Rectangle sx sy sw sh) n bias = Rectangle sx (sy+mh) sw h+    where mh = round $ (fromIntegral sh)*(masterHeight n bias)+          h  = round $ (fromIntegral sh)*(1-masterHeight n bias)++-- | Divide rectangle between windows+divideRow :: Rectangle -> [a] -> [(a, Rectangle)]+divideRow (Rectangle x y w h) ws = zip ws rects+    where n = length ws+          oneW = fromIntegral w `div` n+          oneRect = Rectangle x y (fromIntegral oneW) h+          rects = take n $ iterate (shiftR (fromIntegral oneW)) oneRect++-- | Shift rectangle right+shiftR :: Position -> Rectangle -> Rectangle+shiftR s (Rectangle x y w h) = Rectangle (x+s) y w h++-- | User interface function+autoMaster :: LayoutClass l a =>+              Int ->      -- Number of master windows+              Float ->    -- Step for which to increment/decrement master area size with Shrink/Expand+              l a ->+              ModifiedLayout AutoMaster l a+autoMaster nmaster delta = ModifiedLayout (AutoMaster nmaster 0 delta)+
+ XMonad/Layout/BorderResize.hs view
@@ -0,0 +1,164 @@+{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, PatternGuards #-}+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.BorderResize+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- This layout modifier will allow to resize windows by dragging their+-- borders with the mouse. However, it only works in layouts or modified+-- layouts that react to the 'SetGeometry' message.+-- "XMonad.Layout.WindowArranger" can be used to create such a setup.+-- BorderResize is probably most useful in floating layouts.+--+-----------------------------------------------------------------------------++module XMonad.Layout.BorderResize+    ( -- * Usage+      -- $usage+      borderResize+    , BorderResize (..)+    ) where++import XMonad+import XMonad.Layout.Decoration+import XMonad.Layout.WindowArranger+import XMonad.Util.XUtils+import Control.Monad(when,forM)+import Control.Arrow(first)+import Control.Applicative((<$>))++-- $usage+-- You can use this module with the following in your+-- @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.BorderResize+-- > myLayout = borderResize (... layout setup that reacts to SetGeometry ...)+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--++data BorderInfo = RightSideBorder Window Rectangle+                    | LeftSideBorder Window Rectangle+                    | TopSideBorder Window Rectangle+                    | BottomSideBorder Window Rectangle+                    deriving (Show, Read, Eq)+type BorderWithRect = (Rectangle, Rectangle, Glyph, BorderInfo)+type BorderWithWin = (Window, BorderInfo)++data BorderResize a = BR [BorderWithWin] deriving (Show, Read)++brBorderOffset :: Position+brBorderOffset = 5+brBorderSize :: Dimension+brBorderSize = 10++brCursorRightSide :: Glyph+brCursorRightSide = 96+brCursorLeftSide :: Glyph+brCursorLeftSide = 70+brCursorTopSide :: Glyph+brCursorTopSide = 138+brCursorBottomSide :: Glyph+brCursorBottomSide = 16++borderResize :: l a -> ModifiedLayout BorderResize l a+borderResize = ModifiedLayout (BR [])++instance LayoutModifier BorderResize Window where+    redoLayout _       _ Nothing  wrs = return (wrs, Nothing)+    redoLayout (BR borders) _ _ wrs = do+        let preparedBorders = for wrs $ \wr -> (wr, prepareBorders wr)+        mapM_ deleteBorder borders+        newBorders <- forM preparedBorders $ \(wr, (b1, b2, b3, b4)) ->+                        first (++[wr]) . unzip <$> mapM createBorder [b1,b2,b3,b4]+        let wrs' = concat $ map fst newBorders+            newBordersSerialized = concat $ map snd newBorders+        return (wrs', Just $ BR newBordersSerialized)+            -- What we return is the original wrs with the new border+            -- windows inserted at the correct positions - this way, the core+            -- will restack the borders correctly.+            -- We also return information about our borders, so that we+            -- can handle events that they receive and destroy them when+            -- they are no longer needed.++    handleMess (BR borders) m+        | Just e <- fromMessage m :: Maybe Event = handleResize borders e >> return Nothing+        | Just _ <- fromMessage m :: Maybe LayoutMessages =+            mapM_ deleteBorder borders >> return (Just $ BR [])+    handleMess _ _ = return Nothing++prepareBorders :: (Window, Rectangle) -> (BorderWithRect, BorderWithRect, BorderWithRect, BorderWithRect)+prepareBorders (w, r@(Rectangle x y wh ht)) =+    ((r, (Rectangle (x + fi wh - brBorderOffset) y brBorderSize ht) , brCursorRightSide     , RightSideBorder w r),+     (r, (Rectangle (x - brBorderOffset) y brBorderSize ht)         , brCursorLeftSide      , LeftSideBorder w r),+     (r, (Rectangle x (y - brBorderOffset) wh brBorderSize)         , brCursorTopSide       , TopSideBorder w r),+     (r, (Rectangle x (y + fi ht - brBorderOffset) wh brBorderSize) , brCursorBottomSide    , BottomSideBorder w r)+    )++handleResize :: [BorderWithWin] -> Event -> X ()+handleResize borders ButtonEvent { ev_window = ew, ev_event_type = et }+    | et == buttonPress, Just edge <- lookup ew borders =+    case edge of+        RightSideBorder hostWin (Rectangle hx hy _ hht) ->+            mouseDrag (\x _ -> do+                            let nwh = max 1 $ fi (x - hx)+                                rect = Rectangle hx hy nwh hht+                            focus hostWin+                            when (x - hx > 0) $ sendMessage (SetGeometry rect)) (focus hostWin)+        LeftSideBorder hostWin (Rectangle hx hy hwh hht) ->+            mouseDrag (\x _ -> do+                            let nx = max 0 $ min (hx + fi hwh) $ x+                                nwh = max 1 $ hwh + fi (hx - x)+                                rect = Rectangle nx hy nwh hht+                            focus hostWin+                            when (x < hx + fi hwh) $ sendMessage (SetGeometry rect)) (focus hostWin)+        TopSideBorder hostWin (Rectangle hx hy hwh hht) ->+            mouseDrag (\_ y -> do+                            let ny = max 0 $ min (hy + fi hht) $ y+                                nht = max 1 $ hht + fi (hy - y)+                                rect = Rectangle hx ny hwh nht+                            focus hostWin+                            when (y < hy + fi hht) $ sendMessage (SetGeometry rect)) (focus hostWin)+        BottomSideBorder hostWin (Rectangle hx hy hwh _) ->+            mouseDrag (\_ y -> do+                            let nht = max 1 $ fi (y - hy)+                                rect = Rectangle hx hy hwh nht+                            focus hostWin+                            when (y - hy > 0) $ sendMessage (SetGeometry rect)) (focus hostWin)+handleResize _ _ = return ()++createBorder :: BorderWithRect -> X (((Window, Rectangle), BorderWithWin))+createBorder (_, borderRect, borderCursor, borderInfo) = do+    borderWin <- createInputWindow borderCursor borderRect+    return ((borderWin, borderRect), (borderWin, borderInfo))++deleteBorder :: BorderWithWin -> X ()+deleteBorder (borderWin, _) = deleteWindow borderWin++createInputWindow :: Glyph -> Rectangle -> X Window+createInputWindow cursorGlyph r = withDisplay $ \d -> do+    win <- mkInputWindow d r+    io $ selectInput d win (exposureMask .|. buttonPressMask)+    cursor <- io $ createFontCursor d cursorGlyph+    io $ defineCursor d win cursor+    io $ freeCursor d cursor+    showWindow win+    return win++mkInputWindow :: Display -> Rectangle -> X Window+mkInputWindow d (Rectangle x y w h) = do+  rw <- asks theRoot+  let screen   = defaultScreenOfDisplay d+      visual   = defaultVisualOfScreen screen+      attrmask = cWOverrideRedirect+  io $ allocaSetWindowAttributes $+         \attributes -> do+           set_override_redirect attributes True+           createWindow d rw x y w h 0 0 inputOnly visual attrmask attributes++for :: [a] -> (a -> b) -> [b]+for = flip map
XMonad/Layout/BoringWindows.hs view
@@ -1,5 +1,5 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-+{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, DeriveDataTypeable #-}+{-# LANGUAGE PatternGuards, FlexibleContexts, FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.BoringWindows@@ -17,51 +17,122 @@ module XMonad.Layout.BoringWindows (                                    -- * Usage                                    -- $usage-                                   boringWindows,+                                   boringWindows, boringAuto,                                    markBoring, clearBoring,-                                   focusUp, focusDown+                                   focusUp, focusDown, focusMaster,++                                   UpdateBoring(UpdateBoring),+                                   BoringMessage(Replace,Merge),+                                   BoringWindows()                                   ) where -import XMonad hiding (Point)+import XMonad.Layout.LayoutModifier(ModifiedLayout(..),+                                    LayoutModifier(handleMessOrMaybeModifyIt, redoLayout))+import XMonad(Typeable, LayoutClass, Message, X, fromMessage,+              sendMessage, windows, withFocused, Window)+import Control.Applicative((<$>))+import Control.Monad(Monad(return, (>>)))+import Data.List((\\), union)+import Data.Maybe(Maybe(..), maybe, fromMaybe, listToMaybe,+                  maybeToList)+import qualified Data.Map as M import qualified XMonad.StackSet as W-import XMonad.Layout.LayoutModifier-import XMonad.Util.Invisible -data BoringMessage = FocusUp | FocusDown | IsBoring Window | ClearBoring-                       deriving ( Read, Show, Typeable )+-- $usage+-- You can use this module with the following in your+-- @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.BoringWindows+--+-- Then edit your @layoutHook@ by adding the layout modifier:+--+-- > myLayout = boringWindows (Full ||| etc..)+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- Then to your keybindings, add:+--+-- > , ((modm, xK_j), focusUp)+-- > , ((modm, xK_k), focusDown)+-- > , ((modm, xK_m), focusMaster)+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+++data BoringMessage = FocusUp | FocusDown | FocusMaster | IsBoring Window | ClearBoring+                     | Replace String [Window]+                     | Merge String [Window]+                     deriving ( Read, Show, Typeable )+ instance Message BoringMessage -markBoring, clearBoring, focusUp, focusDown :: X ()+-- | UpdateBoring is sent before attempting to view another boring window, so+-- that layouts have a chance to mark boring windows.+data UpdateBoring = UpdateBoring+    deriving (Typeable)+instance Message UpdateBoring++markBoring, clearBoring, focusUp, focusDown, focusMaster :: X () markBoring = withFocused (sendMessage . IsBoring) clearBoring = sendMessage ClearBoring-focusUp = sendMessage FocusUp-focusDown = sendMessage FocusDown+focusUp = sendMessage UpdateBoring >> sendMessage FocusUp+focusDown = sendMessage UpdateBoring >> sendMessage FocusDown+focusMaster = sendMessage UpdateBoring >> sendMessage FocusMaster -data BoringWindows a = BoringWindows (Invisible [] a) deriving ( Show, Read, Typeable )+data BoringWindows a = BoringWindows+    { namedBoring :: M.Map String [a] -- ^ store borings with a specific source+    , chosenBoring :: [a]             -- ^ user-chosen borings+    , hiddenBoring :: Maybe [a]       -- ^ maybe mark hidden windows+    } deriving (Show,Read,Typeable)  boringWindows :: (LayoutClass l a, Eq a) => l a -> ModifiedLayout BoringWindows l a-boringWindows = ModifiedLayout (BoringWindows (I []))+boringWindows = ModifiedLayout (BoringWindows M.empty [] Nothing) +-- | Mark windows that are not given rectangles as boring+boringAuto :: (LayoutClass l a, Eq a) => l a -> ModifiedLayout BoringWindows l a+boringAuto = ModifiedLayout (BoringWindows M.empty [] (Just []))+ instance LayoutModifier BoringWindows Window where-    handleMessOrMaybeModifyIt (BoringWindows (I bs)) m-        | Just (IsBoring b) <- fromMessage m = return $ Just $ Left $ BoringWindows (I (b:bs))-        | Just ClearBoring <- fromMessage m = return $ Just $ Left $ BoringWindows (I [])-        | Just FocusUp <- fromMessage m = do windows $ W.modify' $ focusUp'-                                             return Nothing+    redoLayout (b@BoringWindows { hiddenBoring = bs }) _r mst arrs = do+        let bs' = W.integrate' mst \\ map fst arrs+        return (arrs, Just $ b { hiddenBoring = const bs' <$> bs } )++    handleMessOrMaybeModifyIt bst@(BoringWindows nbs cbs lbs) m+        | Just (Replace k ws) <- fromMessage m+        , maybe True (ws/=) (M.lookup k nbs) =+            let nnb = if null ws then M.delete k nbs+                          else M.insert k ws nbs+            in rjl bst { namedBoring = nnb }+        | Just (Merge k ws) <- fromMessage m+        , maybe True (not . null . (ws \\)) (M.lookup k nbs) =+            rjl bst { namedBoring = M.insertWith union k ws nbs }+        | Just (IsBoring w) <- fromMessage m , w `notElem` cbs =+            rjl bst { chosenBoring = w:cbs }+        | Just ClearBoring <- fromMessage m, not (null cbs) =+            rjl bst { namedBoring = M.empty, chosenBoring = []}+        | Just FocusUp <- fromMessage m =+                            do windows $ W.modify' $ skipBoring W.focusUp'+                               return Nothing         | Just FocusDown <- fromMessage m =-                            do windows $ W.modify' (reverseStack . focusUp' . reverseStack)+                            do windows $ W.modify' $ skipBoring W.focusDown'                                return Nothing-        where focusUp' (W.Stack t ls rs)-                  | (a,l:ls') <- skipBoring ls = W.Stack l ls' (a++t:rs)-                  | otherwise = case skipBoring (reverse (t:rs)++ls) of-                                (a,x:xs) -> W.Stack x xs a-                                _ -> W.Stack t ls rs-              skipBoring [] = ([],[])-              skipBoring (x:xs) | x `elem` bs = case skipBoring xs of-                                                (a,b) -> (x:a,b)-                                | otherwise = ([],x:xs)+        | Just FocusMaster <- fromMessage m =+                            do windows $ W.modify'+                                            $ skipBoring W.focusDown' -- wiggle focus to make sure+                                            . skipBoring W.focusUp'   -- no boring window gets the focus+                                            . focusMaster'+                               return Nothing+        where skipBoring f st = fromMaybe st $ listToMaybe+                                $ filter ((`notElem` W.focus st:bs) . W.focus)+                                $ take (length $ W.integrate st)+                                $ iterate f st+              bs = concat $ cbs:maybeToList lbs ++ M.elems nbs+              rjl = return . Just . Left     handleMessOrMaybeModifyIt _ _ = return Nothing --- | reverse a stack: up becomes down and down becomes up.-reverseStack :: W.Stack a -> W.Stack a-reverseStack (W.Stack t ls rs) = W.Stack t rs ls+-- | Variant of 'focusMaster' that works on a+-- 'Stack' rather than an entire 'StackSet'.+focusMaster' :: W.Stack a -> W.Stack a+focusMaster' c@(W.Stack _ [] _) = c+focusMaster' (W.Stack t ls rs) = W.Stack x [] (xs ++ t : rs) where (x:xs) = reverse ls
+ XMonad/Layout/CenteredMaster.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.CenteredMaster+-- Copyright   :  (c) 2009 Ilya Portnov+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Two layout modifiers. centerMaster places master window at center,+-- on top of all other windows, which are managed by base layout.+-- topRightMaster is similar, but places master window in top right corner+-- instead of center.+--+-----------------------------------------------------------------------------++module XMonad.Layout.CenteredMaster (+         -- * Usage+         -- $usage++         centerMaster,+         topRightMaster+         ) where++import XMonad+import XMonad.Layout.LayoutModifier+import qualified XMonad.StackSet as W++-- $usage+-- This module defines two new layout modifiers: centerMaster and topRightMaster.+-- centerMaster places master window at center of screen, on top of others.+-- All other windows in background are managed by base layout.+-- topRightMaster is like centerMaster, but places master window in top right corner instead of center.+--+-- Yo can use this module by adding folowing in your @xmonad.hs@:+--+-- > import XMonad.Layout.CenteredMaster+--+-- Then add layouts to your layoutHook:+--+-- > myLayoutHook = centerMaster Grid ||| ...++-- | Function that decides where master window should be placed+type Positioner = Rectangle -> Rectangle++-- | Data type for LayoutModifier+data CenteredMaster a = CenteredMaster deriving (Read,Show)++instance LayoutModifier CenteredMaster Window where+  modifyLayout CenteredMaster = applyPosition (center (5/7) (5/7))++data TopRightMaster a = TopRightMaster deriving (Read,Show)++instance LayoutModifier TopRightMaster Window where+  modifyLayout TopRightMaster = applyPosition (topRight (3/7) (1/2))++-- | Modifier that puts master window in center, other windows in background+-- are managed by given layout+centerMaster :: LayoutClass l a => l a -> ModifiedLayout CenteredMaster l a+centerMaster = ModifiedLayout CenteredMaster++-- | Modifier that puts master window in top right corner, other windows in background+-- are managed by given layout+topRightMaster :: LayoutClass l a => l a -> ModifiedLayout TopRightMaster l a+topRightMaster = ModifiedLayout TopRightMaster++-- | Internal function, doing main job+applyPosition :: (LayoutClass l a, Eq a) =>+                    Positioner+                 -> W.Workspace WorkspaceId (l a) a+                 -> Rectangle+                 -> X ([(a, Rectangle)], Maybe (l a))++applyPosition pos wksp rect = do+  let stack = W.stack wksp+  let ws = W.integrate' $ stack+  if null ws then+     runLayout wksp rect+     else do+       let first = head ws+       let other = tail ws+       let filtStack = stack >>= W.filter (first /=)+       wrs <- runLayout (wksp {W.stack = filtStack}) rect+       return ((first, place pos other rect) : fst wrs, snd wrs)++-- | Place master window (it's Rectangle is given), using the given Positioner.+-- If second argument is empty (that is, there is only one window on workspace),+-- place that window fullscreen.+place :: Positioner -> [a] -> Rectangle -> Rectangle+place _ [] rect = rect+place pos _ rect = pos rect++-- | Function that calculates Rectangle at top right corner of given Rectangle+topRight :: Float -> Float -> Rectangle -> Rectangle+topRight rx ry (Rectangle sx sy sw sh) = Rectangle x sy w h+  where w = round (fromIntegral sw * rx)+        h = round (fromIntegral sh * ry)+        x = sx + fromIntegral (sw-w)++-- | Function that calculates Rectangle at center of given Rectangle.+center :: Float -> Float -> Rectangle -> Rectangle+center rx ry (Rectangle sx sy sw sh) = Rectangle x y w h+  where w = round (fromIntegral sw * rx)+        h = round (fromIntegral sh * ry)+        x = sx + fromIntegral (sw-w) `div` 2+        y = sy + fromIntegral (sh-h) `div` 2++
XMonad/Layout/Circle.hs view
@@ -31,8 +31,8 @@ -- -- Then edit your @layoutHook@ by adding the Circle layout: ----- > myLayouts = Circle ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = Circle ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
+ XMonad/Layout/Column.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.Column+-- Copyright   :  (c) 2009 Ilya Portnov+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Provides Column layout that places all windows in one column. Windows+-- heights are calculated from equation: H1/H2 = H2/H3 = ... = q, where q is+-- given. With Shrink/Expand messages you can change the q value.+--+-----------------------------------------------------------------------------++module XMonad.Layout.Column (+                             -- * Usage+                             -- $usage+                             Column (..)+                            ) where+import XMonad+import qualified XMonad.StackSet as W++-- $usage+-- This module defines layot named Column. It places all windows in one+-- column. Windows heights are calculated from equation: H1/H2 = H2/H3 = ... =+-- q, where `q' is given (thus, windows heights are members of geometric+-- progression). With Shrink/Expand messages one can change the `q' value.+--+-- You can use this module by adding folowing in your @xmonad.hs@:+--+-- > import XMonad.Layout.Column+--+-- Then add layouts to your layoutHook:+--+-- > myLayoutHook = Column 1.6 ||| ...+--+-- In this example, each next window will have height 1.6 times less then+-- previous window.++data Column a = Column Float deriving (Read,Show)++instance LayoutClass Column a where+    pureLayout = columnLayout+    pureMessage = columnMessage++columnMessage :: Column a -> SomeMessage -> Maybe (Column a)+columnMessage (Column q) m = fmap resize (fromMessage m)+    where resize Shrink = Column (q-0.1)+          resize Expand = Column (q+0.1)++columnLayout :: Column a -> Rectangle -> W.Stack a -> [(a,Rectangle)]+columnLayout (Column q) rect stack = zip ws rects+    where ws = W.integrate stack+          n = length ws+          heights = map (xn n rect q) [1..n]+          ys = [fromIntegral $ sum $ take k heights | k <- [0..n-1]]+          rects = map (mkRect rect) $ zip heights ys++mkRect :: Rectangle -> (Dimension,Position) -> Rectangle+mkRect (Rectangle xs ys ws _) (h,y) = Rectangle xs (ys+fromIntegral y) ws h+        +xn :: Int -> Rectangle -> Float -> Int -> Dimension+xn n (Rectangle _ _ _ h) q k = if q==1 then +                                  h `div` (fromIntegral n)+                               else+                                  round ((fromIntegral h)*q^(n-k)*(1-q)/(1-q^n))++
XMonad/Layout/Combo.hs view
@@ -25,7 +25,7 @@ import Data.List ( delete, intersect, (\\) ) import Data.Maybe ( isJust ) import XMonad hiding (focus)-import XMonad.StackSet ( integrate, Workspace (..), Stack(..) )+import XMonad.StackSet ( integrate', Workspace (..), Stack(..) ) import XMonad.Layout.WindowNavigation ( MoveWindowToWindow(..) ) import qualified XMonad.StackSet as W ( differentiate ) @@ -51,10 +51,10 @@ -- each sublayout. To do this, use "XMonad.Layout.WindowNavigation", -- and add the following key bindings (or something similar): ----- >    , ((modMask x .|. controlMask .|. shiftMask, xK_Right), sendMessage $ Move R)--- >    , ((modMask x .|. controlMask .|. shiftMask, xK_Left ), sendMessage $ Move L)--- >    , ((modMask x .|. controlMask .|. shiftMask, xK_Up   ), sendMessage $ Move U)--- >    , ((modMask x .|. controlMask .|. shiftMask, xK_Down ), sendMessage $ Move D)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Right), sendMessage $ Move R)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Left ), sendMessage $ Move L)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Up   ), sendMessage $ Move U)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Down ), sendMessage $ Move D) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -76,7 +76,7 @@  instance (LayoutClass l (), LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a)     => LayoutClass (CombineTwo (l ()) l1 l2) a where-    doLayout (C2 f w2 super l1 l2) rinput s = arrange (integrate s)+    runLayout (Workspace _ (C2 f w2 super l1 l2) s) rinput = arrange (integrate' s)         where arrange [] = do l1' <- maybe l1 id `fmap` handleMessage l1 (SomeMessage ReleaseResources)                               l2' <- maybe l2 id `fmap` handleMessage l2 (SomeMessage ReleaseResources)                               super' <- maybe super id `fmap`@@ -93,12 +93,11 @@                                                              x -> case origws \\ x of                                                                   [] -> init x                                                                   _ -> x-                         superstack = if focus s `elem` w2'-                                      then Stack { focus=(), up=[], down=[()] }-                                      else Stack { focus=(), up=[], down=[()] }+                         superstack = Stack { focus=(), up=[], down=[()] }                          s1 = differentiate f' (origws \\ w2')                          s2 = differentiate f' w2'-                         f' = focus s:delete (focus s) f+                         f' = case s of (Just s') -> focus s':delete (focus s') f+                                        Nothing -> f                      ([((),r1),((),r2)], msuper') <- runLayout (Workspace "" super (Just superstack)) rinput                      (wrs1, ml1') <- runLayout (Workspace "" l1 s1) r1                      (wrs2, ml2') <- runLayout (Workspace "" l2 s2) r2
+ XMonad/Layout/ComboP.hs view
@@ -0,0 +1,180 @@+{-# LANGUAGE TypeSynonymInstances, DeriveDataTypeable, MultiParamTypeClasses, FlexibleContexts, FlexibleInstances, PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.ComboP+-- Copyright   :  (c) Konstantin Sobolev <konstantin.sobolev@gmail.com>+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Konstantin Sobolev <konstantin.sobolev@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A layout that combines multiple layouts and allows to specify where to put+-- new windows.+--+-----------------------------------------------------------------------------++module XMonad.Layout.ComboP (+                             -- * Usage+                             -- $usage+                             combineTwoP,+                             CombineTwoP,+                             SwapWindow(..),+                             Property(..)+                            ) where++import Data.List ( delete, intersect, (\\) )+import Data.Maybe ( isJust )+import Control.Monad+import XMonad hiding (focus)+import XMonad.StackSet ( integrate, Workspace (..), Stack(..) )+import XMonad.Layout.WindowNavigation+import XMonad.Util.WindowProperties+import qualified XMonad.StackSet as W++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.ComboP+--+-- and add something like+--+-- > combineTwoP (TwoPane 0.03 0.5) (tabbed shrinkText defaultTConf) (tabbed shrinkText defaultTConf) (ClassName "Firefox")+--+-- to your layouts. This way all windows with class = \"Firefox\" will always go+-- to the left pane, all others - to the right.+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+--+-- 'combineTwoP' is a simple layout combinator based on 'combineTwo' from Combo, with+-- addition of a 'Property' which tells where to put new windows. Windows mathing+-- the property will go into the first part, all others will go into the second+-- part. It supports @Move@ messages as 'combineTwo' does, but it also introduces+-- 'SwapWindow' message which sends focused window to the other part. It is+-- required because @Move@ commands don't work when one of the parts is empty.+-- To use it, import \"XMonad.Layout.WindowNavigation\", and add the following key+-- bindings (or something similar):+--+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Right), sendMessage $ Move R)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Left ), sendMessage $ Move L)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Up   ), sendMessage $ Move U)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_Down ), sendMessage $ Move D)+-- >    , ((modm .|. controlMask .|. shiftMask, xK_s    ), sendMessage $ SwapWindow)+--+-- For detailed instruction on editing the key binding see+-- "XMonad.Doc.Extending#Editing_key_bindings".++data SwapWindow =  SwapWindow        -- ^ Swap window between panes+                 | SwapWindowN Int   -- ^ Swap window between panes in the N-th nested ComboP. @SwapWindowN 0@ equals to SwapWindow+                 deriving (Read, Show, Typeable)+instance Message SwapWindow++data CombineTwoP l l1 l2 a = C2P [a] [a] [a] l (l1 a) (l2 a) Property+                                deriving (Read, Show)++combineTwoP :: (LayoutClass super(), LayoutClass l1 Window, LayoutClass l2 Window) =>+                super () -> l1 Window -> l2 Window -> Property -> CombineTwoP (super ()) l1 l2 Window+combineTwoP = C2P [] [] []++instance (LayoutClass l (), LayoutClass l1 Window, LayoutClass l2 Window) =>+    LayoutClass (CombineTwoP (l ()) l1 l2) Window where+    doLayout (C2P f w1 w2 super l1 l2 prop) rinput s =+        let origws = W.integrate s           -- passed in windows+            w1c = origws `intersect` w1      -- current windows in the first pane+            w2c = origws `intersect` w2      -- current windows in the second pane+            new = origws \\ (w1c ++ w2c)     -- new windows+            superstack = Just Stack { focus=(), up=[], down=[()] }+            f' = focus s:delete (focus s) f  -- list of focused windows, contains 2 elements at most+        in do+            matching <- (hasProperty prop) `filterM` new  -- new windows matching predecate+            let w1' = w1c ++ matching                     -- updated first pane windows+                w2' = w2c ++ (new \\ matching)            -- updated second pane windows+                s1 = differentiate f' w1'                 -- first pane stack+                s2 = differentiate f' w2'                 -- second pane stack+            ([((),r1),((),r2)], msuper') <- runLayout (Workspace "" super superstack) rinput+            (wrs1, ml1') <- runLayout (Workspace "" l1 s1) r1+            (wrs2, ml2') <- runLayout (Workspace "" l2 s2) r2+            return  (wrs1++wrs2, Just $ C2P f' w1' w2' (maybe super id msuper')+                (maybe l1 id ml1') (maybe l2 id ml2') prop)++    handleMessage us@(C2P f ws1 ws2 super l1 l2 prop) m+        | Just SwapWindow      <- fromMessage m = swap us+        | Just (SwapWindowN 0) <- fromMessage m = swap us+        | Just (SwapWindowN n) <- fromMessage m = forwardToFocused us $ SomeMessage $ SwapWindowN $ n-1++        | Just (MoveWindowToWindow w1 w2) <- fromMessage m,+          w1 `elem` ws1,+          w2 `elem` ws2 = return $ Just $ C2P f (delete w1 ws1) (w1:ws2) super l1 l2 prop++        | Just (MoveWindowToWindow w1 w2) <- fromMessage m,+          w1 `elem` ws2,+          w2 `elem` ws1 = return $ Just $ C2P f (w1:ws1) (delete w1 ws2) super l1 l2 prop++        | otherwise = do ml1' <- handleMessage l1 m+                         ml2' <- handleMessage l2 m+                         msuper' <- handleMessage super m+                         if isJust msuper' || isJust ml1' || isJust ml2'+                            then return $ Just $ C2P f ws1 ws2+                                                 (maybe super id msuper')+                                                 (maybe l1 id ml1')+                                                 (maybe l2 id ml2') prop+                            else return Nothing++    description (C2P _ _ _ super l1 l2 prop) = "combining " ++ description l1 ++ " and "+++                                description l2 ++ " with " ++ description super ++ " using "++ (show prop)++-- send focused window to the other pane. Does nothing if we don't+-- own the focused window+swap :: (LayoutClass s a, LayoutClass l1 Window, LayoutClass l2 Window) =>+        CombineTwoP (s a) l1 l2 Window -> X (Maybe (CombineTwoP (s a) l1 l2 Window))+swap (C2P f ws1 ws2 super l1 l2 prop) = do+    mst <- gets (W.stack . W.workspace . W.current . windowset)+    let (ws1', ws2') = case mst of+            Nothing -> (ws1, ws2)+            Just st -> if foc `elem` ws1+                           then (foc `delete` ws1, foc:ws2)+                           else if foc `elem` ws2+                               then (foc:ws1, foc `delete` ws2)+                               else (ws1, ws2)+                       where foc = W.focus st+    if (ws1,ws2) == (ws1',ws2')+        then return Nothing+        else return $ Just $ C2P f ws1' ws2' super l1 l2 prop+++-- forwards the message to the sublayout which contains the focused window+forwardToFocused :: (LayoutClass l1 Window, LayoutClass l2 Window, LayoutClass s a) =>+                    CombineTwoP (s a) l1 l2 Window -> SomeMessage -> X (Maybe (CombineTwoP (s a) l1 l2 Window))+forwardToFocused (C2P f ws1 ws2 super l1 l2 prop) m = do+    ml1 <- forwardIfFocused l1 ws1 m+    ml2 <- forwardIfFocused l2 ws2 m+    ms <- if isJust ml1 || isJust ml2+            then return Nothing+            else handleMessage super m+    if isJust ml1 || isJust ml2 || isJust ms+        then return $ Just $ C2P f ws1 ws2 (maybe super id ms) (maybe l1 id ml1) (maybe l2 id ml2) prop+        else return Nothing++-- forwards message m to layout l if focused window is among w+forwardIfFocused :: (LayoutClass l Window) => l Window -> [Window] -> SomeMessage -> X (Maybe (l Window))+forwardIfFocused l w m = do+    mst <- gets (W.stack . W.workspace . W.current . windowset)+    maybe (return Nothing) send mst where+    send st = if (W.focus st) `elem` w+                then handleMessage l m+                else return Nothing++-- code from CombineTwo+-- given two sets of zs and xs takes the first z from zs that also belongs to xs+-- and turns xs into a stack with z being current element. Acts as+-- StackSet.differentiate if zs and xs don't intersect+differentiate :: Eq q => [q] -> [q] -> Maybe (Stack q)+differentiate (z:zs) xs | z `elem` xs = Just $ Stack { focus=z+                                                     , up = reverse $ takeWhile (/=z) xs+                                                     , down = tail $ dropWhile (/=z) xs }+                        | otherwise = differentiate zs xs+differentiate [] xs = W.differentiate xs++-- vim:ts=4:shiftwidth=4:softtabstop=4:expandtab:foldlevel=20:
+ XMonad/Layout/Cross.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}++-- |+-- Module      :  XMonad.Layout.Cross+-- Copyright   :  (c) Luis Cabellos <zhen.sydow@gmail.com>+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Luis Cabellos <zhen.sydow@gmail.com>+-- Stability   :  stable+-- Portability :  portable+--+-- A Cross Layout with the main window in the center.+--+module XMonad.Layout.Cross(+                          -- * Usage+                          -- $usage+                          simpleCross+                          , Cross(..) ) where++import XMonad( Dimension, Rectangle(..), LayoutClass(..), Resize(..), fromMessage )+import XMonad.StackSet( focus, up, down )+import Control.Monad( msum )++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.Cross+--+-- Then edit your @layoutHook@ by adding one of the Cross layouts:+--+-- > myLayout =  simpleCross ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--++-- apply a factor to a Rectangle Dimension+(<%>) :: Dimension -> Rational -> Dimension+d <%> f = floor $ f * (fromIntegral d)++-- | The Cross Layout draws the focused window in the center of the screen+--   and part of the other windows on the sides. The 'Shrink' and 'Expand'+--   messages increment the size of the main window.+--+--   The focus keybindings change the center window, while other windows+--   cycle through the side positions. With the Cross layout only four+--   windows are shown around the focused window, two ups and two downs,+--   no matter how many are in the current stack. I.e. focus down cycles the+--   window below focused into the center; focus up cycles the window above.+data Cross a = Cross {+      crossProp :: !Rational, -- ^ Proportion of screen occupied by the main window.+      crossInc  :: !Rational  -- ^ Percent of main window to increment by when resizing.+    }+    deriving( Show, Read )++-- | A simple Cross Layout. It places the focused window in the center.+--   The proportion of the screen used by the main window is 4\/5.+simpleCross :: Cross a+simpleCross = Cross (4/5) (1/100)++instance LayoutClass Cross a where+    pureLayout (Cross f _) r s = [(focus s, mainRect r f)] +++                                 (zip winCycle (upRects r f)) +++                                 (zip (reverse winCycle) (downRects r f))+        where winCycle = (up s) ++ (reverse (down s))++    pureMessage (Cross f d) m = msum [fmap resize (fromMessage m)]+        where resize Shrink = Cross (max (1/100) $ f - d) d+              resize Expand = Cross (min 1 $ f + d) d++    description _ = "Cross"++-- get the Rectangle for the focused window+mainRect :: Rectangle -> Rational -> Rectangle+mainRect (Rectangle rx ry rw rh) f = Rectangle+                                     (rx + (fromIntegral (rw <%> invf)))+                                     (ry + (fromIntegral (rh <%> invf)))+                                     (rw <%> f) (rh <%> f)+    where invf = (1/2) * (1-f)++-- get the rectangles for the up windows+upRects :: Rectangle -> Rational -> [Rectangle]+upRects r f = [topRectangle r nf, rightRectangle r nf]+    where nf = f * (8/10)++-- get the rectangles for the down windows+downRects :: Rectangle -> Rational -> [Rectangle]+downRects r f = [bottomRectangle r nf, leftRectangle r nf]+    where nf = f * (8/10)++topRectangle :: Rectangle -> Rational -> Rectangle+topRectangle (Rectangle rx ry rw rh) f = Rectangle+                                         (rx + (fromIntegral (rw <%> ((1-f)*(1/2)))))+                                         ry+                                         (rw <%> f) (rh <%> ((1-f)*(1/2)))++rightRectangle :: Rectangle -> Rational -> Rectangle+rightRectangle (Rectangle rx ry rw rh) f = Rectangle+                                           (rx + (fromIntegral (rw - (rw <%> (1/2)))))+                                           (ry + (fromIntegral (rh <%> ((1-f)*(1/2)))))+                                           (rw <%> (1/2)) (rh <%> f)++bottomRectangle :: Rectangle -> Rational -> Rectangle+bottomRectangle (Rectangle rx ry rw rh) f = Rectangle+                                            (rx + (fromIntegral (rw <%> ((1-f)*(1/2)))))+                                            (ry + (fromIntegral (rh - (rh <%> ((1-f)*(1/2))))))+                                            (rw <%> f) (rh <%> ((1-f)*(1/2)))++leftRectangle :: Rectangle -> Rational -> Rectangle+leftRectangle (Rectangle rx ry rw rh) f = Rectangle+                                          rx+                                           (ry + (fromIntegral (rh <%> ((1-f)*(1/2)))))+                                           (rw <%> (1/2)) (rh <%> f)+
XMonad/Layout/Decoration.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- for deriving Typeable-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-} ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.Decoration@@ -24,8 +23,9 @@     , DecorationStyle (..)     , DefaultDecoration (..)     , Shrinker (..), DefaultShrinker-    , shrinkText, CustomShrink ( CustomShrink )+    , shrinkText, CustomShrink ( CustomShrink ), shrinkWhile     , isInStack, isVisible, isInvisible, isWithin, fi+    , findWindowByDecoration     , module XMonad.Layout.LayoutModifier     ) where @@ -201,7 +201,12 @@ -- 'handleEvent', which will call the appropriate 'DecorationStyle' -- methods to perform its tasks. instance (DecorationStyle ds Window, Shrinker s) => LayoutModifier (Decoration ds s) Window where-    redoLayout (Decoration st sh t ds) sc stack wrs+    redoLayout (Decoration (I (Just s)) sh t ds) _ Nothing _ = do+        releaseResources s+        return ([], Just $ Decoration (I Nothing) sh t ds)+    redoLayout _                                 _ Nothing _  = return ([], Nothing)++    redoLayout (Decoration st sh t ds) sc (Just stack) wrs         | I Nothing  <- st = initState t ds sc stack wrs >>= processState         | I (Just s) <- st = do let dwrs  = decos s                                     (d,a) = curry diff (get_ws dwrs) ws@@ -264,11 +269,6 @@                                                       return $ Just $ Decoration (I Nothing) sh t  ds     handleMess _ _ = return Nothing -    emptyLayoutMod (Decoration (I (Just s)) sh t ds) _ _ = do-        releaseResources s-        return ([], Just $ Decoration (I Nothing) sh t ds)-    emptyLayoutMod _ _ _  = return ([], Nothing)-     modifierDescription (Decoration _ _ _ ds) = describeDeco ds  -- | By default 'Decoration' handles 'PropertyEvent' and 'ExposeEvent'@@ -306,6 +306,9 @@                                    | otherwise = lookFor w dwrs lookFor w ((_, (Nothing, _)):dwrs) = lookFor w dwrs lookFor _ [] = Nothing++findWindowByDecoration :: Window -> DecorationState -> Maybe (OrigWin,(Window,Maybe Rectangle))+findWindowByDecoration w ds = lookFor w (decos ds)  -- | Initialize the 'DecorationState' by initializing the font -- structure and by creating the needed decorations.
XMonad/Layout/DecorationMadness.hs view
@@ -127,8 +127,8 @@ -- up the key bindings, please read the documentation of -- "XMonad.Layout.WindowArranger" ----- The deafult theme can be dynamically change with the xmonad theme--- selector. See "XMonad.Prompt.Theme". For more themse, look at+-- The default theme can be dynamically change with the xmonad theme+-- selector. See "XMonad.Prompt.Theme". For more themes, look at -- "XMonad.Util.Themes"  -- $circle@@ -541,12 +541,12 @@ -- -- <http://code.haskell.org/~arossato/xmonadShots/floatSimpleSimple.png> floatSimpleSimple :: (Show a, Eq a) => ModifiedLayout (Decoration SimpleDecoration DefaultShrinker)-	             (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+                 (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatSimpleSimple = simpleFloat  floatSimple :: (Show a, Eq a, Shrinker s) => s -> Theme ->                ModifiedLayout (Decoration SimpleDecoration s)-	      (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+          (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatSimple = simpleFloat'  -- | This version is decorated with the 'DefaultDecoration' style.@@ -555,14 +555,14 @@ -- -- <http://code.haskell.org/~arossato/xmonadShots/floatSimpleDefault.png> floatSimpleDefault :: (Show a, Eq a) => ModifiedLayout (Decoration DefaultDecoration DefaultShrinker)-	              (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+                  (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatSimpleDefault = decoration shrinkText defaultTheme DefaultDecoration (mouseResize $ windowArrangeAll $ SF 20)  -- | Same as 'floatSimpleDefault', but with the possibility of setting a -- custom shrinker and a custom theme. floatDefault :: (Show a, Eq a, Shrinker s) => s -> Theme ->                 ModifiedLayout (Decoration DefaultDecoration s)-	       (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+           (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatDefault s t = decoration s t DefaultDecoration (mouseResize $ windowArrangeAll $ SF (decoHeight t))  -- | This version is decorated with the 'DwmStyle'. Note that this is@@ -572,14 +572,14 @@ -- -- <http://code.haskell.org/~arossato/xmonadShots/floatSimpleDwmStyle.png> floatSimpleDwmStyle :: (Show a, Eq a) => ModifiedLayout (Decoration DwmStyle DefaultShrinker)-	               (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+                   (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatSimpleDwmStyle = decoration shrinkText defaultTheme Dwm (mouseResize $ windowArrangeAll $ SF 20)  -- | Same as 'floatSimpleDwmStyle', but with the possibility of setting a -- custom shrinker and a custom theme. floatDwmStyle :: (Show a, Eq a, Shrinker s) => s -> Theme ->                  ModifiedLayout (Decoration DwmStyle s)-	        (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+            (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatDwmStyle s t = decoration s t Dwm (mouseResize $ windowArrangeAll $ SF (decoHeight t))  -- | This version is decorated with the 'TabbedDecoration' style.@@ -589,12 +589,12 @@ -- -- <http://code.haskell.org/~arossato/xmonadShots/floatSimpleTabbed.png> floatSimpleTabbed :: (Show a, Eq a) => ModifiedLayout (Decoration TabBarDecoration DefaultShrinker)-	             (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+                 (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatSimpleTabbed = tabBar shrinkText defaultTheme Top (mouseResize $ windowArrangeAll $ SF 20)  -- | Same as 'floatSimpleTabbed', but with the possibility of setting a -- custom shrinker and a custom theme. floatTabbed :: (Show a, Eq a, Shrinker s) => s -> Theme ->                ModifiedLayout (Decoration TabBarDecoration s)-	      (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a+          (ModifiedLayout MouseResize (ModifiedLayout WindowArranger SimpleFloat)) a floatTabbed s t = tabBar s t Top (mouseResize $ windowArrangeAll $ SF (decoHeight t))
XMonad/Layout/Dishes.hs view
@@ -33,8 +33,8 @@ -- -- Then edit your @layoutHook@ by adding the Dishes layout: ----- > myLayouts = Dishes 2 (1/6) ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = Dishes 2 (1/6) ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
XMonad/Layout/DragPane.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}  ----------------------------------------------------------------------------- -- |@@ -8,7 +7,7 @@ --                    David Roundy <droundy@darcs.net>, --                    Andrea Rossato <andrea.rossato@unibz.it> -- License     :  BSD3-style (see LICENSE)--- +-- -- Maintainer  :  Andrea Rossato <andrea.rossato@unibz.it> -- Stability   :  unstable -- Portability :  unportable@@ -30,7 +29,7 @@ import XMonad import Data.Unique -import qualified XMonad.StackSet as W +import qualified XMonad.StackSet as W import XMonad.Util.Invisible import XMonad.Util.XUtils @@ -41,8 +40,8 @@ -- -- Then edit your @layoutHook@ by adding the DragPane layout: ----- > myLayouts = dragPane Horizontal 0.1 0.5 ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = dragPane Horizontal 0.1 0.5 ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -57,8 +56,8 @@ dragPane :: DragType -> Double -> Double -> DragPane a dragPane t x y = DragPane (I Nothing) t x y -data DragPane a = -    DragPane (Invisible Maybe (Window,Rectangle,Int)) DragType Double Double +data DragPane a =+    DragPane (Invisible Maybe (Window,Rectangle,Int)) DragType Double Double              deriving ( Show, Read )  data DragType = Horizontal | Vertical deriving ( Show, Read )@@ -87,7 +86,7 @@ handleMess _ _ = return Nothing  handleEvent :: DragPane a -> Event -> X ()-handleEvent (DragPane (I (Just (win,r,ident))) ty _ _) +handleEvent (DragPane (I (Just (win,r,ident))) ty _ _)             (ButtonEvent {ev_window = thisw, ev_subwindow = thisbw, ev_event_type = t })     | t == buttonPress && thisw == win || thisbw == win  = do   mouseDrag (\ex ey -> do@@ -115,12 +114,12 @@               [] -> case W.down s of                       (next:_) -> [(W.focus s,left),(next,right)]                       [] -> [(W.focus s, r)]-  if length wrs > 1 +  if length wrs > 1      then case mw of-            I (Just (w,_,ident)) -> do +            I (Just (w,_,ident)) -> do                     w' <- deleteWindow w >> newDragWin handr                     return (wrs, Just $ DragPane (I $ Just (w',r',ident)) ty delta split)-            I Nothing -> do +            I Nothing -> do                     w <- newDragWin handr                     i <- io $ newUnique                     return (wrs, Just $ DragPane (I $ Just (w,r',hashUnique i)) ty delta split)
+ XMonad/Layout/FixedColumn.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.FixedColumn+-- Copyright   :  (c) 2008 Justin Bogner <mail@justinbogner.com>+-- License     :  BSD3-style (as xmonad)+--+-- Maintainer  :  Justin Bogner <mail@justinbogner.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A layout much like Tall, but using a multiple of a window's minimum+-- resize amount instead of a percentage of screen to decide where to+-- split. This is useful when you usually leave a text editor or+-- terminal in the master pane and like it to be 80 columns wide.+--+-----------------------------------------------------------------------------++module XMonad.Layout.FixedColumn (+    -- * Usage+    -- $usage+        FixedColumn(..)+) where++import Control.Monad (msum)+import Data.Maybe (fromMaybe)+import Graphics.X11.Xlib (Window, rect_width)+import Graphics.X11.Xlib.Extras ( getWMNormalHints+                                , getWindowAttributes+                                , sh_base_size+                                , sh_resize_inc+                                , wa_border_width)++import XMonad.Core (X, LayoutClass(..), fromMessage, io, withDisplay)+import XMonad.Layout (Resize(..), IncMasterN(..), tile)+import XMonad.StackSet as W++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.FixedColumn+--+-- Then edit your @layoutHook@ by adding the FixedColumn layout:+--+-- > myLayout = FixedColumn 1 20 80 10 ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"++-- | A tiling mode based on preserving a nice fixed width+--   window. Supports 'Shrink', 'Expand' and 'IncMasterN'.+data FixedColumn a = FixedColumn !Int -- Number of windows in the master pane+                                 !Int -- Number to increment by when resizing+                                 !Int -- Default width of master pane+                                 !Int -- Column width for normal windows+                        deriving (Read, Show)++instance LayoutClass FixedColumn Window where+    doLayout (FixedColumn nmaster _ ncol fallback) r s = do+            fws <- mapM (widthCols fallback ncol) ws+            let frac = maximum (take nmaster fws) // rect_width r+                rs   = tile frac r nmaster (length ws)+            return $ (zip ws rs, Nothing)+        where ws     = W.integrate s+              x // y = fromIntegral x / fromIntegral y++    pureMessage (FixedColumn nmaster delta ncol fallback) m =+            msum [fmap resize     (fromMessage m)+                 ,fmap incmastern (fromMessage m)]+        where resize Shrink+                  = FixedColumn nmaster delta (max 0 $ ncol - delta) fallback+              resize Expand+                  = FixedColumn nmaster delta (ncol + delta) fallback+              incmastern (IncMasterN d)+                  = FixedColumn (max 0 (nmaster+d)) delta ncol fallback++    description _ = "FixedColumn"++-- | Determine the width of @w@ given that we would like it to be @n@+--   columns wide, using @inc@ as a resize increment for windows that+--   don't have one+widthCols :: Int -> Int -> Window -> X Int+widthCols inc n w = withDisplay $ \d -> io $ do+    sh <- getWMNormalHints d w+    bw <- fmap (fromIntegral . wa_border_width) $ getWindowAttributes d w+    let widthHint f = f sh >>= return . fromIntegral . fst+        oneCol      = fromMaybe inc $ widthHint sh_resize_inc+        base        = fromMaybe 0 $ widthHint sh_base_size+    return $ 2 * bw + base + n * oneCol
XMonad/Layout/Gaps.hs view
@@ -1,8 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}---- for now, use -fglasgow-exts for compatibility with ghc 6.6, which chokes--- on some of the LANGUAGE pragmas below-{- LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, TypeSynonymInstances -}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, TypeSynonymInstances, PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -32,7 +28,7 @@ module XMonad.Layout.Gaps (                                -- * Usage                                -- $usage-                          Direction(..),+                          Direction2D(..),                           GapSpec, gaps, GapMessage(..)                            ) where@@ -40,8 +36,8 @@ import XMonad.Core import Graphics.X11 (Rectangle(..)) -import XMonad.Hooks.ManageDocks (Direction(..)) import XMonad.Layout.LayoutModifier+import XMonad.Util.Types (Direction2D(..))  import Data.List (delete) @@ -58,10 +54,10 @@ -- You can additionally add some keybindings to toggle or modify the gaps, -- for example: ----- > , ((modMask x .|. controlMask, xK_g), sendMessage $ ToggleGaps)  -- toggle all gaps--- > , ((modMask x .|. controlMask, xK_t), sendMessage $ ToggleGap U) -- toggle the top gap--- > , ((modMask x .|. controlMask, xK_w), sendMessage $ IncGap R 5)  -- increment the right-hand gap--- > , ((modMask x .|. controlMask, xK_q), sendMessage $ DecGap R 5)  -- decrement the right-hand gap+-- > , ((modm .|. controlMask, xK_g), sendMessage $ ToggleGaps)  -- toggle all gaps+-- > , ((modm .|. controlMask, xK_t), sendMessage $ ToggleGap U) -- toggle the top gap+-- > , ((modm .|. controlMask, xK_w), sendMessage $ IncGap R 5)  -- increment the right-hand gap+-- > , ((modm .|. controlMask, xK_q), sendMessage $ DecGap R 5)  -- decrement the right-hand gap -- -- If you want complete control over all gaps, you could include -- something like this in your keybindings, assuming in this case you@@ -83,19 +79,19 @@  -- | A manual gap configuration.  Each side of the screen on which a --   gap is enabled is paired with a size in pixels.-type GapSpec = [(Direction,Int)]+type GapSpec = [(Direction2D,Int)]  -- | The gap state.  The first component is the configuration (which --   gaps are allowed, and their current size), the second is the gaps --   which are currently active.-data Gaps a = Gaps GapSpec [Direction]+data Gaps a = Gaps GapSpec [Direction2D]   deriving (Show, Read)  -- | Messages which can be sent to a gap modifier. data GapMessage = ToggleGaps              -- ^ Toggle all gaps.-                | ToggleGap  !Direction    -- ^ Toggle a single gap.-                | IncGap !Int !Direction    -- ^ Increase a gap by a certain number of pixels.-                | DecGap !Int !Direction    -- ^ Decrease a gap.+                | ToggleGap  !Direction2D    -- ^ Toggle a single gap.+                | IncGap !Int !Direction2D    -- ^ Increase a gap by a certain number of pixels.+                | DecGap !Int !Direction2D    -- ^ Decrease a gap.   deriving (Typeable)  instance Message GapMessage@@ -125,16 +121,16 @@ activeGaps :: Gaps a -> GapSpec activeGaps (Gaps conf cur) = filter ((`elem` cur) . fst) conf -toggleGaps :: GapSpec -> [Direction] -> [Direction]+toggleGaps :: GapSpec -> [Direction2D] -> [Direction2D] toggleGaps conf [] = map fst conf toggleGaps _    _  = [] -toggleGap :: GapSpec -> [Direction] -> Direction -> [Direction]+toggleGap :: GapSpec -> [Direction2D] -> Direction2D -> [Direction2D] toggleGap conf cur d | d `elem` cur            = delete d cur                      | d `elem` (map fst conf) = d:cur                      | otherwise               = cur -incGap :: GapSpec -> Direction -> Int -> GapSpec+incGap :: GapSpec -> Direction2D -> Int -> GapSpec incGap gs d i = map (\(dir,j) -> if dir == d then (dir,max (j+i) 0) else (dir,j)) gs  fi :: (Num b, Integral a) => a -> b
XMonad/Layout/Grid.hs view
@@ -17,7 +17,7 @@ module XMonad.Layout.Grid (     -- * Usage     -- $usage-    Grid(..), arrange+    Grid(..), arrange, defaultRatio ) where  import XMonad@@ -30,24 +30,34 @@ -- -- Then edit your @layoutHook@ by adding the Grid layout: ----- > myLayouts = Grid ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = Grid ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } --+-- You can also specify an aspect ratio for Grid to strive for with the+-- GridRatio constructor.  For example, if you want Grid to try to make a grid+-- four windows wide and three windows tall, you could use+--+-- > myLayout = GridRatio (4/3) ||| etc.+-- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" -data Grid a = Grid deriving (Read, Show)+data Grid a = Grid | GridRatio Double deriving (Read, Show) +defaultRatio :: Double+defaultRatio = 16/9+ instance LayoutClass Grid a where-    pureLayout Grid r s = arrange r (integrate s)+    pureLayout Grid          r = pureLayout (GridRatio defaultRatio) r+    pureLayout (GridRatio d) r = arrange d r . integrate -arrange :: Rectangle -> [a] -> [(a, Rectangle)]-arrange (Rectangle rx ry rw rh) st = zip st rectangles+arrange :: Double -> Rectangle -> [a] -> [(a, Rectangle)]+arrange aspectRatio (Rectangle rx ry rw rh) st = zip st rectangles     where     nwins = length st-    ncols = max 1 . round . sqrt $ fromIntegral nwins * 9 * fromIntegral rw / (16 * fromIntegral rh :: Double)-    mincs = nwins `div` ncols+    ncols = max 1 . round . sqrt $ fromIntegral nwins * fromIntegral rw / (fromIntegral rh * aspectRatio)+    mincs = max 1 $ nwins `div` ncols     extrs = nwins - ncols * mincs     chop :: Int -> Dimension -> [(Position, Dimension)]     chop n m = ((0, m - k * fromIntegral (pred n)) :) . map (flip (,) k) . tail . reverse . take n . tail . iterate (subtract k') $ m'
+ XMonad/Layout/GridVariants.hs view
@@ -0,0 +1,224 @@+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses #-}++----------------------------------------------------------------------+-- |+-- Module      : XMonad.Layout.GridVariants+-- Copyright   : (c) Norbert Zeh+-- License     : BSD-style (see LICENSE)+--+-- Maintainer  : nzeh@cs.dal.ca+-- Stability   : unstable+-- Portability : unportable+--+-- Two layouts: one is a variant of the Grid layout that allows the+-- desired aspect ratio of windows to be specified.  The other is like+-- Tall but places a grid with fixed number of rows and columns in the+-- master area and uses an aspect-ratio-specified layout for the+-- slaves.+----------------------------------------------------------------------++module XMonad.Layout.GridVariants ( -- * Usage+                                    -- $usage+                                    ChangeMasterGeom(..)+                                  , Grid(..)+                                  , TallGrid(..)+                                  , SplitGrid(..)+                                  , Orientation(..)+                                  ) where++import Control.Monad+import XMonad+import qualified XMonad.StackSet as W++-- $usage+-- This module can be used as follows:+--+-- > import XMonad.Layout.GridVariants+--+-- Then add something like this to your layouts:+--+-- > Grid (16/10)+--+-- for a 16:10 aspect ratio grid, or+--+-- > SplitGrid L 2 3 (2/3) (16/10) (5/100)+--+-- for a layout with a 2x3 master grid that uses 2/3 of the screen,+-- and a 16:10 aspect ratio slave grid to its right.  The last+-- parameter is again the percentage by which the split between master+-- and slave area changes in response to Expand/Shrink messages.+--+-- To be able to change the geometry of the master grid, add something+-- like this to your keybindings:+--+-- > ((modm .|. shiftMask, xK_equal), sendMessage $ IncMasterCols 1),+-- > ((modm .|. shiftMask, xK_minus), sendMessage $ IncMasterCols (-1)),+-- > ((modm .|. controlMask,  xK_equal), sendMessage $ IncMasterRows 1),+-- > ((modm .|. controlMask,  xK_minus), sendMessage $ IncMasterRows (-1))++-- | Grid layout.  The parameter is the desired x:y aspect ratio of windows+data Grid a = Grid !Rational+              deriving (Read, Show)++instance LayoutClass Grid a where++    pureLayout (Grid aspect) rect st = zip wins rects+        where+          wins  = W.integrate st+          nwins = length wins+          rects = arrangeAspectGrid rect nwins aspect++    description _ = "Grid"++-- | SplitGrid layout.  Parameters are+--+--   - side where the master is+--   - number of master rows+--   - number of master columns+--   - portion of screen used for master grid+--   - x:y aspect ratio of slave windows+--   - increment for resize messages+data SplitGrid a = SplitGrid Orientation !Int !Int !Rational !Rational !Rational+                   deriving (Read, Show)++-- | Type to specify the side of the screen that holds+--   the master area of a SplitGrid.+data Orientation = T | B | L | R+                   deriving (Eq, Read, Show)++instance LayoutClass SplitGrid a where++    pureLayout (SplitGrid o mrows mcols mfrac saspect _) rect st = zip wins rects+        where+          wins  = W.integrate st+          nwins = length wins+          rects = arrangeSplitGrid rect o nwins mrows mcols mfrac saspect++    pureMessage layout msg =+        msum [ fmap (resizeMaster layout) (fromMessage msg)+             , fmap (changeMasterGrid layout) (fromMessage msg) ]++    description _ = "SplitGrid"++-- |The geometry change message understood by the master grid+data ChangeMasterGeom+    = IncMasterRows !Int -- ^Change the number of master rows+    | IncMasterCols !Int -- ^Change the number of master columns+    deriving Typeable++instance Message ChangeMasterGeom++arrangeSplitGrid :: Rectangle -> Orientation -> Int -> Int -> Int -> Rational -> Rational -> [Rectangle]+arrangeSplitGrid rect@(Rectangle rx ry rw rh) o nwins mrows mcols mfrac saspect+    | nwins <= mwins = arrangeMasterGrid rect nwins mcols+    | mwins == 0     = arrangeAspectGrid rect nwins saspect+    | otherwise      = (arrangeMasterGrid mrect mwins mcols) +++                       (arrangeAspectGrid srect swins saspect)+    where+      mwins            = mrows * mcols+      swins            = nwins - mwins+      mrect            = Rectangle mx my mw mh+      srect            = Rectangle sx sy sw sh+      (mh, sh, mw, sw) = if o `elem` [T, B] then+                             (ceiling (fromIntegral rh * mfrac), rh - mh, rw, rw)+                         else+                             (rh, rh, ceiling (fromIntegral rw * mfrac), rw - mw)+      mx               = fromIntegral rx + if o == R then fromIntegral sw else 0+      my               = fromIntegral ry + if o == B then fromIntegral sh else 0+      sx               = fromIntegral rx + if o == L then fromIntegral mw else 0+      sy               = fromIntegral ry + if o == T then fromIntegral mh else 0++arrangeMasterGrid :: Rectangle -> Int -> Int -> [Rectangle]+arrangeMasterGrid rect nwins mcols = arrangeGrid rect nwins (min nwins mcols)++arrangeAspectGrid :: Rectangle -> Int -> Rational -> [Rectangle]+arrangeAspectGrid rect@(Rectangle _ _ rw rh) nwins aspect =+    arrangeGrid rect nwins (min nwins ncols)+    where+      scr_a = fromIntegral rw / fromIntegral rh+      fcols = sqrt ( fromRational $ scr_a * fromIntegral nwins / aspect ) :: Double+      cols1 = floor fcols :: Int+      cols2 = ceiling fcols :: Int+      rows1 = ceiling ( fromIntegral nwins / fromIntegral cols1 :: Rational ) :: Int+      rows2 = floor ( fromIntegral nwins / fromIntegral cols2 :: Rational ) :: Int+      a1    = scr_a * fromIntegral rows1 / fromIntegral cols1+      a2    = scr_a * fromIntegral rows2 / fromIntegral cols2+      ncols | cols1 == 0                = cols2+            | rows2 == 0                = cols1+            | a1 / aspect < aspect / a2 = cols1+            | otherwise                 = cols2++arrangeGrid :: Rectangle -> Int -> Int -> [Rectangle]+arrangeGrid (Rectangle rx ry rw rh) nwins ncols =+    [Rectangle (fromIntegral x + rx) (fromIntegral y + ry) (fromIntegral w) (fromIntegral h)+     | (x, y, w, h) <- rects]+    where+      nrows_in_cols = listDifference $ splitEvenly nwins ncols+      x_slabs       = splitIntoSlabs (fromIntegral rw) ncols+      y_slabs       = [splitIntoSlabs (fromIntegral rh) nrows | nrows <- nrows_in_cols]+      rects_in_cols = [[(x, y, w, h) | (y, h) <- lst]+                       | ((x, w), lst) <- zip x_slabs y_slabs]+      rects         = foldr (++) [] rects_in_cols++splitIntoSlabs :: Int -> Int -> [(Int, Int)]+splitIntoSlabs width nslabs = zip (0:xs) widths+    where+      xs = splitEvenly width nslabs+      widths = listDifference xs++listDifference :: [Int] -> [Int]+listDifference lst = [cur-pre | (cur,pre) <- zip lst (0:lst)]++splitEvenly :: Int -> Int -> [Int]+splitEvenly n parts = [ sz-off | (sz,off) <- zip sizes offsets]+    where+      size    = ceiling ( (fromIntegral n / fromIntegral parts) :: Double )+      extra   = size*parts - n+      sizes   = [i*size | i <- [1..parts]]+      offsets = (take (fromIntegral extra) [1..]) ++ [extra,extra..]++resizeMaster :: SplitGrid a -> Resize -> SplitGrid a+resizeMaster (SplitGrid o mrows mcols mfrac saspect delta) Shrink =+    SplitGrid o mrows mcols (max 0 (mfrac - delta)) saspect delta+resizeMaster (SplitGrid o mrows mcols mfrac saspect delta) Expand =+    SplitGrid o mrows mcols (min 1 (mfrac + delta)) saspect delta++changeMasterGrid :: SplitGrid a -> ChangeMasterGeom -> SplitGrid a+changeMasterGrid (SplitGrid o mrows mcols mfrac saspect delta) (IncMasterRows d) =+    SplitGrid o (max 0 (mrows + d)) mcols mfrac saspect delta+changeMasterGrid (SplitGrid o mrows mcols mfrac saspect delta) (IncMasterCols d) =+    SplitGrid o mrows (max 0 (mcols + d)) mfrac saspect delta++-- | TallGrid layout.  Parameters are+--+--   - number of master rows+--   - number of master columns+--   - portion of screen used for master grid+--   - x:y aspect ratio of slave windows+--   - increment for resize messages+--+--   This exists mostly because it was introduced in an earlier version.+--   It's a fairly thin wrapper around "SplitGrid L".+data TallGrid a = TallGrid !Int !Int !Rational !Rational !Rational+                  deriving (Read, Show)++instance LayoutClass TallGrid a where++    pureLayout (TallGrid mrows mcols mfrac saspect _) rect st = zip wins rects+        where+          wins  = W.integrate st+          nwins = length wins+          rects = arrangeSplitGrid rect L nwins mrows mcols mfrac saspect++    pureMessage layout msg =+        msum [ fmap ((tallGridAdapter resizeMaster) layout) (fromMessage msg)+             , fmap ((tallGridAdapter changeMasterGrid) layout) (fromMessage msg) ]++    description _ = "TallGrid"++tallGridAdapter :: (SplitGrid a -> b -> SplitGrid a) -> TallGrid a -> b -> TallGrid a+tallGridAdapter f (TallGrid mrows mcols mfrac saspect delta) msg =+    TallGrid mrows' mcols' mfrac' saspect' delta'+    where+      SplitGrid _ mrows' mcols' mfrac' saspect' delta' =+          f (SplitGrid L mrows mcols mfrac saspect delta) msg
XMonad/Layout/HintedGrid.hs view
@@ -18,7 +18,7 @@ module XMonad.Layout.HintedGrid (     -- * Usage     -- $usage-    Grid(..), arrange+    Grid(..), arrange, defaultRatio ) where  import Prelude hiding ((.))@@ -41,19 +41,28 @@ -- -- Then edit your @layoutHook@ by adding the 'Grid' layout: ----- > myLayouts = Grid False ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = Grid False ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } --+-- You can also specify an aspect ratio for Grid to strive for with the+-- GridRatio constructor:+--+-- > myLayout = GridRatio (4/3) False ||| etc.+-- -- For more detailed instructions on editing the layoutHook see -- "XMonad.Doc.Extending#Editing_the_layout_hook".  -- | Automatic mirroring of hinted layouts doesn't work very well, so this -- 'Grid' comes with built-in mirroring. @Grid False@ is the normal layout, -- @Grid True@ is the mirrored variant (rotated by 90 degrees).-data Grid a = Grid Bool deriving (Read, Show)+data Grid a = Grid Bool | GridRatio Double Bool deriving (Read, Show) +defaultRatio :: Double+defaultRatio = 16/9+ instance LayoutClass Grid Window where-    doLayout (Grid m) r w = flip (,) Nothing . arrange m r (integrate w)+    doLayout (Grid m)        r w = doLayout (GridRatio defaultRatio m) r w+    doLayout (GridRatio d m) r w = flip (,) Nothing . arrange d m r (integrate w)  replicateS :: Int -> (a -> (b, a)) -> a -> ([b], a) replicateS n = runState . replicateM n . State@@ -92,12 +101,12 @@         zipWith3 (\x y (w, h) -> Rectangle (fromIntegral x) (fromIntegral y) w h) xs ys c' ++ doR width' (n - 1) cs  -- | The internal function for computing the grid layout.-arrange :: Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]-arrange mirror (Rectangle rx ry rw rh) wins = do+arrange :: Double -> Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]+arrange aspectRatio mirror (Rectangle rx ry rw rh) wins = do     proto <- mapM mkAdjust wins     let         adjs = map (\f -> twist . f . twist) proto-        rs = arrange' (twist (rw, rh)) adjs+        rs = arrange' aspectRatio (twist (rw, rh)) adjs         rs' = map (\(Rectangle x y w h) -> uncurry (uncurry Rectangle (twist (x, y))) (twist (w, h))) rs     return . zip wins . map (\r -> r{ rect_x = rect_x r + rx, rect_y = rect_y r + ry }) $ rs'     where@@ -105,11 +114,11 @@         | mirror = \(a, b) -> (b, a)         | otherwise = id -arrange' :: D -> [D -> D] -> [Rectangle]-arrange' (rw, rh) adjs = reverse $ doRect rh rw (fromIntegral ncolumns) (ecols ++ cols)+arrange' :: Double -> D -> [D -> D] -> [Rectangle]+arrange' aspectRatio (rw, rh) adjs = reverse $ doRect rh rw (fromIntegral ncolumns) (ecols ++ cols)     where     nwindows = length adjs-    ncolumns = max 1 . round . sqrt $ fromIntegral nwindows * 9 * fromIntegral rw / (16 * fromIntegral rh :: Double)+    ncolumns = max 1 . round . sqrt $ fromIntegral nwindows * fromIntegral rw / (fromIntegral rh * aspectRatio)     nrows = nwindows `div` ncolumns     nextras = nwindows - ncolumns * nrows     (ecols, adjs') = replicateS nextras (splitAt (nrows + 1)) $ reverse adjs
XMonad/Layout/HintedTile.hs view
@@ -50,11 +50,12 @@ -- "XMonad.Doc.Extending#Editing_the_layout_hook"  data HintedTile a = HintedTile-    { nmaster     :: !Int-    , delta, frac :: !Rational+    { nmaster     :: !Int         -- ^ number of windows in the master pane+    , delta       :: !Rational    -- ^ how much to change when resizing+    , frac        :: !Rational    -- ^ ratio between master/nonmaster panes     , alignment   :: !Alignment   -- ^ Where to place windows that are smaller                                   --   than their preordained rectangles.-    , orientation :: !Orientation+    , orientation :: !Orientation -- ^ Tall or Wide (mirrored) layout?     } deriving ( Show, Read )  data Orientation
XMonad/Layout/IM.hs view
@@ -10,7 +10,7 @@ -- Stability   :  unstable -- Portability :  unportable ----- Layout modfier suitable for workspace with multi-windowed instant messanger+-- Layout modfier suitable for workspace with multi-windowed instant messenger -- (like Psi or Tkabber). -- -----------------------------------------------------------------------------@@ -45,8 +45,8 @@ -- for managing your chat windows (Grid in this example, another useful choice -- to consider is Tabbed layout). ----- > myLayouts = withIM (1%7) (ClassName "Tkabber") Grid ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = withIM (1%7) (ClassName "Tkabber") Grid ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- Here @1%7@ is the part of the screen which your roster will occupy, -- @ClassName \"Tkabber\"@ tells xmonad which window is actually your roster.@@ -122,6 +122,6 @@         let (masterRect, slaveRect) = splitHorizontallyBy r rect         master <- findM (hasProperty prop) ws         let positions = case master of-                Just w -> (w, masterRect) : arrange slaveRect (filter (w /=) ws)-                Nothing -> arrange rect ws+                Just w -> (w, masterRect) : arrange defaultRatio slaveRect (filter (w /=) ws)+                Nothing -> arrange defaultRatio rect ws         return (positions, Nothing)
+ XMonad/Layout/IndependentScreens.hs view
@@ -0,0 +1,104 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.IndependentScreens+-- Copyright   :  (c) 2009 Daniel Wagner+-- License     :  BSD3+--+-- Maintainer  :  <daniel@wagner-home.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Utility functions for simulating independent sets of workspaces on+-- each screen (like dwm's workspace model), using internal tags to+-- distinguish workspaces associated with each screen.+-----------------------------------------------------------------------------++module XMonad.Layout.IndependentScreens (+    -- * Usage+    -- $usage+    VirtualWorkspace, PhysicalWorkspace,+    workspaces',+    withScreens, onCurrentScreen,+    countScreens,+    marshall, unmarshall+) where++-- for the screen stuff+import Control.Arrow hiding ((|||))+import Control.Monad+import Control.Monad.Instances+import Data.List+import Graphics.X11.Xinerama+import XMonad+import XMonad.StackSet hiding (workspaces)++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.IndependentScreens+--+-- You can define your workspaces by calling @withScreens@:+--+-- > myConfig = defaultConfig { workspaces = withScreens 2 ["web", "email", "irc"] }+--+-- This will create \"physical\" workspaces with distinct internal names for+-- each (screen, virtual workspace) pair.+--+-- Then edit any keybindings that use the list of workspaces or refer+-- to specific workspace names.  In the default configuration, only+-- the keybindings for changing workspace do this:+--+-- > [((m .|. modm, k), windows $ f i)+-- >     | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]+-- >     , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]+--+-- This should change to+--+-- > [((m .|. modm, k), windows $ onCurrentScreen f i)+-- >     | (i, k) <- zip (workspaces' conf) [xK_1 .. xK_9]+-- >     , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]+--+-- In particular, the analogue of @XMonad.workspaces@ is+-- @workspaces'@, and you can use @onCurrentScreen@ to convert functions+-- of virtual workspaces to functions of physical workspaces, which work+-- by marshalling the virtual workspace name and the currently focused+-- screen into a physical workspace name.++type VirtualWorkspace  = WorkspaceId+type PhysicalWorkspace = WorkspaceId++marshall :: ScreenId -> VirtualWorkspace -> PhysicalWorkspace+marshall (S sc) vws = show sc ++ '_':vws++unmarshall :: PhysicalWorkspace -> (ScreenId, VirtualWorkspace)+unmarshall = ((S . read) *** drop 1) . break (=='_')++-- ^ You shouldn't need to use @marshall@ and @unmarshall@ very much.+-- They simply convert between the physical and virtual worlds.  For+-- example, you might want to use them as part of a status bar+-- configuration.  The function @snd . unmarshall@ would discard the+-- screen information from an otherwise unsightly workspace name.++workspaces' :: XConfig l -> [VirtualWorkspace]+workspaces' = nub . map (snd . unmarshall) . workspaces++withScreens :: ScreenId            -- ^ The number of screens to make workspaces for+            -> [VirtualWorkspace]  -- ^ The desired virtual workspace names+            -> [PhysicalWorkspace] -- ^ A list of all internal physical workspace names+withScreens n vws = [marshall sc pws | pws <- vws, sc <- [0..n-1]]++onCurrentScreen :: (VirtualWorkspace -> WindowSet -> a) -> (PhysicalWorkspace -> WindowSet -> a)+onCurrentScreen f vws = screen . current >>= f . flip marshall vws++-- | In case you don't know statically how many screens there will be, you can call this in main before starting xmonad.  For example, part of my config reads+--+-- > main = do+-- >   nScreens <- countScreens+-- >   xmonad $ defaultConfig {+-- >     ...+-- >     workspaces = withScreens nScreens (workspaces defaultConfig),+-- >     ...+-- >     }+--+countScreens :: (MonadIO m, Integral i) => m i+countScreens = liftM genericLength . liftIO $ openDisplay "" >>= getScreenInfo
+ XMonad/Layout/LayoutBuilder.hs view
@@ -0,0 +1,277 @@+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, PatternGuards, DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.LayoutBuilder+-- Copyright   :  (c) 2009 Anders Engstrom <ankaan@gmail.com>+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Anders Engstrom <ankaan@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A layout combinator that sends a specified number of windows to one rectangle+-- and the rest to another.+--+-----------------------------------------------------------------------------++module XMonad.Layout.LayoutBuilder (+  -- * Usage+  -- $usage+  layoutN,+  layoutR,+  layoutAll,+  IncLayoutN (..),+  SubMeasure (..),+  SubBox (..),+  absBox,+  relBox+) where++import XMonad+import XMonad.Layout+import qualified XMonad.StackSet as W+import Graphics.X11.Xlib+import Data.Maybe (isJust)+import Control.Monad++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.LayoutBuilder+--+-- Then edit your @layoutHook@ by adding something like:+--+-- > myLayout = ( (layoutN 1 (relBox 0 0 0.5 1) (Just $ relBox 0 0 1 1) $ simpleTabbed)+-- >             $ (layoutAll (relBox 0.5 0 1 1)                         $ simpleTabbed)+-- >             ) |||+-- >             ( (layoutN 1       (relBox (1/3) 0 (1/2) 1) (Just $ relBox 0 0 1 1) $ Tall 0 0.01 0.5)+-- >             $ (layoutR 0.1 0.5 (relBox (2/3) 0 1     1) Nothing                 $ Tall 0 0.01 0.5)+-- >             $ (layoutAll       (relBox 0     0 (1/3) 1)                         $ Tall 0 0.01 0.5)+-- >             ) |||+-- >             ( (layoutN 1 (absBox (-512-200) 0 512        0) (Just $ relBox 0 0 1 1) $ simpleTabbed)+-- >             $ (layoutN 1 (absBox (-200)     0 0          0) Nothing                 $ simpleTabbed)+-- >             $ (layoutAll (absBox 0          0 (-512-200) 0)                         $ simpleTabbed)+-- >             ) ||| Full ||| etc...+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- This will produce a layout similar to DragPane, but with the possibility to have multiple windows in the left half+-- and tabs that show the available windows. It will also produce a layout similar to ThreeColMid and a special layout+-- created for use with a 80 columns wide Emacs window, its sidebar and a tabbed area for all other windows.+--+-- This module can be used to create many different custom layouts, but there are limitations. The primary limitation+-- can be observed in the second and third example when there are only two columns with windows in them. The leftmost+-- area is left blank. These blank areas can be avoided by placing the rectangles appropriately.+--+-- These examples require "XMonad.Layout.Tabbed".+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+--+-- You may wish to add the following keybindings:+--+-- >    , ((modm .|. shiftMask, xK_h ), sendMessage $ IncLayoutN (-1))+-- >    , ((modm .|. shiftMask, xK_l ), sendMessage $ IncLayoutN 1)+--+-- For detailed instruction on editing the key binding see:+--+-- "XMonad.Doc.Extending#Editing_key_bindings".++type WindowNum = Either Int (Rational,Rational)++-- | Use one layout in the specified area for a number of windows and possibly let another layout handle the rest.+data LayoutN l1 l2 a =+    LayoutN (Maybe a) (Maybe a) WindowNum SubBox (Maybe SubBox) (l1 a) (Maybe (l2 a))+    deriving (Show,Read)++-- | Use the specified layout in the described area for N windows and send the rest of the windows to the next layout in the chain.+--   It is possible to supply an alternative area that will then be used instead, if there are no windows to send to the next layout.+layoutN :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) =>+       Int                          -- ^ The number of windows to handle+    -> SubBox                       -- ^ The box to place the windows in+    -> Maybe SubBox                 -- ^ Possibly an alternative box that is used when this layout handles all windows that are left+    -> l1 a                         -- ^ The layout to use in the specified area+    -> LayoutN l2 l3 a              -- ^ Where to send the remaining windows+    -> LayoutN l1 (LayoutN l2 l3) a -- ^ The resulting layout+layoutN num box mbox sub next = LayoutN Nothing Nothing (Left num) box mbox sub (Just next)++-- | As layoutN, but the number of windows is given relative to the total number of windows remaining to be handled. The first+--   argument is how much to change the ratio when using IncLayoutN, and the second is the initial ratio.+layoutR :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) =>+       Rational                     -- ^ How much to change the ratio with each IncLayoutN+    -> Rational                     -- ^ The ratio of the remaining windows to handle+    -> SubBox                       -- ^ The box to place the windows in+    -> Maybe SubBox                 -- ^ Possibly an alternative box that is used when this layout handles all windows that are left+    -> l1 a                         -- ^ The layout to use in the specified area+    -> LayoutN l2 l3 a              -- ^ Where to send the remaining windows+    -> LayoutN l1 (LayoutN l2 l3) a -- ^ The resulting layout+layoutR numdiff num box mbox sub next = LayoutN Nothing Nothing (Right (numdiff,num)) box mbox sub (Just next)++-- | Use the specified layout in the described area for all remaining windows.+layoutAll :: (Read a, Eq a, LayoutClass l1 a) =>+       SubBox             -- ^ The box to place the windows in+    -> l1 a               -- ^ The layout to use in the specified area+    -> LayoutN l1 Full a  -- ^ The resulting layout+layoutAll box sub = LayoutN Nothing Nothing (Right (0,1)) box Nothing sub Nothing++-- | Change the number of windows handled by the focused layout.+data IncLayoutN = IncLayoutN Int deriving Typeable+instance Message IncLayoutN++-- | The absolute or relative measures used to describe the area a layout should be placed in. For negative absolute values+--   the total remaining space will be added. For sizes, the remaining space will also be added for zeroes. Relative values+--   are applied on the remaining space after the top-left corner of the box have been removed.+data SubMeasure = Abs Int | Rel Rational deriving (Show,Read)++-- | A box to place a layout in. The stored values are xpos, ypos, width and height.+data SubBox = SubBox SubMeasure SubMeasure SubMeasure SubMeasure deriving (Show,Read)+++-- | Create a box with only absolute measurements. If the values are negative, the total remaining space will be added. For+--   sizes it will also be added for zeroes.+absBox :: Int     -- ^ Absolute X-Position+       -> Int     -- ^ Absolute Y-Position+       -> Int     -- ^ Absolute width+       -> Int     -- ^ Absolute height+       -> SubBox  -- ^ The resulting 'SubBox' describing the area+absBox x y w h = SubBox (Abs x) (Abs y) (Abs w) (Abs h)+++-- | Create a box with only relative measurements.+relBox :: Rational  -- ^ Relative X-Position with respect to the surrounding area+       -> Rational  -- ^ Relative Y-Position with respect to the surrounding area+       -> Rational  -- ^ Relative width with respect to the remaining width+       -> Rational  -- ^ Relative height with respect to the remaining height+       -> SubBox    -- ^ The resulting 'SubBox' describing the area+relBox x y w h = SubBox (Rel x) (Rel y) (Rel w) (Rel h)+++instance (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) =>+    LayoutClass (LayoutN l1 l2) a where++        -- | Update window locations.+        runLayout (W.Workspace _ (LayoutN subf nextf num box mbox sub next) s) rect+            = do let (subs,nexts,subf',nextf') = splitStack s num subf nextf+                     selBox = if isJust nextf'+                              then box+                              else maybe box id mbox++                 (sublist,sub') <- handle sub subs $ calcArea selBox rect++                 (nextlist,next') <- case next of Nothing -> return ([],Nothing)+                                                  Just n -> do (res,l) <- handle n nexts rect+                                                               return (res,Just l)++                 return (sublist++nextlist, Just $ LayoutN subf' nextf' num box mbox sub' next' )+              where+                  handle l s' r = do (res,ml) <- runLayout (W.Workspace "" l s') r+                                     l' <- return $ maybe l id ml+                                     return (res,l')++        -- |  Propagate messages.+        handleMessage l m+            | Just (IncLayoutN _) <- fromMessage m = windowNum l m+            | Just (IncMasterN _) <- fromMessage m = sendFocus l m+            | Just (Shrink) <- fromMessage m = sendFocus l m+            | Just (Expand) <- fromMessage m = sendFocus l m+            | otherwise = sendBoth l m++        -- |  Descriptive name for layout.+        description (LayoutN _ _ _ _ _ sub Nothing) = "layoutAll "++ description sub+        description (LayoutN _ _ (Left _) _ _ sub (Just next)) = "layoutN "++ description sub ++" "++ description next+        description (LayoutN _ _ (Right _) _ _ sub (Just next)) = "layoutR "++ description sub ++" "++ description next+++windowNum :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))+windowNum l@(LayoutN subf nextf num box mbox subl nextl) m | (Just (IncLayoutN n)) <- fromMessage m =+    do foc <- isFocus subf+       if foc then do let newnum = case num of+                                       (Left oldnum) -> Left $ max 1 $ oldnum + n+                                       (Right (diff,oldnum)) -> Right (diff, min 1 $ max 0 $ oldnum + (fromIntegral n)*diff)+                      return $ Just $ LayoutN subf nextf newnum box mbox subl nextl+              else sendNext l m+windowNum l m = sendNext l m++sendSub :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))+sendSub (LayoutN subf nextf num box mbox sub next) m =+    do sub' <- handleMessage sub m+       return $ if isJust sub'+                then Just $ LayoutN subf nextf num box mbox (maybe sub id sub') next+                else Nothing++sendBoth :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))+sendBoth l@(LayoutN _ _ _ _ _ _ Nothing) m = sendSub l m+sendBoth (LayoutN subf nextf num box mbox sub (Just next)) m =+    do sub' <- handleMessage sub m+       next' <- handleMessage next m+       return $ if isJust sub' || isJust next'+                then Just $ LayoutN subf nextf num box mbox (maybe sub id sub') (Just $ maybe next id next')+                else Nothing++sendNext :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))+sendNext (LayoutN _ _ _ _ _ _ Nothing) _ = return Nothing+sendNext (LayoutN subf nextf num box mbox sub (Just next)) m =+    do next' <- handleMessage next m+       return $ if isJust next'+                then Just $ LayoutN subf nextf num box mbox sub next'+                else Nothing++sendFocus :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))+sendFocus l@(LayoutN subf _ _ _ _ _ _) m = do foc <- isFocus subf+                                              if foc then sendSub l m+                                                     else sendNext l m++isFocus :: (Show a) => Maybe a -> X Bool+isFocus Nothing = return False+isFocus (Just w) = do ms <- (W.stack . W.workspace . W.current) `fmap` gets windowset+                      return $ maybe False (\s -> show w == (show $ W.focus s)) ms+++calcNum :: Int -> WindowNum -> Int+calcNum tot num = max 1 $ case num of Left i -> i+                                      Right (_,r) -> ceiling $ r * fromIntegral tot++splitStack :: Eq a => Maybe (W.Stack a) -> WindowNum -> Maybe a -> Maybe a -> (Maybe (W.Stack a),Maybe (W.Stack a),Maybe a,Maybe a)+splitStack Nothing _ _ _ = (Nothing,Nothing,Nothing,Nothing)+splitStack (Just s) num subf nextf = ( differentiate' subf' subl+                                     , differentiate' nextf' nextl+                                     , subf'+                                     , nextf'+                                     )+    where+        ws = W.integrate s+        n = calcNum (length ws) num+        subl = take n ws+        nextl = drop n ws+        subf' = foc subl subf+        nextf' = foc nextl nextf+        foc [] _ = Nothing+        foc l f = if W.focus s `elem` l+                  then Just $ W.focus s+                  else if maybe False (`elem` l) f+                       then f+                       else Just $ head l++calcArea :: SubBox -> Rectangle -> Rectangle+calcArea (SubBox xpos ypos width height) rect = Rectangle (rect_x rect + fromIntegral xpos') (rect_y rect + fromIntegral ypos') width' height'+    where+        xpos' = calc False xpos $ rect_width rect+        ypos' = calc False ypos $ rect_height rect+        width' = calc True width $ rect_width rect - xpos'+        height' = calc True height $ rect_height rect - ypos'++        calc zneg val tot = fromIntegral $ min (fromIntegral tot) $ max 0 $+            case val of Rel v -> floor $ v * fromIntegral tot+                        Abs v -> if v<0 || (zneg && v==0)+                                 then (fromIntegral tot)+v+                                 else v++differentiate' :: Eq q => Maybe q -> [q] -> Maybe (W.Stack q)+differentiate' _ [] = Nothing+differentiate' Nothing w = W.differentiate w+differentiate' (Just f) w+    | f `elem` w = Just $ W.Stack { W.focus = f+                                  , W.up    = reverse $ takeWhile (/=f) w+                                  , W.down  = tail $ dropWhile (/=f) w+                                  }+    | otherwise = W.differentiate w
XMonad/Layout/LayoutCombinators.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module       : XMonad.Layout.LayoutCombinators@@ -47,7 +46,7 @@       -- * New layout choice combinator and 'JumpToLayout'       -- $jtl     , (|||)-    , JumpToLayout(JumpToLayout)+    , JumpToLayout(..)     ) where  import Data.Maybe ( isJust, isNothing )@@ -65,8 +64,8 @@ -- Then edit your @layoutHook@ to use the new layout combinators. For -- example: ----- > myLayouts = (Tall 1 (3/100) (1/2) *//* Full)  ||| (Tall 1 (3/100) (1/2) ***||** Full) ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = (Tall 1 (3/100) (1/2) *//* Full)  ||| (Tall 1 (3/100) (1/2) ***||** Full) ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the @layoutHook@ see: --@@ -79,7 +78,7 @@ -- -- Then bind some keys to a 'JumpToLayout' message: ----- >   , ((modMask x .|. controlMask, xK_f), sendMessage $ JumpToLayout "Full")  -- jump directly to the Full layout+-- >   , ((modm .|. controlMask, xK_f), sendMessage $ JumpToLayout "Full")  -- jump directly to the Full layout -- -- See below for more detailed documentation. @@ -214,12 +213,12 @@  data NewSelect l1 l2 a = NewSelect Bool (l1 a) (l2 a) deriving ( Read, Show ) -data NoWrap = NextLayoutNoWrap | Wrap deriving ( Read, Show, Typeable )-instance Message NoWrap---- | A message to jump to a particular layout, specified by its---   description string.-data JumpToLayout = JumpToLayout String deriving ( Read, Show, Typeable )+-- | +data JumpToLayout = JumpToLayout String -- ^ A message to jump to a particular layout+                                        -- , specified by its description string..+                  | NextLayoutNoWrap+                  | Wrap+                    deriving ( Read, Show, Typeable ) instance Message JumpToLayout  instance (LayoutClass l1 a, LayoutClass l2 a) => LayoutClass (NewSelect l1 l2) a where
XMonad/Layout/LayoutHints.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}-+{-# LANGUAGE ParallelListComp, PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module       : XMonad.Layout.LayoutHints@@ -8,7 +8,7 @@ -- -- Maintainer   : none -- Stability    : unstable--- Portability  : portable+-- Portability  : unportable -- -- Make layouts respect size hints. -----------------------------------------------------------------------------@@ -17,40 +17,221 @@     ( -- * usage       -- $usage       layoutHints+    , layoutHintsWithPlacement+    , layoutHintsToCenter     , LayoutHints-    ) where+    )  where -import XMonad hiding ( trace )-import XMonad.Layout.LayoutModifier-import XMonad.Layout.Decoration ( isInStack )+import XMonad(LayoutClass(runLayout), mkAdjust, Window,+              Dimension, Position, Rectangle(Rectangle),D)+import qualified XMonad.StackSet as W +import XMonad.Layout.Decoration(isInStack)+import XMonad.Layout.LayoutModifier(ModifiedLayout(..),+                                    LayoutModifier(modifyLayout, redoLayout, modifierDescription))+import XMonad.Util.Types(Direction2D(..))+import Control.Applicative((<$>))+import Control.Arrow(Arrow((***), first, second))+import Control.Monad(Monad(return), mapM, join)+import Data.Function(on)+import Data.List(sortBy)++import Data.Set (Set)+import qualified Data.Set as Set+ -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Layout.LayoutHints ----- Then edit your @layoutHook@ by adding the LayoutHints layout modifier+-- Then edit your @layoutHook@ by adding the 'layoutHints' layout modifier -- to some layout: ----- > myLayouts = layoutHints (Tall 1 (3/100) (1/2))  ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = layoutHints (Tall 1 (3/100) (1/2))  ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } --+-- Or, to center the adapted window in its available area:+--+-- > myLayout = layoutHintsWithPlacement (0.5, 0.5) (Tall 1 (3/100) (1/2))+-- >                   ||| Full ||| etc..+--+-- Or, to make a reasonable attempt to eliminate gaps between windows:+--+-- > myLayout = layoutHintsToCenter (Tall 1 (3/100) (1/2))+-- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook"  layoutHints :: (LayoutClass l a) => l a -> ModifiedLayout LayoutHints l a-layoutHints = ModifiedLayout LayoutHints+layoutHints = ModifiedLayout (LayoutHints (0, 0)) -data LayoutHints a = LayoutHints deriving (Read, Show)+-- | @layoutHintsWithPlacement (rx, ry) layout@ will adapt the sizes of a layout's+-- windows according to their size hints, and position them inside their+-- originally assigned area according to the @rx@ and @ry@ parameters.+-- (0, 0) places the window at the top left, (1, 0) at the top right, (0.5, 0.5)+-- at the center, etc.+layoutHintsWithPlacement :: (LayoutClass l a) => (Double, Double)+                         -> l a -> ModifiedLayout LayoutHints l a+layoutHintsWithPlacement rs = ModifiedLayout (LayoutHints rs) +-- | @layoutHintsToCenter layout@ applies hints, sliding the window to the+-- center of the screen and expanding its neighbors to fill the gaps. Windows+-- are never expanded in a way that increases overlap.+--+-- @layoutHintsToCenter@ only makes one pass at resizing the neighbors of+-- hinted windows, so with some layouts (ex. the arrangement with two 'Mirror'+-- 'Tall' stacked vertically), @layoutHintsToCenter@ may leave some gaps.+-- Simple layouts like 'Tall' are unaffected.+layoutHintsToCenter :: (LayoutClass l a) => l a -> ModifiedLayout LayoutHintsToCenter l a+layoutHintsToCenter = ModifiedLayout LayoutHintsToCenter++data LayoutHints a = LayoutHints (Double, Double)+                     deriving (Read, Show)+ instance LayoutModifier LayoutHints Window where     modifierDescription _ = "Hinted"-    redoLayout _ _ s xs = do-                            xs' <- mapM applyHint xs-                            return (xs', Nothing)+    redoLayout _ _ Nothing  xs = return (xs, Nothing)+    redoLayout (LayoutHints al) _ (Just s) xs+        = do xs' <- mapM (\x@(_, r) -> second (placeRectangle al r) <$> applyHint x) xs+             return (xs', Nothing)      where         applyHint (w,r@(Rectangle a b c d)) = do             adj <- mkAdjust w             let (c',d') = adj (c,d)             return (w, if isInStack s w then Rectangle a b c' d' else r)++-- | @placeRectangle (rx, ry) r0 r@ will return a new rectangle with the same dimensions+-- as @r@, but positioned inside of @r0@ as specified by the (rx, ry) parameters (see+-- 'layoutHintsWithPlacement').+placeRectangle :: RealFrac r => (r, r) -> Rectangle -> Rectangle -> Rectangle+placeRectangle (rx, ry) (Rectangle x0 y0 w h) (Rectangle _ _ dx dy)+    = Rectangle (align x0 dx w rx) (align y0 dy h ry) dx dy+    where align :: RealFrac r => Position -> Dimension -> Dimension -> r -> Position+          align z0 dz d r = z0 + truncate (fromIntegral (d - dz) * r)++fitting :: [Rectangle] -> Int+fitting rects = sum $ do+    r <- rects+    return $ length $ filter (touching r) rects++applyOrder :: Rectangle -> [((Window, Rectangle),t)] -> [[((Window, Rectangle),t)]]+applyOrder root wrs = do+    -- perhaps it would just be better to take all permutations, or apply the+    -- resizing multiple times+    f <- [maximum, minimum, sum, sum . map sq]+    return $ sortBy (compare `on` (f . distance)) wrs+    where distFC = uncurry ((+) `on` sq) . pairWise (-) (center root)+          distance = map distFC . corners . snd . fst+          pairWise f (a,b) (c,d) = (f a c, f b d)+          sq = join (*)++data LayoutHintsToCenter a = LayoutHintsToCenter deriving (Read, Show)++instance LayoutModifier LayoutHintsToCenter Window where+    modifyLayout _ ws@(W.Workspace _ _ Nothing) r = runLayout ws r+    modifyLayout _ ws@(W.Workspace _ _ (Just st)) r = do+        (arrs,ol) <- runLayout ws r+        flip (,) ol+            . head . reverse . sortBy (compare `on` (fitting . map snd))+            . map (applyHints st r) . applyOrder r+            <$> mapM (\x -> fmap ((,) x) $ mkAdjust (fst x)) arrs++-- apply hints to first, grow adjacent windows+applyHints :: W.Stack Window -> Rectangle -> [((Window, Rectangle),(D -> D))] -> [(Window, Rectangle)]+applyHints _ _ [] = []+applyHints s root (((w,lrect@(Rectangle a b c d)),adj):xs) =+        let (c',d') = adj (c,d)+            redr = placeRectangle (centerPlacement root lrect :: (Double,Double)) lrect+                    $ if isInStack s w then Rectangle a b c' d' else lrect++            ds = (fromIntegral c - fromIntegral c',fromIntegral d - fromIntegral d')+            growOther' r = growOther ds lrect (freeDirs root lrect) r+            mapSnd f = map (first $ second f)+            next = applyHints s root $ mapSnd growOther' xs+        in (w,redr):next++growOther :: (Position, Position) -> Rectangle -> Set Direction2D -> Rectangle -> Rectangle+growOther ds lrect fds r+    | dirs <- flipDir <$> Set.toList (Set.intersection adj fds)+    , not $ any (uncurry opposite) $ cross dirs =+        foldr (flip grow ds) r dirs+    | otherwise = r+    where+        adj = adjacent lrect  r+        cross xs = [ (a,b) | a <- xs, b <- xs ]++        flipDir :: Direction2D -> Direction2D+        flipDir d = case d of { L -> R; U -> D; R -> L; D -> U }++        opposite :: Direction2D -> Direction2D -> Bool+        opposite x y = flipDir x == y++-- | Leave the opposite edges where they were+grow :: Direction2D -> (Position,Position) -> Rectangle -> Rectangle+grow L (px,_ ) (Rectangle x y w h) = Rectangle (x-px) y (w+fromIntegral px) h+grow U (_ ,py) (Rectangle x y w h) = Rectangle x (y-py) w (h+fromIntegral py)+grow R (px,_ ) (Rectangle x y w h) = Rectangle x y (w+fromIntegral px) h+grow D (_ ,py) (Rectangle x y w h) = Rectangle x y w (h+fromIntegral py)++comparingEdges :: ([Position] -> [Position] -> Bool) -> Rectangle -> Rectangle -> Set Direction2D+comparingEdges surrounds r1 r2 = Set.fromList $ map fst $ filter snd [ (\k -> (dir,k)) $+            any and [[dir `elem` [R,L], allEq [a,c,w,y], [b,d] `surrounds` [x,z]]+                    ,[dir `elem` [U,D], allEq [b,d,x,z], [a,c] `surrounds` [w,y]]]+    | ((a,b),(c,d)) <- edge $ corners r1+    | ((w,x),(y,z)) <- edge $ delay 2 $ corners r2+    | dir <- [U,R,D,L]]+        where edge (x:xs) = zip (x:xs) (xs ++ [x])+              edge [] = []+              delay n xs = drop n xs ++ take n xs+              allEq = all (uncurry (==)) . edge++-- | in what direction is the second window from the first that can expand if the+-- first is shrunk, assuming that the root window is fully covered:+--  one direction for a common edge+--  two directions for a common corner+adjacent :: Rectangle -> Rectangle -> Set Direction2D+adjacent = comparingEdges (all . onClosedInterval)++-- | True whenever two edges touch. not (Set.null $ adjacent x y) ==> touching x y+touching :: Rectangle -> Rectangle -> Bool+touching a b = not . Set.null $ comparingEdges c a b+    where c x y = any (onClosedInterval x) y || any (onClosedInterval y) x++onClosedInterval :: Ord a => [a] -> a -> Bool+onClosedInterval bds x = minimum bds <= x && maximum bds >= x++-- | starting top left going clockwise+corners :: Rectangle -> [(Position, Position)]+corners (Rectangle x y w h) = [(x,y)+                              ,(x+fromIntegral w, y)+                              ,(x+fromIntegral w, y+fromIntegral h)+                              ,(x, y+fromIntegral h)]++center :: Rectangle -> (Position, Position)+center (Rectangle x y w h) = (avg x w, avg y h)+    where avg a b = a + fromIntegral b `div` 2++centerPlacement :: RealFrac r => Rectangle -> Rectangle -> (r, r)+centerPlacement = centerPlacement' clamp+    where clamp n = case signum n of+                            0 -> 0.5+                            1 -> 1+                            _ -> 0++freeDirs :: Rectangle -> Rectangle -> Set Direction2D+freeDirs root = Set.fromList . uncurry (++) . (lr *** ud)+              . centerPlacement' signum root+    where+        lr 1 = [L]+        lr (-1) = [R]+        lr _ = [L,R]+        ud 1 = [U]+        ud (-1) = [D]+        ud _ = [U,D]++centerPlacement' :: (Position -> r) -> Rectangle -> Rectangle -> (r, r)+centerPlacement' cf root assigned+    = (cf $ cx - cwx, cf $ cy - cwy)+    where (cx,cy) = center root+          (cwx,cwy) = center assigned
XMonad/Layout/LayoutModifier.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -164,18 +163,17 @@     --   consider implementing 'hook' and 'pureModifier' instead of     --   'redoLayout'.     ---    --   If you also need to perform some action when 'runLayout' is-    --   called on an empty workspace, see 'emptyLayoutMod'.+    --   On empty workspaces, the Stack is Nothing.     --     --   The default implementation of 'redoLayout' calls 'hook' and     --   then 'pureModifier'.-    redoLayout :: m a          -- ^ the layout modifier-               -> Rectangle    -- ^ screen rectangle-               -> Stack a      -- ^ current window stack+    redoLayout :: m a               -- ^ the layout modifier+               -> Rectangle         -- ^ screen rectangle+               -> Maybe (Stack a)   -- ^ current window stack                -> [(a, Rectangle)]  -- ^ (window,rectangle) pairs returned                                     -- by the underlying layout                -> X ([(a, Rectangle)], Maybe (m a))-    redoLayout m r s wrs = do hook m; return $ pureModifier m r s wrs+    redoLayout m r ms wrs = do hook m; return $ pureModifier m r ms wrs      -- | 'pureModifier' allows you to intercept a call to 'runLayout'     --   /after/ it is called on the underlying layout, in order to@@ -184,33 +182,14 @@     --     --   The default implementation of 'pureModifier' returns the     --   window rectangles unmodified.-    pureModifier :: m a        -- ^ the layout modifier-                 -> Rectangle  -- ^ screen rectangle-                 -> Stack a    -- ^ current window stack+    pureModifier :: m a               -- ^ the layout modifier+                 -> Rectangle         -- ^ screen rectangle+                 -> Maybe (Stack a)   -- ^ current window stack                  -> [(a, Rectangle)]  -- ^ (window, rectangle) pairs returned                                       -- by the underlying layout                  -> ([(a, Rectangle)], Maybe (m a))     pureModifier _ _ _ wrs = (wrs, Nothing) -    -- | 'emptyLayoutMod' allows you to intercept a call to-    --   'runLayout' on an empty workspace, /after/ it is called on-    --   the underlying layout, in order to perform some effect in the-    --   X monad, possibly return a new layout modifier, and\/or-    --   modify the results of 'runLayout' before returning them.-    ---    --   If you don't need access to the X monad, then tough luck.-    --   There isn't a pure version of 'emptyLayoutMod'.-    ---    --   The default implementation of 'emptyLayoutMod' ignores its-    --   arguments and returns an empty list of window\/rectangle-    --   pairings.-    ---    --   /NOTE/: 'emptyLayoutMod' will likely be combined with-    --   'redoLayout' soon!-    emptyLayoutMod :: m a -> Rectangle -> [(a, Rectangle)]-                   -> X ([(a, Rectangle)], Maybe (m a))-    emptyLayoutMod _ _ _ = return ([], Nothing)-     -- | 'hook' is called by the default implementation of     --   'redoLayout', and as such represents an X action which is to     --   be run each time 'runLayout' is called on the underlying@@ -256,9 +235,7 @@ instance (LayoutModifier m a, LayoutClass l a) => LayoutClass (ModifiedLayout m l) a where     runLayout (Workspace i (ModifiedLayout m l) ms) r =         do (ws, ml')  <- modifyLayout m (Workspace i l ms) r-           (ws', mm') <- case ms of-                           Just s  -> redoLayout m r s ws-                           Nothing -> emptyLayoutMod m r ws+           (ws', mm') <- redoLayout m r ms ws            let ml'' = case mm' of                         Just m' -> Just $ (ModifiedLayout m') $ maybe l id ml'                         Nothing -> ModifiedLayout m `fmap` ml'
XMonad/Layout/LayoutScreens.hs view
@@ -10,6 +10,7 @@ -- Stability   :  unstable -- Portability :  unportable --+-- Divide a single screen into multiple screens. -----------------------------------------------------------------------------  module XMonad.Layout.LayoutScreens (@@ -38,8 +39,8 @@ -- -- Then add some keybindings; for example: ----- >   , ((modMask x .|. shiftMask,                 xK_space), layoutScreens 2 (TwoPane 0.5 0.5))--- >   , ((modMask x .|. controlMask .|. shiftMask, xK_space), rescreen)+-- >   , ((modm .|. shiftMask,                 xK_space), layoutScreens 2 (TwoPane 0.5 0.5))+-- >   , ((modm .|. controlMask .|. shiftMask, xK_space), rescreen) -- -- Another example use would be to handle a scenario where xrandr didn't -- work properly (e.g. a VNC X server in my case) and you want to be able@@ -47,9 +48,9 @@ -- -- > import XMonad.Layout.LayoutScreens ----- >   , ((modMask x .|. shiftMask, xK_space),+-- >   , ((modm .|. shiftMask, xK_space), -- >        layoutScreens 1 (fixedLayout [Rectangle 0 0 1024 768]))--- >   , ((modMask x .|. controlMask .|. shiftMask, xK_space), rescreen)+-- >   , ((modm .|. controlMask .|. shiftMask, xK_space), rescreen) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".
+ XMonad/Layout/LimitWindows.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.LimitWindows+-- Copyright   :  (c) 2009 Adam Vogt+--                (c) 2009 Max Rabkin -- wrote limitSelect+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  vogt.adam@gmail.com+-- Stability   :  unstable+-- Portability :  unportable+--+-- A layout modifier that limits the number of windows that can be shown.+-- See "XMonad.Layout.Minimize" for manually setting hidden windows.+--+-----------------------------------------------------------------------------++module XMonad.Layout.LimitWindows (+    -- * Usage+    -- $usage++    -- * Layout Modifiers+    limitWindows,limitSlice,limitSelect,++    -- * Change the number of windows+    increaseLimit,decreaseLimit,setLimit+    ) where++import XMonad.Layout.LayoutModifier+import XMonad+import qualified XMonad.StackSet as W+import XMonad.Layout (IncMasterN (..))+import Control.Monad((<=<),guard)+import Control.Applicative((<$>))+import Data.Maybe(fromJust)++-- $usage+-- To use this module, add the following import to @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.LimitWindows+--+-- > myLayout = limitWindows 6 $ Tall 1 0.03 0.5 ||| Full ||| RandomOtherLayout...+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- You may also be interested in dynamically changing the number dynamically,+-- by binding keys to the 'increaseLimit', 'decreaseLimit', or 'setLimit'+-- actions.+--+-- For detailed instructions on editing your key bindings, see+-- "XMonad.Doc.Extending#Editing_key_bindings".+--+-- See also 'XMonad.Layout.BoringWindows.boringAuto' for keybindings that skip+-- the hidden windows.++increaseLimit :: X ()+increaseLimit = sendMessage $ LimitChange succ++decreaseLimit :: X ()+decreaseLimit = sendMessage . LimitChange $ max 1 . pred++setLimit :: Int -> X ()+setLimit tgt = sendMessage . LimitChange $ const tgt++-- | Only display the first @n@ windows.+limitWindows :: Int -> l a -> ModifiedLayout LimitWindows l a+limitWindows n = ModifiedLayout (LimitWindows FirstN n)++-- | Only display @n@ windows around the focused window. This makes sense with+-- layouts that arrange windows linearily, like 'XMonad.Layout.Layout.Accordion'.+limitSlice :: Int -> l a -> ModifiedLayout LimitWindows l a+limitSlice n = ModifiedLayout (LimitWindows Slice n)++-- | Only display the first @m@ windows and @r@ others.+-- The @IncMasterN@ message will change @m@, as well as passing it onto the+-- underlying layout.+limitSelect :: Int -> Int -> l a -> ModifiedLayout Selection l a+limitSelect m r = ModifiedLayout Sel{ nMaster=m, start=m, nRest=r }++data LimitWindows a = LimitWindows SliceStyle Int deriving (Read,Show)++data SliceStyle = FirstN | Slice deriving (Read,Show)++data LimitChange = LimitChange { unLC :: (Int -> Int) } deriving (Typeable)++instance Message LimitChange++instance LayoutModifier LimitWindows a where+     pureMess (LimitWindows s n) =+        fmap (LimitWindows s) . pos <=< (`app` n) . unLC <=< fromMessage+      where pos x   = guard (x>=1)     >> return x+            app f x = guard (f x /= x) >>  return (f x)++     modifyLayout (LimitWindows style n) ws r =+        runLayout ws { W.stack = f n <$> W.stack ws } r+      where f = case style of+                    FirstN -> firstN+                    Slice -> slice++firstN ::  Int -> W.Stack a -> W.Stack a+firstN n st = upfocus $ fromJust $ W.differentiate $ take (max 1 n) $ W.integrate st+    where upfocus = foldr (.) id $ replicate (length (W.up st)) W.focusDown'++-- | A non-wrapping, fixed-size slice of a stack around the focused element+slice ::  Int -> W.Stack t -> W.Stack t+slice n (W.Stack f u d) =+        W.Stack f (take (nu + unusedD) u)+                  (take (nd + unusedU) d)+    where unusedD = max 0 $ nd - length d+          unusedU = max 0 $ nu - length u+          nd = div (n - 1) 2+          nu = uncurry (+) $ divMod (n - 1) 2++data Selection a = Sel { nMaster :: Int, start :: Int, nRest :: Int }+    deriving (Read, Show, Eq)++instance LayoutModifier Selection a where+    modifyLayout s w r =+        runLayout (w { W.stack = updateAndSelect s <$> W.stack w }) r++    pureModifier sel _ stk wins = (wins, update sel <$> stk)++    pureMess sel m+        | Just f <- unLC <$> fromMessage m =+            Just $ sel { nRest = max 0 (f (nMaster sel + nRest sel) - nMaster sel) }+        | Just (IncMasterN n) <- fromMessage m =+            Just $ sel { nMaster = max 0 (nMaster sel + n) }+        | otherwise =+            Nothing++select :: Selection l -> W.Stack a -> W.Stack a+select s stk+    | lups < nMaster s+        = stk { W.down=take (nMaster s - lups - 1) downs +++                    (take (nRest s) . drop (start s - lups - 1) $ downs) }+    | otherwise+        = stk { W.up=reverse (take (nMaster s) ups ++ drop (start s) ups),+                W.down=take ((nRest s) - (lups - start s) - 1) downs }+    where+        downs = W.down stk+        ups = reverse $ W.up stk+        lups = length ups+    +updateStart :: Selection l -> W.Stack a -> Int+updateStart s stk+    | lups < nMaster s  -- the focussed window is in the master pane+        = start s `min` (lups + ldown - (nRest s) + 1) `max` nMaster s+    | otherwise+        = start s `min` lups+                  `max` (lups - (nRest s) + 1)+                  `min` (lups + ldown - (nRest s) + 1)+                  `max` nMaster s+    where+        lups = length $ W.up stk+        ldown = length $ W.down stk++update :: Selection l -> W.Stack a -> Selection a+update sel stk = sel { start=updateStart sel stk }++updateAndSelect :: Selection l -> W.Stack a -> W.Stack a+updateAndSelect sel stk = select (update sel stk) stk
XMonad/Layout/MagicFocus.hs view
@@ -16,13 +16,21 @@ module XMonad.Layout.MagicFocus     (-- * Usage      -- $usage-     magicFocus+     magicFocus,+     promoteWarp,+     promoteWarp',+     followOnlyIf,+     disableFollowOnWS     ) where  import XMonad-import XMonad.StackSet+import qualified XMonad.StackSet as W import XMonad.Layout.LayoutModifier +import XMonad.Actions.UpdatePointer(updatePointer, PointerPosition(TowardsCentre))+import Data.Monoid(All(..))+import qualified Data.Map as M+ -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: --@@ -31,8 +39,9 @@ -- Then edit your @layoutHook@ by adding the magicFocus layout -- modifier: ----- > myLayouts = magicFocus (Tall 1 (3/100) (1/2)) ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = magicFocus (Tall 1 (3/100) (1/2)) ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout,+-- >                               handleEventHook = promoteWarp } -- -- For more detailed instructions on editing the layoutHook see: --@@ -46,10 +55,53 @@ data MagicFocus a = MagicFocus deriving (Show, Read)  instance LayoutModifier MagicFocus Window where-  modifyLayout MagicFocus (Workspace i l s) r =+  modifyLayout MagicFocus (W.Workspace i l s) r =     withWindowSet $ \wset ->-      runLayout (Workspace i l (s >>= \st -> Just $ swap st (peek wset))) r+      runLayout (W.Workspace i l (s >>= \st -> Just $ swap st (W.peek wset))) r -swap :: (Eq a) => Stack a -> Maybe a -> Stack a-swap (Stack f u d) focused | Just f == focused = Stack f [] (reverse u ++ d)-                           | otherwise         = Stack f u d+swap :: (Eq a) => W.Stack a -> Maybe a -> W.Stack a+swap (W.Stack f u d) focused+    | Just f == focused = W.Stack f [] (reverse u ++ d)+    | otherwise         = W.Stack f u d++-- | An eventHook that overrides the normal focusFollowsMouse. When the mouse+-- it moved to another window, that window is replaced as the master, and the+-- mouse is warped to inside the new master.+--+-- It prevents infinite loops when focusFollowsMouse is true (the default), and+-- MagicFocus is in use when changing focus with the mouse.+--+-- This eventHook does nothing when there are floating windows on the current+-- workspace.+promoteWarp :: Event -> X All+promoteWarp = promoteWarp' (TowardsCentre 0.15 0.15)++-- | promoteWarp' allows you to specify an arbitrary PointerPosition to apply+-- when the mouse enters another window.+promoteWarp' :: PointerPosition -> Event -> X All+promoteWarp' pos e@(CrossingEvent {ev_window = w, ev_event_type = t})+    | t == enterNotify && ev_mode   e == notifyNormal = do+        ws <- gets windowset+        let foc = W.peek ws+            st = W.integrate' . W.stack . W.workspace $ W.current ws+            wsFloats = M.filterWithKey (\k _ -> k `elem` st) $ W.floating ws+        if Just w /= foc && M.null wsFloats then do+            windows (W.swapMaster . W.focusWindow w)+            updatePointer pos+            return $ All False+          else return $ All True+promoteWarp' _ _ = return $ All True++-- | Another event hook to override the focusFollowsMouse and make the pointer+-- only follow if a given condition is satisfied. This could be used to disable+-- focusFollowsMouse only for given workspaces or layouts.+-- Beware that your focusFollowsMouse setting is ignored if you use this event hook.+followOnlyIf :: X Bool -> Event -> X All+followOnlyIf cond e@(CrossingEvent {ev_window = w, ev_event_type = t})+    | t == enterNotify && ev_mode e == notifyNormal+    = whenX cond (focus w) >> return (All False)+followOnlyIf _ _ = return $ All True++-- | Disables focusFollow on the given workspaces:+disableFollowOnWS :: [WorkspaceId] -> X Bool+disableFollowOnWS wses = (`notElem` wses) `fmap` gets (W.currentTag . windowset)
XMonad/Layout/Magnifier.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses, TypeSynonymInstances, PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.Magnifier@@ -41,8 +41,8 @@ -- Then edit your @layoutHook@ by adding the 'magnifier' layout modifier -- to some layout: ----- > myLayouts = magnifier (Tall 1 (3/100) (1/2))  ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = magnifier (Tall 1 (3/100) (1/2))  ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- By default magnifier increases the focused window's size by 1.5. -- You can also use:@@ -59,11 +59,11 @@ -- Magnifier supports some commands. To use them add something like -- this to your key bindings: ----- >    , ((modMask x .|. controlMask              , xK_plus ), sendMessage MagnifyMore)--- >    , ((modMask x .|. controlMask              , xK_minus), sendMessage MagnifyLess)--- >    , ((modMask x .|. controlMask              , xK_o    ), sendMessage ToggleOff  )--- >    , ((modMask x .|. controlMask .|. shiftMask, xK_o    ), sendMessage ToggleOn   )--- >    , ((modMask x .|. controlMask              , xK_m    ), sendMessage Toggle     )+-- >    , ((modm .|. controlMask              , xK_plus ), sendMessage MagnifyMore)+-- >    , ((modm .|. controlMask              , xK_minus), sendMessage MagnifyLess)+-- >    , ((modm .|. controlMask              , xK_o    ), sendMessage ToggleOff  )+-- >    , ((modm .|. controlMask .|. shiftMask, xK_o    ), sendMessage ToggleOn   )+-- >    , ((modm .|. controlMask              , xK_m    ), sendMessage Toggle     ) -- -- Note that a few other extension modules, such as -- "XMonad.Layout.MultiToggle" and "XMonad.Layout.ToggleLayouts", also@@ -114,14 +114,13 @@ data MagnifyMaster = All | NoMaster deriving  (Read, Show)  instance LayoutModifier Magnifier Window where-    redoLayout  (Mag z On All     ) = applyMagnifier z-    redoLayout  (Mag z On NoMaster) = unlessMaster $ applyMagnifier z-    redoLayout  _                   = nothing-        where nothing _ _ wrs = return (wrs, Nothing)+    redoLayout  (Mag z On All     ) r (Just s) wrs = applyMagnifier z r s wrs+    redoLayout  (Mag z On NoMaster) r (Just s) wrs = unlessMaster (applyMagnifier z) r s wrs+    redoLayout  _                   _ _        wrs = return (wrs, Nothing)      handleMess (Mag z On  t) m-                    | Just MagnifyMore <- fromMessage m = return . Just $ (Mag (z `addto` 0.1) On  t)-                    | Just MagnifyLess <- fromMessage m = return . Just $ (Mag (z `addto` 0.1) On  t)+                    | Just MagnifyMore <- fromMessage m = return . Just $ (Mag (z `addto`   0.1 ) On  t)+                    | Just MagnifyLess <- fromMessage m = return . Just $ (Mag (z `addto` (-0.1)) On  t)                     | Just ToggleOff   <- fromMessage m = return . Just $ (Mag (z      ) Off t)                     | Just Toggle      <- fromMessage m = return . Just $ (Mag (z      ) Off t)                     where addto (x,y) i = (x+i,y+i)
XMonad/Layout/Master.hs view
@@ -1,110 +1,86 @@-{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleContexts #-}-{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances, FlexibleContexts, PatternGuards #-}  ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.Master--- Copyright   :  (c) Lukas Mai+-- Copyright   :  (c) Ismael Carnales, Lukas Mai -- License     :  BSD-style (see LICENSE) ----- Maintainer  :  <l.mai@web.de>+-- Maintainer  :  Ismael Carnales <icarnales@gmail.com> -- Stability   :  unstable -- Portability :  unportable ----- A layout that adds a distinguished master window to a base layout.+-- Layout modfier that adds a master window to another layout. -----------------------------------------------------------------------------  module XMonad.Layout.Master (     -- * Usage     -- $usage-    mastered,-    Master++    mastered ) where  import XMonad-import XMonad.StackSet--import Data.List-import Data.Ord+import qualified XMonad.StackSet as S+import XMonad.Layout.LayoutModifier  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Layout.Master ----- and add something like+-- Then edit your @layoutHook@ and add the Master modifier to the layout that+-- you prefer. -- -- > mastered (1/100) (1/2) $ Grid ----- to your layouts. This will use the left half of your screen for a master--- window and let Grid manage the right half.+-- This will use the left half of your screen for a master window and let+-- Grid manage the right half. -- -- For more detailed instructions on editing the layoutHook see -- "XMonad.Doc.Extending#Editing_the_layout_hook". ----- Like 'XMonad.Layout.Tall', 'Master' supports the 'XMonad.Layout.Shrink' and--- 'XMonad.Layout.Expand' messages.+-- Like 'XMonad.Layout.Tall', 'withMaster' supports the+-- 'XMonad.Layout.Shrink' and XMonad.Layout.Expand' messages. -mastered :: (LayoutClass l a)-    => Rational -- ^ @delta@, the ratio of the screen to resize by-    -> Rational -- ^ @frac@, what portion of the screen to reserve for the master window-    -> l a      -- ^ the layout to use for the remaining windows-    -> Master l a-mastered d f b = Master d f' b-    where-    f' = min 1 . max 0 $ f+-- | Data type for LayoutModifier which converts given layout to a mastered+-- layout+data AddMaster a = AddMaster Rational Rational deriving (Show, Read) -data Master l a =-    Master{-        delta :: Rational,-        frac :: Rational,-        base :: l a-    } deriving (Show, Read, Eq, Ord)+-- | Modifier which converts given layout to a mastered one+mastered :: (LayoutClass l a) =>+       Rational -- ^ @delta@, the ratio of the screen to resize by+    -> Rational -- ^ @frac@, what portion of the screen to use for the master window+    -> l a      -- ^ the layout to be modified+    -> ModifiedLayout AddMaster l a+mastered delta frac = ModifiedLayout $ AddMaster delta frac -extractMaster :: Stack a -> (a, Maybe (Stack a))-extractMaster (Stack x ls rs) = case reverse ls of-    [] -> (x, differentiate rs)-    (m : ls') -> (m, Just $ Stack x (reverse ls') rs)+instance LayoutModifier AddMaster Window where+    modifyLayout (AddMaster delta frac) = applyMaster delta frac+    modifierDescription _               = "Mastered" -area :: Rectangle -> Dimension-area r = rect_width r * rect_height r+    pureMess (AddMaster delta frac) m+        | Just Shrink <- fromMessage m = Just $ AddMaster delta (frac-delta)+        | Just Expand <- fromMessage m = Just $ AddMaster delta (frac+delta) -chop :: D -> Rectangle -> Rectangle-chop (w, h) (Rectangle rx ry rw rh) =-    let-        r' = maximumBy (comparing area)-            [ Rectangle rx (ry + fromIntegral h) rw (rh - h)-            , Rectangle (rx + fromIntegral w) ry (rw - w) rh]-    in-    r'{ rect_width = max 0 $ rect_width r', rect_height = max 0 $ rect_height r' }+    pureMess _ _ = Nothing -instance (LayoutClass l Window) => LayoutClass (Master l) Window where-    description m = "Master " ++ description (base m)-    handleMessage m msg-        | Just Shrink <- fromMessage msg =-            return . Just $ m{ frac = max 0 $ frac m - delta m }-        | Just Expand <- fromMessage msg =-            return . Just $ m{ frac = min 1 $ frac m + delta m }-        | otherwise =-            fmap (fmap (\x -> m{ base = x })) $ handleMessage (base m) msg-    runLayout ws rect = do-        (f, ws', rect') <- case fmap extractMaster $ stack ws of-            Nothing ->-                return (id, ws, rect)-            Just (x, Nothing) -> do-                f <- mkAdjust x-                let-                    (w', h') = f (rect_width rect, rect_height rect)-                    xr = rect{ rect_width = w', rect_height = h' }-                return (((x, xr) :), ws{ stack = Nothing }, Rectangle (rect_x xr + fromIntegral w') (rect_y xr) 0 0)-            Just (x, Just st) -> do-                f <- mkAdjust x-                let-                    d@(w', h') = f (scale $ rect_width rect, rect_height rect)-                    xr = rect{ rect_width = w', rect_height = h' }-                return (((x, xr) :), ws{ stack = Just st }, chop d rect)-        (y, l) <- runLayout ws'{ layout = base m } rect'-        return (f y, fmap (\x -> m{ base = x }) l)-        where-        m = layout ws-        scale = round . (* frac m) . fromIntegral+-- | Internal function for adding a master window and let the modified+-- layout handle the rest of the windows+applyMaster :: (LayoutClass l Window) =>+                  Rational+               -> Rational+               -> S.Workspace WorkspaceId (l Window) Window+               -> Rectangle+               -> X ([(Window, Rectangle)], Maybe (l Window))+applyMaster _ frac wksp rect = do+    let st= S.stack wksp+    let ws = S.integrate' $ st+    if length ws > 1 then do+        let m = head ws+        let (mr, sr) = splitHorizontallyBy frac rect+        let nst = st>>= S.filter (m/=)+        wrs <- runLayout (wksp {S.stack = nst}) sr+        return ((m, mr) : fst wrs, snd wrs)++        else runLayout wksp rect
XMonad/Layout/Maximize.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}  ----------------------------------------------------------------------------- -- |@@ -24,6 +23,7 @@     ) where  import XMonad+import qualified XMonad.StackSet as S import XMonad.Layout.LayoutModifier import Data.List ( partition ) @@ -34,8 +34,8 @@ -- -- Then edit your @layoutHook@ by adding the Maximize layout modifier: ----- > myLayouts = maximize (Tall 1 (3/100) (1/2)) ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = maximize (Tall 1 (3/100) (1/2)) ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -43,7 +43,7 @@ -- -- In the key-bindings, do something like: ----- >        , ((modMask x, xK_backslash), withFocused (sendMessage . maximizeRestore))+-- >        , ((modm, xK_backslash), withFocused (sendMessage . maximizeRestore)) -- >        ... -- -- For detailed instruction on editing the key binding see:@@ -61,19 +61,23 @@  instance LayoutModifier Maximize Window where     modifierDescription (Maximize _) = "Maximize"-    redoLayout (Maximize mw) rect _ wrs = case mw of-        Just win ->-                return (maxed ++ rest, Nothing)-            where-                maxed = map (\(w, _) -> (w, maxRect)) toMax-                (toMax, rest) = partition (\(w, _) -> w == win) wrs-                maxRect = Rectangle (rect_x rect + 50) (rect_y rect + 50)-                    (rect_width rect - 100) (rect_height rect - 100)-        Nothing -> return (wrs, Nothing)-    handleMess (Maximize mw) m = case fromMessage m of+    pureModifier (Maximize (Just target)) rect (Just (S.Stack focused _ _)) wrs =+            if focused == target+                then (maxed ++ rest, Nothing)+                else (rest ++ maxed, Nothing)+        where+            (toMax, rest) = partition (\(w, _) -> w == target) wrs+            maxed = map (\(w, _) -> (w, maxRect)) toMax+            maxRect = Rectangle (rect_x rect + 25) (rect_y rect + 25)+                (rect_width rect - 50) (rect_height rect - 50)+    pureModifier _ _ _ wrs = (wrs, Nothing)++    pureMess (Maximize mw) m = case fromMessage m of         Just (MaximizeRestore w) -> case mw of-            Just _ -> return $ Just $ Maximize Nothing-            Nothing -> return $ Just $ Maximize $ Just w-        _ -> return Nothing+            Just w' -> if (w == w')+                        then Just $ Maximize Nothing   -- restore window+                        else Just $ Maximize $ Just w  -- maximize different window+            Nothing -> Just $ Maximize $ Just w        -- maximize window+        _ -> Nothing  -- vim: sw=4:et
+ XMonad/Layout/MessageControl.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.MessageControl+-- Copyright   :  (c) 2008 Quentin Moser+-- License     :  BSD3+--+-- Maintainer  :  <quentin.moser@unifr.ch>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Provides message \"escaping\" and filtering facilities which+-- help control complex nested layouts.+-----------------------------------------------------------------------------++module XMonad.Layout.MessageControl (+                               -- * Usage+                               -- $usage+                            Ignore()+                          , ignore+                          , UnEscape()+                          , unEscape+                          , EscapedMessage(Escape)+                          , escape+                          ) where++import XMonad.Core (Message, SomeMessage(..)+                   , fromMessage, LayoutClass(..))+import XMonad.StackSet (Workspace(..))++import XMonad.Layout.LayoutModifier (LayoutModifier(..), ModifiedLayout(..))++import Data.Typeable (Typeable)+import Control.Applicative ((<$>))+import Control.Arrow (second)++-- $usage+-- You can use this module by importing it into your @~\/.xmonad\/xmonad.hs@ file:+--+-- > import XMonad.Layout.MessageEscape+--+-- Then, if you use a modified layout where the modifier would intercept+-- a message, but you'd want to be able to send it to the inner layout +-- only, add the 'unEscape' modifier to the inner layout like so:+--+-- > import XMonad.Layout.Master (mastered)+-- > import XMonad.Layout.Tabbed (simpleTabbed)+-- > import XMonad.Layout.LayoutCombinators ((|||))+-- >+-- > myLayout = Tall ||| unEscape (mastered 0.01 0.5 $ Full ||| simpleTabbed)+--+-- you can now send a message to the inner layout with+--  @sendMessage $ escape message@, e.g.+--+-- > -- Change the inner layout+-- > ((modm .|. controlMask, xK_space), sendMessage $ escape NextLayout)+--+-- If you want unescaped messages to be handled /only/ by the enclosing+-- layout, use the 'ignore' modifier:+--+-- > myLayout = Tall ||| (ignore NextLayout $ ignore (JumpToLayout "") $+-- >                       unEscape $ mastered 0.01 0.5 +-- >                         $ Full ||| simpleTabbed)+--+-- /IMPORTANT NOTE:/ The standard '(|||)' operator from "XMonad.Layout"+-- does not behave correctly with 'ignore'. Make sure you use the one+-- from "XMonad.Layout.LayoutCombinators".++-- | the Ignore layout modifier. Prevents its inner layout from receiving+-- messages of a certain type.++data Ignore m l w = I (l w)+                    deriving (Show, Read)++instance (Message m, LayoutClass l w) => LayoutClass (Ignore m l) w where+    runLayout ws r = second (I <$>) <$> runLayout (unILayout ws) r+        where  unILayout :: Workspace i (Ignore m l w) w -> Workspace i (l w) w+               unILayout w@(Workspace { layout = (I l) }) = w { layout = l }+    handleMessage l@(I l') sm+        = case fromMessageAs sm l of+            Just _ -> return Nothing+            Nothing -> (I <$>) <$> handleMessage l' sm+        where fromMessageAs :: Message m' => SomeMessage -> Ignore m' l w -> Maybe m'+              fromMessageAs a _ = fromMessage a+    description (I l) = "Ignore "++description l++-- | the UnEscape layout modifier. Listens to 'EscapedMessage's and sends+-- their nested message to the inner layout.++data UnEscape w = UE+                deriving (Show, Read)++instance LayoutModifier UnEscape a where+    handleMessOrMaybeModifyIt _ mess+        = return $ case fromMessage mess of+                     Just (Escape mess') -> Just $ Right mess'+                     Nothing -> Nothing+++-- | Data type for an escaped message. Send with 'escape'.++newtype EscapedMessage = Escape SomeMessage+    deriving Typeable++instance Message EscapedMessage+++-- | Creates an 'EscapedMessage'.++escape :: Message m => m -> EscapedMessage+escape = Escape . SomeMessage+++-- | Applies the UnEscape layout modifier to a layout.++unEscape :: LayoutClass l w => l w -> ModifiedLayout UnEscape l w+unEscape l = ModifiedLayout UE l+++-- | Applies the Ignore layout modifier to a layout, blocking+-- all messages of the same type as the one passed as its first argument.++ignore :: (Message m, LayoutClass l w) +          => m -> l w -> (Ignore m l w)+ignore _ l = I l
+ XMonad/Layout/Minimize.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE MultiParamTypeClasses, DeriveDataTypeable, TypeSynonymInstances, FlexibleContexts #-}+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.Minimize+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- Makes it possible to minimize windows, temporarily removing them+-- from the layout until they are restored.+--+-----------------------------------------------------------------------------++module XMonad.Layout.Minimize (+        -- * Usage+        -- $usage+        minimize,+        MinimizeMsg(..)+    ) where++import XMonad+import qualified XMonad.StackSet as W+import XMonad.Layout.LayoutModifier+import XMonad.Layout.BoringWindows as BW+import Data.List++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.Minimize+--+-- Then edit your @layoutHook@ by adding the Minimize layout modifier:+--+-- > myLayout = minimize (Tall 1 (3/100) (1/2)) ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+--+-- In the key-bindings, do something like:+--+-- >        , ((modm,               xK_m     ), withFocused (\f -> sendMessage (MinimizeWin f)))+-- >        , ((modm .|. shiftMask, xK_m     ), sendMessage RestoreNextMinimizedWin)+--+-- The first action will minimize the focused window, while the second one will restore+-- the next minimized window.+--+-- For detailed instruction on editing the key binding see:+--+-- "XMonad.Doc.Extending#Editing_key_bindings".+--+-- The module is designed to work together with "XMonad.Layout.BoringWindows" so+-- that minimized windows will be skipped when switching the focus window with+-- the keyboard.  Use the 'BW.boringAuto' function.+--+-- Also see "XMonad.Hooks.RestoreMinimized" if you want to be able to restore+-- minimized windows from your taskbar.++data Minimize a = Minimize [Window] deriving ( Read, Show )+minimize :: LayoutClass l Window => l Window -> ModifiedLayout Minimize l Window+minimize = ModifiedLayout $ Minimize []++data MinimizeMsg = MinimizeWin Window+                    | RestoreMinimizedWin Window+                    | RestoreNextMinimizedWin+                    deriving (Typeable, Eq)+instance Message MinimizeMsg++instance LayoutModifier Minimize Window where+    modifierDescription (Minimize _) = "Minimize"++    modifyLayout (Minimize minimized) wksp rect = do+        let stack = W.stack wksp+            filtStack = stack >>=W.filter (\w -> not (w `elem` minimized))+        runLayout (wksp {W.stack = filtStack}) rect++    handleMess (Minimize minimized) m = case fromMessage m of+        Just (MinimizeWin w)+          | not (w `elem` minimized) -> do+                BW.focusDown+                return $ Just $ Minimize (w:minimized)+          | otherwise               -> return Nothing+        Just (RestoreMinimizedWin w) ->+            return $ Just $ Minimize (minimized \\ [w])+        Just (RestoreNextMinimizedWin)+          | not (null minimized)    -> do+                focus (head minimized)+                return $ Just $ Minimize (tail minimized)+          | otherwise               -> return Nothing+        _ -> return Nothing
+ XMonad/Layout/Monitor.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, DeriveDataTypeable, PatternGuards #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.Monitor+-- Copyright   :  (c) Roman Cheplyaka+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Roman Cheplyaka <roma@ro-che.info>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Layout modfier for displaying some window (monitor) above other windows+--+-----------------------------------------------------------------------------+module XMonad.Layout.Monitor (+    -- * Usage+    -- $usage++    -- * Hints and issues+    -- $hints++    Monitor(..),+    monitor,+    Property(..),+    MonitorMessage(..),+    doHideIgnore,+    manageMonitor++    -- * TODO+    -- $todo+    ) where++import XMonad+import XMonad.Layout.LayoutModifier+import XMonad.Util.WindowProperties+import XMonad.Hooks.ManageHelpers (doHideIgnore)+import XMonad.Hooks.FadeInactive (setOpacity)+import Control.Monad++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.Monitor+--+-- Define 'Monitor' record. 'monitor' can be used as a template. At least 'prop'+-- and 'rect' should be set here. Also consider setting 'persistent' to True.+--+-- Minimal example:+--+-- > myMonitor = monitor+-- >     { prop = ClassName "SomeClass"+-- >     , rect = Rectangle 0 0 40 20 -- rectangle 40x20 in upper left corner+-- >     }+--+-- More interesting example:+--+-- > clock = monitor {+-- >      -- Cairo-clock creates 2 windows with the same classname, thus also using title+-- >      prop = ClassName "Cairo-clock" `And` Title "MacSlow's Cairo-Clock"+-- >      -- rectangle 150x150 in lower right corner, assuming 1280x800 resolution+-- >    , rect = Rectangle (1280-150) (800-150) 150 150+-- >      -- avoid flickering+-- >    , persistent = True+-- >      -- make the window transparent+-- >    , opacity = 0.6+-- >      -- hide on start+-- >    , visible = False+-- >      -- assign it a name to be able to toggle it independently of others+-- >    , name = "clock"+-- >    }+--+-- Add ManageHook to de-manage monitor windows and apply opacity settings.+--+-- > manageHook = myManageHook <+> manageMonitor clock+--+-- Apply layout modifier.+--+-- > myLayout = ModifiedLayout clock $ tall ||| Full ||| ...+--+-- After that, if there exists a window with specified properties, it will be+-- displayed on top of all /tiled/ (not floated) windows on specified+-- position.+--+-- It's also useful to add some keybinding to toggle monitor visibility:+--+-- > , ((mod1Mask, xK_u     ), broadcastMessage ToggleMonitor >> refresh)+--+-- Screenshot: <http://www.haskell.org/haskellwiki/Image:Xmonad-clock.png>++data Monitor a = Monitor+    { prop :: Property    -- ^ property which uniquely identifies monitor window+    , rect :: Rectangle   -- ^ specifies where to put monitor+    , visible :: Bool     -- ^ is it visible by default?+    , name :: String      -- ^ name of monitor (useful when we have many of them)+    , persistent :: Bool  -- ^ is it shown on all layouts?+    , opacity :: Rational -- ^ opacity level+    } deriving (Read, Show)++-- | Template for 'Monitor' record. At least 'prop' and 'rect' should be+-- redefined. Default settings: 'visible' is 'True', 'persistent' is 'False'.+monitor :: Monitor a+monitor = Monitor+    { prop = Const False+    , rect = Rectangle 0 0 0 0+    , visible = True+    , name = ""+    , persistent = False+    , opacity = 1+    }++-- | Messages without names affect all monitors. Messages with names affect only+-- monitors whose names match.+data MonitorMessage = ToggleMonitor | ShowMonitor | HideMonitor+                    | ToggleMonitorNamed String+                    | ShowMonitorNamed String+                    | HideMonitorNamed String+    deriving (Read,Show,Eq,Typeable)+instance Message MonitorMessage++withMonitor :: Property -> a -> (Window -> X a) -> X a+withMonitor p a fn = do+    monitorWindows <- allWithProperty p+    case monitorWindows of+        [] -> return a+        w:_ -> fn w++instance LayoutModifier Monitor Window where+    redoLayout mon _ _ rects = withMonitor (prop mon) (rects, Nothing) $ \w ->+        if visible mon+            then do tileWindow w (rect mon)+                    reveal w+                    return ((w,rect mon):rects, Nothing)+            else do hide w+                    return (rects, Nothing)+    handleMess mon mess+        | Just ToggleMonitor <- fromMessage mess = return $ Just $ mon { visible = not $ visible mon }+        | Just (ToggleMonitorNamed n) <- fromMessage mess = return $+            if name mon == n then Just $ mon { visible = not $ visible mon } else Nothing+        | Just ShowMonitor <- fromMessage mess = return $ Just $ mon { visible = True }+        | Just (ShowMonitorNamed n) <- fromMessage mess = return $+            if name mon == n then Just $ mon { visible = True } else Nothing+        | Just HideMonitor <- fromMessage mess = return $ Just $ mon { visible = False }+        | Just (HideMonitorNamed n) <- fromMessage mess = return $+            if name mon == n then Just $ mon { visible = False } else Nothing+        | Just Hide <- fromMessage mess = do unless (persistent mon) $ withMonitor (prop mon) () hide; return Nothing+        | otherwise = return Nothing++-- | ManageHook which demanages monitor window and applies opacity settings.+manageMonitor :: Monitor a -> ManageHook+manageMonitor mon = propertyToQuery (prop mon) --> do+    w <- ask+    liftX $ setOpacity w $ opacity mon+    if persistent mon then doIgnore else doHideIgnore++-- $hints+-- - This module assumes that there is only one window satisfying property exists.+--+-- - If your monitor is available on /all/ layouts, set+-- 'persistent' to 'True' to avoid unnecessary+-- flickering. You can still toggle monitor with a keybinding.+--+-- - You can use several monitors with nested modifiers. Give them names+---  to be able to toggle them independently.+--+-- - You can display monitor only on specific workspaces with+-- "XMonad.Layout.PerWorkspace".++-- $todo+-- - make Monitor remember the window it manages+--+-- - specify position relative to the screen
+ XMonad/Layout/Mosaic.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.Mosaic+-- Copyright   :  (c) 2009 Adam Vogt, 2007 James Webb+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  vogt.adam<at>gmail.com+-- Stability   :  unstable+-- Portability :  unportable+--+-- Based on MosaicAlt, but aspect ratio messages always change the aspect+-- ratios, and rearranging the window stack changes the window sizes.+--+-----------------------------------------------------------------------------++module XMonad.Layout.Mosaic (+    -- * Usage+    -- $usage+     Aspect(..)+    ,mosaic+    ,changeMaster+    ,changeFocused+    )+    where++import Prelude hiding (sum)++import XMonad(Typeable,+              LayoutClass(doLayout, handleMessage, pureMessage, description),+              Message, X, fromMessage, withWindowSet, Resize(..),+              splitHorizontallyBy, splitVerticallyBy, sendMessage, Rectangle)+import qualified XMonad.StackSet as W+import Control.Arrow(second, first)+import Control.Monad(mplus)+import Data.Foldable(Foldable,foldMap, sum)+import Data.Function(on)+import Data.List(sortBy)+import Data.Monoid(Monoid,mempty, mappend)+++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.Mosaic+--+-- Then edit your @layoutHook@ by adding the Mosaic layout:+--+-- > myLayout = mosaic 2 [3,2] ||| Full ||| etc..+-- > main = xmonad $ defaultConfig { layoutHook = myLayout }+--+-- Unfortunately, infinite lists break serialization, so don't use them. And if+-- the list is too short, it is extended with @++ repeat 1@, which covers the+-- main use case.+--+-- To change the choice in aspect ratio and the relative sizes of windows, add+-- to your keybindings:+--+--  > , ((modm, xK_a), sendMessage Taller)+--  > , ((modm, xK_z), sendMessage Wider)+--+--  > , ((modm, xK_r), sendMessage Reset)+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"++data Aspect+    = Taller+    | Wider+    | Reset+    | SlopeMod ([Rational] -> [Rational])+    deriving (Typeable)++instance Message Aspect++-- | The relative magnitudes (the sign is ignored) of the rational numbers in+-- the second argument determine the relative areas that the windows receive.+-- The first number represents the size of the master window, the second is for+-- the next window in the stack, and so on.+--+-- The list is extended with @++ repeat 1@, so @mosaic 1.5 []@ is like a+-- resizable grid.+--+-- The first parameter is the multiplicative factor to use when responding to+-- the 'Expand' message.+mosaic :: Rational -> [Rational] -> Mosaic a+mosaic = Mosaic Nothing++data Mosaic a = -- | True to override the aspect, current index, maximum index+                Mosaic (Maybe(Bool,Rational,Int)) Rational [Rational] deriving (Read,Show)++instance LayoutClass Mosaic a where+    description = const "Mosaic"++    pureMessage (Mosaic Nothing _ _) _ = Nothing+    pureMessage (Mosaic (Just(_,ix,mix)) delta ss) ms = fromMessage ms >>= ixMod+        where ixMod Taller | round ix >= mix = Nothing+                           | otherwise = Just $ Mosaic (Just(False,succ ix,mix)) delta ss+              ixMod Wider  | round ix <= (0::Integer) = Nothing+                           | otherwise = Just $ Mosaic (Just(False,pred ix,mix)) delta ss+              ixMod Reset              = Just $ Mosaic Nothing delta ss+              ixMod (SlopeMod f)       = Just $ Mosaic (Just(False,ix,mix)) delta (f ss)++    handleMessage l@(Mosaic _ delta _) ms+        | Just Expand <- fromMessage ms = changeFocused (*delta) >> return Nothing+        | Just Shrink <- fromMessage ms = changeFocused (/delta) >> return Nothing+        | otherwise = return $ pureMessage l ms++    doLayout (Mosaic state delta ss) r st = let+        ssExt = zipWith const (ss ++ repeat 1) $ W.integrate st+        rects = splits r ssExt+        nls = length rects+        fi = fromIntegral+        nextIx (ov,ix,mix)+                | mix <= 0 || ov = fromIntegral $ nls `div` 2+                | otherwise = max 0 $ (*fi (pred nls)) $ min 1 $ ix / fi mix+        rect = rects !! maybe (nls `div` 2) round (nextIx `fmap` state)+        state' = fmap (\x@(ov,_,_) -> (ov,nextIx x,pred nls)) state+                    `mplus` Just (True,fromIntegral nls / 2,pred nls)+        ss' = maybe ss (const ss `either` const ssExt) $ zipRemain ss ssExt+        in return (zip (W.integrate st) rect, Just $ Mosaic state' delta ss')++zipRemain :: [a] -> [b] -> Maybe (Either [a] [b])+zipRemain (_:xs) (_:ys) = zipRemain xs ys+zipRemain [] [] = Nothing+zipRemain [] y = Just (Right y)+zipRemain x [] = Just (Left x)++-- | These sample functions are meant to be applied to the list of window sizes+-- through the 'SlopeMod' message.+changeMaster :: (Rational -> Rational) -> X ()+changeMaster = sendMessage . SlopeMod . onHead++-- | Apply a function to the Rational that represents the currently focused+-- window.+--+-- 'Expand' and 'Shrink' messages are responded to with @changeFocused+-- (*delta)@ or @changeFocused (delta/)@ where @delta@ is the first argument to+-- 'mosaic'.+--+-- This is exported because other functions (ex. @const 1@, @(+1)@) may be+-- useful to apply to the current area.+changeFocused :: (Rational -> Rational) -> X ()+changeFocused f = withWindowSet $ sendMessage . SlopeMod+                    . maybe id (mulIx . length . W.up)+                    . W.stack . W.workspace . W.current+    where mulIx i = uncurry (++) . second (onHead f) . splitAt i++onHead :: (a -> a) -> [a] -> [a]+onHead f = uncurry (++) . first (fmap f) . splitAt 1++splits :: Rectangle -> [Rational] -> [[Rectangle]]+splits rect = map (reverse . map snd . sortBy (compare `on` fst))+                . splitsL rect . makeTree snd . zip [1..]+                . normalize . reverse . map abs++splitsL :: Rectangle -> Tree (Int,Rational) -> [[(Int,Rectangle)]]+splitsL _rect Empty = []+splitsL rect (Leaf (x,_)) = [[(x,rect)]]+splitsL rect (Branch l r) = do+    let mkSplit f = f ((sumSnd l /) $ sumSnd l + sumSnd r) rect+        sumSnd = sum . fmap snd+    (rl,rr) <- map mkSplit [splitVerticallyBy,splitHorizontallyBy]+    splitsL rl l `interleave` splitsL rr r++-- like zipWith (++), but when one list is shorter, its elements are duplicated+-- so that they match+interleave :: [[a]] -> [[a]] -> [[a]]+interleave xs ys | lx > ly = zc xs (extend lx ys)+                 | otherwise = zc (extend ly xs) ys+  where lx = length xs+        ly = length ys+        zc = zipWith (++)++        extend :: Int -> [a] -> [a]+        extend n pat = do+            (p,e) <- zip pat $ replicate m True ++ repeat False+            [p | e] ++ replicate d p+            where (d,m) = n `divMod` length pat++normalize :: Fractional a => [a] -> [a]+normalize x = let s = sum x in map (/s) x++data Tree a = Branch (Tree a) (Tree a) | Leaf a | Empty++instance Foldable Tree where+   foldMap _f Empty = mempty+   foldMap f (Leaf x) = f x+   foldMap f (Branch l r) = foldMap f l `mappend` foldMap f r++instance Functor Tree where+   fmap f (Leaf x) = Leaf $ f x+   fmap f (Branch l r) = Branch (fmap f l) (fmap f r)+   fmap _ Empty = Empty++instance Monoid (Tree a) where+    mempty = Empty+    mappend Empty x = x+    mappend x Empty = x+    mappend x y = Branch x y++makeTree ::  (Num a1, Ord a1) => (a -> a1) -> [a] -> Tree a+makeTree _ [] = Empty+makeTree _ [x] = Leaf x+makeTree f xs = Branch (makeTree f a) (makeTree f b)+    where ((a,b),_) = foldr go (([],[]),(0,0)) xs+          go n ((ls,rs),(l,r))+            | l > r     = ((ls,n:rs),(l,f n+r))+            | otherwise = ((n:ls,rs),(f n+l,r))
XMonad/Layout/MosaicAlt.hs view
@@ -1,17 +1,16 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances #-}+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances #-}  ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.MosaicAlt -- Copyright   :  (c) 2007 James Webb -- License     :  BSD-style (see xmonad/LICENSE)--- +-- -- Maintainer  :  xmonad#jwebb,sygneca,com -- Stability   :  unstable -- Portability :  unportable ----- A layout which gives each window a specified amount of screen space +-- A layout which gives each window a specified amount of screen space -- relative to the others. Compared to the 'Mosaic' layout, this one -- divides the space in a more balanced way. --@@ -42,8 +41,8 @@ -- -- Then edit your @layoutHook@ by adding the MosaicAlt layout: ----- > myLayouts = MosaicAlt M.empty ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = MosaicAlt M.empty ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -51,11 +50,11 @@ -- -- In the key-bindings, do something like: ----- >     , ((modMask x .|. shiftMask  , xK_a    ), withFocused (sendMessage . expandWindowAlt))--- >     , ((modMask x .|. shiftMask  , xK_z    ), withFocused (sendMessage . shrinkWindowAlt))--- >     , ((modMask x .|. shiftMask  , xK_s    ), withFocused (sendMessage . tallWindowAlt))--- >     , ((modMask x .|. shiftMask  , xK_d    ), withFocused (sendMessage . wideWindowAlt))--- >     , ((modMask x .|. controlMask, xK_space), sendMessage resetAlt)+-- >     , ((modm .|. shiftMask  , xK_a    ), withFocused (sendMessage . expandWindowAlt))+-- >     , ((modm .|. shiftMask  , xK_z    ), withFocused (sendMessage . shrinkWindowAlt))+-- >     , ((modm .|. shiftMask  , xK_s    ), withFocused (sendMessage . tallWindowAlt))+-- >     , ((modm .|. shiftMask  , xK_d    ), withFocused (sendMessage . wideWindowAlt))+-- >     , ((modm .|. controlMask, xK_space), sendMessage resetAlt) -- >     ... -- -- For detailed instruction on editing the key binding see:
+ XMonad/Layout/MouseResizableTile.hs view
@@ -0,0 +1,271 @@+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.MouseResizableTile+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- A layout in the spirit of "XMonad.Layout.ResizableTile", but with the option+-- to use the mouse to adjust the layout.+--+-----------------------------------------------------------------------------++module XMonad.Layout.MouseResizableTile (+                                    -- * Usage+                                    -- $usage+                                    mouseResizableTile,+                                    mouseResizableTileMirrored,+                                    MRTMessage (ShrinkSlave, ExpandSlave)+                                   ) where++import XMonad hiding (tile, splitVertically, splitHorizontallyBy)+import qualified XMonad.StackSet as W+import XMonad.Util.XUtils++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.MouseResizableTile+--+-- Then edit your @layoutHook@ by adding the MouseResizableTile layout.+-- Either in its normal form or the mirrored version. (The mirror layout modifier+-- will not work correctly here because of the use of the mouse.)+--+-- > myLayout = mouseResizableTile ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- or+--+-- > myLayout = mouseResizableTileMirrored ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+--+-- You may also want to add the following key bindings:+--+-- > , ((modm,               xK_u), sendMessage ShrinkSlave) -- %! Shrink a slave area+-- > , ((modm,               xK_i), sendMessage ExpandSlave) -- %! Expand a slave area+--+-- For detailed instruction on editing the key binding see:+--+-- "XMonad.Doc.Extending#Editing_key_bindings".++data MRTMessage = SetMasterFraction Rational+                    | SetLeftSlaveFraction Int Rational+                    | SetRightSlaveFraction Int Rational+                    | ShrinkSlave+                    | ExpandSlave+                    deriving Typeable+instance Message MRTMessage++data DraggerInfo = MasterDragger Position Rational+                    | LeftSlaveDragger Position Rational Int+                    | RightSlaveDragger Position Rational Int+                    deriving (Show, Read)+type DraggerWithRect = (Rectangle, Glyph, DraggerInfo)+type DraggerWithWin = (Window, DraggerInfo)++data MouseResizableTile a = MRT { nmaster :: Int,+                                    masterFrac :: Rational,+                                    leftFracs :: [Rational],+                                    rightFracs :: [Rational],+                                    draggers :: [DraggerWithWin],+                                    focusPos :: Int,+                                    numWindows :: Int,+                                    isMirrored :: Bool+                                } deriving (Show, Read)++mrtFraction :: Rational+mrtFraction = 0.5+mrtDelta :: Rational+mrtDelta = 0.03+mrtDraggerOffset :: Position+mrtDraggerOffset = 3+mrtDraggerSize :: Dimension+mrtDraggerSize = 6+mrtHDoubleArrow :: Glyph+mrtHDoubleArrow = 108+mrtVDoubleArrow :: Glyph+mrtVDoubleArrow = 116++mouseResizableTile :: MouseResizableTile a+mouseResizableTile = MRT 1 mrtFraction [] [] [] 0 0 False++mouseResizableTileMirrored :: MouseResizableTile a+mouseResizableTileMirrored= MRT 1 mrtFraction [] [] [] 0 0 True++instance LayoutClass MouseResizableTile a where+    doLayout state sr (W.Stack w l r) =+        let wins = reverse l ++ w : r+            num = length wins+            sr' = mirrorAdjust sr (mirrorRect sr)+            (rects, preparedDraggers) = tile (nmaster state) (masterFrac state)+                                            (leftFracs state ++ repeat mrtFraction)+                                            (rightFracs state ++ repeat mrtFraction) sr' num+            rects' = map (mirrorAdjust id mirrorRect . sanitizeRectangle sr') rects+        in do+            mapM_ deleteDragger $ draggers state+            newDraggers <- mapM (createDragger sr . adjustForMirror (isMirrored state)) preparedDraggers+            return (zip wins rects', Just $ state { draggers = newDraggers,+                                                    focusPos = length l,+                                                    numWindows = length wins })+        where+            mirrorAdjust a b = if (isMirrored state)+                                then b+                                else a++    handleMessage state m+        | Just (IncMasterN d) <- fromMessage m =+            return $ Just $ state { nmaster = max 0 (nmaster state + d) }+        | Just Shrink <- fromMessage m =+            return $ Just $ state { masterFrac = max 0 (masterFrac state - mrtDelta) }+        | Just Expand <- fromMessage m =+            return $ Just $ state { masterFrac = min 1 (masterFrac state + mrtDelta) }+        | Just ShrinkSlave <- fromMessage m =+            return $ Just $ modifySlave state (-mrtDelta)+        | Just ExpandSlave <- fromMessage m =+            return $ Just $ modifySlave state mrtDelta+        | Just (SetMasterFraction f) <- fromMessage m =+            return $ Just $ state { masterFrac = max 0 (min 1 f) }+        | Just (SetLeftSlaveFraction pos f) <- fromMessage m =+            return $ Just $ state { leftFracs = replaceAtPos (leftFracs state) pos (max 0 (min 1 f)) }+        | Just (SetRightSlaveFraction pos f) <- fromMessage m =+            return $ Just $ state { rightFracs = replaceAtPos (rightFracs state) pos (max 0 (min 1 f)) }++        | Just e <- fromMessage m :: Maybe Event = handleResize (draggers state) (isMirrored state) e >> return Nothing+        | Just Hide             <- fromMessage m = releaseResources >> return (Just $ state { draggers = [] })+        | Just ReleaseResources <- fromMessage m = releaseResources >> return (Just $ state { draggers = [] })+        where releaseResources = mapM_ deleteDragger $ draggers state+    handleMessage _ _ = return Nothing++    description _ = "MouseResizableTile"++adjustForMirror :: Bool -> DraggerWithRect -> DraggerWithRect+adjustForMirror False dragger = dragger+adjustForMirror True (draggerRect, draggerCursor, draggerInfo) =+        (mirrorRect draggerRect, draggerCursor', draggerInfo)+    where+        draggerCursor' = if (draggerCursor == mrtHDoubleArrow)+                            then mrtVDoubleArrow+                            else mrtHDoubleArrow++modifySlave :: MouseResizableTile a -> Rational-> MouseResizableTile a+modifySlave state delta =+    let pos = focusPos state+        num = numWindows state+        nmaster' = nmaster state+        leftFracs' = leftFracs state+        rightFracs' = rightFracs state+        draggersLeft = nmaster' - 1+        draggersRight = (num - nmaster') - 1+    in if pos < nmaster'+        then if draggersLeft > 0+                then let draggerPos = min (draggersLeft - 1) pos+                         oldFraction = (leftFracs' ++ repeat mrtFraction) !! draggerPos+                     in state { leftFracs = replaceAtPos leftFracs' draggerPos+                                            (max 0 (min 1 (oldFraction + delta))) }+                else state+        else if draggersRight > 0+                then let draggerPos = min (draggersRight - 1) (pos - nmaster')+                         oldFraction = (rightFracs' ++ repeat mrtFraction) !! draggerPos+                     in state { rightFracs = replaceAtPos rightFracs' draggerPos+                                            (max 0 (min 1 (oldFraction + delta))) }+                else state++replaceAtPos :: (Num t) => [Rational] -> t -> Rational -> [Rational]+replaceAtPos [] 0 x' = [x']+replaceAtPos [] pos x' = mrtFraction : replaceAtPos [] (pos - 1) x'+replaceAtPos (_:xs) 0 x' = x' : xs+replaceAtPos (x:xs) pos x' = x : replaceAtPos xs (pos -1 ) x'++sanitizeRectangle :: Rectangle -> Rectangle -> Rectangle+sanitizeRectangle (Rectangle sx sy swh sht) (Rectangle x y wh ht) =+    (Rectangle (within 0 (sx + fromIntegral swh) x) (within 0 (sy + fromIntegral sht) y)+                (within 1 swh wh) (within 1 sht ht))++within :: (Ord a) => a -> a -> a -> a+within low high a = max low $ min high a++tile :: Int -> Rational -> [Rational] -> [Rational] -> Rectangle -> Int -> ([Rectangle], [DraggerWithRect])+tile nmaster' masterFrac' leftFracs' rightFracs' sr num+    | num <= nmaster'       = splitVertically (take (num - 1) leftFracs') sr True 0+    | nmaster' == 0         = splitVertically (take (num - 1) rightFracs') sr False 0+    | otherwise             = (leftRects ++ rightRects, masterDragger : leftDraggers ++ rightDraggers)+    where ((sr1, sr2), masterDragger) = splitHorizontallyBy masterFrac' sr+          (leftRects, leftDraggers) = splitVertically (take (nmaster' - 1) leftFracs') sr1 True 0+          (rightRects, rightDraggers) = splitVertically (take (num - nmaster' - 1) rightFracs') sr2 False 0++splitVertically :: RealFrac r => [r] -> Rectangle -> Bool -> Int -> ([Rectangle], [DraggerWithRect])+splitVertically [] r _ _ = ([r], [])+splitVertically (f:fx) (Rectangle sx sy sw sh) isLeft num =+    let nextRect = Rectangle sx sy sw $ smallh - div mrtDraggerSize 2+        (otherRects, otherDragger) = splitVertically fx+                                        (Rectangle sx (sy + fromIntegral smallh + mrtDraggerOffset)+                                                    sw (sh - smallh - div mrtDraggerSize 2))+                                        isLeft (num + 1)+        draggerRect = Rectangle sx (sy + fromIntegral smallh - mrtDraggerOffset) sw mrtDraggerSize+        draggerInfo = if isLeft+                        then LeftSlaveDragger sy (fromIntegral sh) num+                        else RightSlaveDragger sy (fromIntegral sh) num+        nextDragger = (draggerRect, mrtVDoubleArrow, draggerInfo)+    in (nextRect : otherRects, nextDragger : otherDragger)+  where smallh = floor $ fromIntegral sh * f++splitHorizontallyBy :: RealFrac r => r -> Rectangle -> ((Rectangle, Rectangle), DraggerWithRect)+splitHorizontallyBy f (Rectangle sx sy sw sh) = ((leftHalf, rightHalf), (draggerRect, mrtHDoubleArrow, draggerInfo))+  where leftw = floor $ fromIntegral sw * f+        leftHalf = Rectangle sx sy (leftw - mrtDraggerSize `div` 2) sh+        rightHalf = Rectangle (sx + fromIntegral leftw + mrtDraggerOffset) sy+                                (sw - fromIntegral leftw - mrtDraggerSize `div` 2) sh+        draggerRect = Rectangle (sx + fromIntegral leftw - mrtDraggerOffset) sy mrtDraggerSize sh+        draggerInfo = MasterDragger sx (fromIntegral sw)++createDragger :: Rectangle -> DraggerWithRect -> X DraggerWithWin+createDragger sr (draggerRect, draggerCursor, draggerInfo) = do+        draggerWin <- createInputWindow draggerCursor $ sanitizeRectangle sr draggerRect+        return (draggerWin, draggerInfo)++deleteDragger :: DraggerWithWin -> X ()+deleteDragger (draggerWin, _) = deleteWindow draggerWin++handleResize :: [DraggerWithWin] -> Bool -> Event -> X ()+handleResize draggers' isM ButtonEvent { ev_window = ew, ev_event_type = et }+    | et == buttonPress, Just x <- lookup ew draggers' = case x of+        MasterDragger     lb r     -> mouseDrag' id   lb r  SetMasterFraction+        LeftSlaveDragger  lb r num -> mouseDrag' flip lb r (SetLeftSlaveFraction num)+        RightSlaveDragger lb r num -> mouseDrag' flip lb r (SetRightSlaveFraction num)+    where+        chooseAxis isM' axis1 axis2 = if isM' then axis2 else axis1+        mouseDrag' flp lowerBound range msg = flip mouseDrag (return ()) $ \x y -> do+                let axis = flp (chooseAxis isM) x y+                    fraction = fromIntegral (axis - lowerBound) / range+                sendMessage (msg fraction)++handleResize _ _ _ = return ()++createInputWindow :: Glyph -> Rectangle -> X Window+createInputWindow cursorGlyph r = withDisplay $ \d -> do+    win <- mkInputWindow d r+    io $ selectInput d win (exposureMask .|. buttonPressMask)+    cursor <- io $ createFontCursor d cursorGlyph+    io $ defineCursor d win cursor+    io $ freeCursor d cursor+    showWindow win+    return win++mkInputWindow :: Display -> Rectangle -> X Window+mkInputWindow d (Rectangle x y w h) = do+  rw <- asks theRoot+  let screen   = defaultScreenOfDisplay d+      visual   = defaultVisualOfScreen screen+      attrmask = cWOverrideRedirect+  io $ allocaSetWindowAttributes $+         \attributes -> do+           set_override_redirect attributes True+           createWindow d rw x y w h 0 0 inputOnly visual attrmask attributes
XMonad/Layout/MultiToggle.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE DeriveDataTypeable, ExistentialQuantification, Rank2Types, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -63,7 +63,7 @@ -- you can now dynamically apply the 'XMonad.Layout.Mirror' transformation: -- -- > ...--- >   , ((modMask,               xK_x     ), sendMessage $ Toggle MIRROR)+-- >   , ((modm,               xK_x     ), sendMessage $ Toggle MIRROR) -- > ... -- -- (That should be part of your key bindings.) When you press @mod-x@, the@@ -92,10 +92,7 @@ -- >     transform _ x k = k (Mirror x) -- -- Note, you need to put @{-\# LANGUAGE DeriveDataTypeable \#-}@ at the--- beginning of your file (ghc 6.8 only; with ghc 6.6 you can use--- @{-\# OPTIONS_GHC -fglasgow-exts \#-}@ instead) to be able to--- derive "Data.Typeable".---+-- beginning of your file.  -- | A class to identify custom transformers (and look up transforming -- functions by type).
XMonad/Layout/MultiToggle/Instances.hs view
@@ -1,6 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}--- above is for compatibility with GHC 6.6.-{- LANGUAGE TypeSynonymInstances, DeriveDataTypeable -}+{-# LANGUAGE TypeSynonymInstances, DeriveDataTypeable, MultiParamTypeClasses #-}  ----------------------------------------------------------------------------- -- |
XMonad/Layout/Named.hs view
@@ -17,9 +17,11 @@ module XMonad.Layout.Named     ( -- * Usage       -- $usage-      named+      named,+      nameTail     ) where +import XMonad import XMonad.Layout.LayoutModifier  -- $usage@@ -30,13 +32,14 @@ -- Then edit your @layoutHook@ by adding the Named layout modifier -- to some layout: ----- > myLayouts = named "real big" Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = named "real big" Full ||| (nameTail $ named "real big" $ Full) ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" +-- | Rename a layout. named :: String -> l a -> ModifiedLayout Named l a named s = ModifiedLayout (Named s) @@ -44,3 +47,13 @@  instance LayoutModifier Named a where     modifyDescription (Named n) _ = n+++-- | Remove the first word of the name.+nameTail :: l a -> ModifiedLayout NameTail l a+nameTail = ModifiedLayout NameTail++data NameTail a = NameTail deriving (Read,Show)++instance LayoutModifier NameTail a where+  modifyDescription NameTail i = dropWhile (==' ') $ dropWhile (/=' ') $ description i
XMonad/Layout/NoBorders.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}+{-# LANGUAGE PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -22,14 +23,20 @@                                 -- $usage                                 noBorders,                                 smartBorders,-                                withBorder+                                withBorder,+                                lessBorders,+                                SetsAmbiguous(..),+                                Ambiguity(..),+                                With(..)                                ) where  import XMonad import XMonad.Layout.LayoutModifier import qualified XMonad.StackSet as W-import Data.List ((\\))+import Control.Monad+import Data.List import qualified Data.Map as M+import Data.Function (on)  -- $usage -- You can use this module with the following in your ~\/.xmonad\/xmonad.hs file:@@ -70,32 +77,10 @@ setBorders :: [Window] -> Dimension -> X () setBorders ws bw = withDisplay $ \d -> mapM_ (\w -> io $ setWindowBorderWidth d w bw) ws -data SmartBorder a = SmartBorder [a] deriving (Read, Show)--instance LayoutModifier SmartBorder Window where-    unhook (SmartBorder s) = asks (borderWidth . config) >>= setBorders s+singleton :: [a] -> Bool+singleton = null . drop 1 -    redoLayout (SmartBorder s) _ st wrs = do-        wset <- gets windowset-        let managedwindows = W.integrate st-            screens = filter (nonzerorect . screenRect . W.screenDetail) . W.screens $ wset-            ws = tiled ++ floating-            tiled = case filter (`elem` managedwindows) $ map fst wrs of-                [w] | singleton screens -> [w]-                _ -> []-            floating =-                [ w |-                    (w, W.RationalRect px py wx wy) <- M.toList . W.floating $ wset,-                    px <= 0, py <= 0,-                    wx + px >= 1, wy + py >= 1-                ]-        asks (borderWidth . config) >>= setBorders (s \\ ws)-        setBorders ws 0-        return (wrs, Just $ SmartBorder ws)-     where-        singleton = null . drop 1-        nonzerorect (Rectangle _ _ 0 0) = False-        nonzerorect _ = True+type SmartBorder = ConfigurableBorder Ambiguity  -- | Removes the borders from a window under one of the following conditions: --@@ -105,4 +90,112 @@ --  * A floating window covers the entire screen (e.g. mplayer). -- smartBorders :: LayoutClass l a => l a -> ModifiedLayout SmartBorder l a-smartBorders = ModifiedLayout (SmartBorder [])+smartBorders = lessBorders Never++-- | Apply a datatype that has a SetsAmbiguous instance to provide a list of+-- windows that should not have borders.+--+-- This gives flexibility over when borders should be drawn, in particular with+-- xinerama setups: 'Ambiguity' has a number of useful 'SetsAmbiguous'+-- instances+lessBorders :: (SetsAmbiguous p, Read p, Show p, LayoutClass l a) =>+        p -> l a -> ModifiedLayout (ConfigurableBorder p) l a+lessBorders amb = ModifiedLayout (ConfigurableBorder amb [])++data ConfigurableBorder p w = ConfigurableBorder p [w] deriving (Read, Show)++instance (Read p, Show p, SetsAmbiguous p) => LayoutModifier (ConfigurableBorder p) Window where+    unhook (ConfigurableBorder _p s) = asks (borderWidth . config) >>= setBorders s++    redoLayout (ConfigurableBorder p s) _ mst wrs = do+        ws <- withWindowSet (\wset -> return (hiddens p wset mst wrs))+        asks (borderWidth . config) >>= setBorders (s \\ ws)+        setBorders ws 0+        return (wrs, Just $ ConfigurableBorder p ws)++-- | SetsAmbiguous allows custom actions to generate lists of windows that+-- should not have borders drawn through 'ConfigurableBorder'+--+-- To add your own (though perhaps those options would better belong as an+-- aditional constructor to 'Ambiguity'), you can add the function as such:+--+-- > data MyAmbiguity = MyAmbiguity deriving (Read, Show)+--+-- > instance SetsAmbiguous MyAmbiguity where+-- >  hiddens _ wset mst wrs = otherHiddens Screen \\ otherHiddens OnlyFloat+-- >     where otherHiddens p = hiddens p wset mst wrs+--+-- The above example is redundant, because you can have the same result with:+--+-- > layoutHook = lessBorders (Combine Difference Screen OnlyFloat) (Tall 1 0.5 0.03 ||| ... )+--+-- To get the same result as smartBorders:+--+-- > layoutHook = lessBorders (Combine Never) (Tall 1 0.5 0.03 ||| ...)+--+-- This indirect method is required to keep the Read and Show for+-- ConfigurableBorder so that xmonad can serialize state.+class SetsAmbiguous p where+    hiddens :: p -> WindowSet -> Maybe (W.Stack Window) -> [(Window, Rectangle)] -> [Window]++instance SetsAmbiguous Ambiguity where+    hiddens amb wset mst wrs+      | Combine Union a b <- amb = on union next a b+      | Combine Difference a b <- amb = on (\\) next a b+      | Combine Intersection a b <- amb = on intersect next a b+      | otherwise = tiled ms ++ floating+      where next p = hiddens p wset mst wrs+            nonzerorect (Rectangle _ _ 0 0) = False+            nonzerorect _ = True++            screens =+              [ scr | scr <- W.screens wset,+                      case amb of+                            Never -> True+                            _ -> not $ null $ integrate scr,+                      nonzerorect . screenRect $ W.screenDetail scr]+            floating = [ w |+                        (w, W.RationalRect px py wx wy) <- M.toList . W.floating $ wset,+                        px <= 0, py <= 0,+                        wx + px >= 1, wy + py >= 1]+            ms = filter (`elem` W.integrate' mst) $ map fst wrs+            tiled [w]+              | Screen <- amb = [w]+              | OnlyFloat <- amb = []+              | OtherIndicated <- amb+              , let nonF = map integrate $ W.current wset : W.visible wset+              , length (concat nonF) > length wrs+              , singleton $ filter (1==) $ map length nonF = [w]+              | singleton screens = [w]+            tiled _ = []+            integrate y = W.integrate' . W.stack $ W.workspace y++-- | In order of increasing ambiguity (less borders more frequently), where+-- subsequent constructors add additional cases where borders are not drawn+-- than their predecessors. These behaviors make most sense with with multiple+-- screens: for single screens, Never or 'smartBorders' makes more sense.+data Ambiguity = Combine With Ambiguity Ambiguity+                             -- ^ This constructor is used to combine the+                             -- borderless windows provided by the+                             -- SetsAmbiguous instances from two other+                             -- 'Ambiguity' data types.+               | OnlyFloat   -- ^ Only remove borders on floating windows that+                             -- cover the whole screen+               | Never       -- ^ Never remove borders when ambiguous:+                             -- this is the same as smartBorders+               | EmptyScreen -- ^ Focus in an empty screens does not count as+                             -- ambiguous.+               | OtherIndicated+                             -- ^ No borders on full when all other screens+                             -- have borders.+               | Screen      -- ^ Borders are never drawn on singleton screens.+                             -- With this one you really need another way such+                             -- as a statusbar to detect focus.+    deriving (Read, Show)++-- | Used to indicate to the 'SetsAmbiguous' instance for 'Ambiguity' how two+-- lists should be combined.+data With = Union        -- ^ Combine with Data.List.union+          | Difference   -- ^ Combine with Data.List.\\+          | Intersection -- ^ Combine with Data.List.intersect+        deriving (Read, Show)
+ XMonad/Layout/NoFrillsDecoration.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.NoFrillsDecoration+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de+-- Stability   :  unstable+-- Portability :  not portable+--+-- Most basic version of decoration for windows without any additional+-- modifications. In contrast to "XMonad.Layout.SimpleDecoration" this will+-- result in title bars that span the entire window instead of being only the+-- length of the window title.+--+-----------------------------------------------------------------------------++module XMonad.Layout.NoFrillsDecoration+    ( -- * Usage:+      -- $usage+      noFrillsDeco+    ) where++import XMonad.Layout.Decoration++-- $usage+-- You can use this module with the following in your+-- @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.NoFrillsDecoration+--+-- Then edit your @layoutHook@ by adding the NoFrillsDecoration to+-- your layout:+--+-- > myL = noFrillsDeco shrinkText defaultTheme (layoutHook defaultConfig)+-- > main = xmonad defaultConfig { layoutHook = myL }+--++-- | Add very simple decorations to windows of a layout.+noFrillsDeco :: (Eq a, Shrinker s) => s -> Theme+             -> l a -> ModifiedLayout (Decoration NoFrillsDecoration s) l a+noFrillsDeco s c = decoration s c $ NFD True++data NoFrillsDecoration a = NFD Bool deriving (Show, Read)++instance Eq a => DecorationStyle NoFrillsDecoration a where+    describeDeco _ = "NoFrillsDeco"
+ XMonad/Layout/OneBig.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.OneBig+-- Copyright   :  (c) 2009 Ilya Portnov+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Provides layout named OneBig. It places one (master) window at top left corner of screen, and other (slave) windows at top+--+-----------------------------------------------------------------------------++module XMonad.Layout.OneBig (+                             -- * Usage+                             -- $usage+                             OneBig (..)+                            ) where+import XMonad+import qualified XMonad.StackSet as W++-- $usage+-- This module defines layout named OneBig. It places one (master)+-- window at top left, and other (slave) windows at right and at+-- bottom of master. It tries to give equal space for each slave+-- window.+--+-- You can use this module by adding following in your @xmonad.hs@:+--+-- > import XMonad.Layout.OneBig+--+-- Then add layouts to your layoutHook:+--+-- > myLayoutHook = OneBig (3/4) (3/4) ||| ...+--+-- In this example, master window will occupy 3/4 of screen width and+-- 3/4 of screen height.++-- | Data type for layout+data OneBig a = OneBig Float Float deriving (Read,Show)++instance LayoutClass OneBig a where+  pureLayout = oneBigLayout+  pureMessage = oneBigMessage++-- | Processes Shrink/Expand messages+oneBigMessage :: OneBig a -> SomeMessage -> Maybe (OneBig a)+oneBigMessage (OneBig cx cy) m = fmap resize (fromMessage m)+    where resize Shrink = OneBig (cx-delta) (cy-delta)+          resize Expand = OneBig (cx+delta) (cy+delta)+          delta = 3/100++-- | Main layout function+oneBigLayout :: OneBig a -> Rectangle -> W.Stack a -> [(a, Rectangle)]+oneBigLayout (OneBig cx cy) rect stack = [(master,masterRect)]+                                      ++ (divideBottom bottomRect bottomWs)+                                      ++ (divideRight rightRect rightWs)+      where ws = W.integrate stack+            n = length ws+            ht (Rectangle _ _ _ hh) = hh+            wd (Rectangle _ _ ww _) = ww+            h' = round (fromIntegral (ht rect)*cy)+            w = wd rect+            m = calcBottomWs n w h'+            master = head ws+            other  = tail ws+            bottomWs = take m other+            rightWs = drop m other+            masterRect = cmaster n m cx cy rect+            bottomRect = cbottom cy rect+            rightRect  = cright cx cy rect++-- | Calculate how many windows must be placed at bottom+calcBottomWs :: Int -> Dimension -> Dimension -> Int+calcBottomWs n w h' = case n of+                        1 -> 0+                        2 -> 1+                        3 -> 2+                        4 -> 2+                        _ -> (fromIntegral w)*(n-1) `div` fromIntegral (h'+(fromIntegral w))++-- | Calculate rectangle for master window+cmaster:: Int -> Int -> Float -> Float -> Rectangle -> Rectangle+cmaster n m cx cy (Rectangle x y sw sh) = Rectangle x y w h+    where w = if (n > m+1) then+                round (fromIntegral sw*cx)+              else+                sw+          h = if (n > 1) then+                round (fromIntegral sh*cy)+              else+                sh++-- | Calculate rectangle for bottom windows+cbottom:: Float -> Rectangle -> Rectangle+cbottom cy (Rectangle sx sy sw sh) = Rectangle sx y sw h+    where h = round (fromIntegral sh*(1-cy))+          y = round (fromIntegral sh*cy+(fromIntegral sy))++-- | Calculate rectangle for right windows+cright:: Float -> Float -> Rectangle -> Rectangle+cright cx cy (Rectangle sx sy sw sh) = Rectangle x sy w h+    where w = round (fromIntegral sw*(1-cx))+          x = round (fromIntegral sw*cx+(fromIntegral sx))+          h = round (fromIntegral sh*cy)++-- | Divide bottom rectangle between windows+divideBottom :: Rectangle -> [a] -> [(a, Rectangle)]+divideBottom (Rectangle x y w h) ws = zip ws rects+    where n = length ws+          oneW = fromIntegral w `div` n+          oneRect = Rectangle x y (fromIntegral oneW) h+          rects = take n $ iterate (shiftR (fromIntegral oneW)) oneRect++-- | Divide right rectangle between windows+divideRight :: Rectangle -> [a] -> [(a, Rectangle)]+divideRight (Rectangle x y w h) ws = if (n==0) then [] else zip ws rects+    where n = length ws+          oneH = fromIntegral h `div` n+          oneRect = Rectangle x y w (fromIntegral oneH)+          rects = take n $ iterate (shiftB (fromIntegral oneH)) oneRect++-- | Shift rectangle right+shiftR :: Position -> Rectangle -> Rectangle+shiftR s (Rectangle x y w h) = Rectangle (x+s) y w h++-- | Shift rectangle bottom+shiftB :: Position -> Rectangle -> Rectangle+shiftB s (Rectangle x y w h) = Rectangle x (y+s) w h++
XMonad/Layout/Reflect.hs view
@@ -1,8 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}---- for now, use -fglasgow-exts for compatibility with ghc 6.6, which chokes--- on some of the LANGUAGE pragmas below-{- LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, TypeSynonymInstances -}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, TypeSynonymInstances #-}  ----------------------------------------------------------------------------- -- |@@ -62,8 +58,8 @@ -- -- Finally, add some keybindings to do the toggling, for example: ----- > , ((modMask x .|. controlMask, xK_x), sendMessage $ Toggle REFLECTX)--- > , ((modMask x .|. controlMask, xK_y), sendMessage $ Toggle REFLECTY)+-- > , ((modm .|. controlMask, xK_x), sendMessage $ Toggle REFLECTX)+-- > , ((modm .|. controlMask, xK_y), sendMessage $ Toggle REFLECTY) --  -- | Apply a horizontal reflection (left \<--\> right) to a
XMonad/Layout/ResizableTile.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}  ----------------------------------------------------------------------------- -- |@@ -34,8 +33,8 @@ -- -- Then edit your @layoutHook@ by adding the ResizableTile layout: ----- > myLayouts =  ResizableTall 1 (3/100) (1/2) [] ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout =  ResizableTall 1 (3/100) (1/2) [] ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -43,8 +42,8 @@ -- -- You may also want to add the following key bindings: ----- > , ((modMask x,               xK_a), sendMessage MirrorShrink)--- > , ((modMask x,               xK_z), sendMessage MirrorExpand)+-- > , ((modm,               xK_a), sendMessage MirrorShrink)+-- > , ((modm,               xK_z), sendMessage MirrorExpand) -- -- For detailed instruction on editing the key binding see: --@@ -53,7 +52,20 @@ data MirrorResize = MirrorShrink | MirrorExpand deriving Typeable instance Message MirrorResize -data ResizableTall a = ResizableTall Int Rational Rational [Rational] deriving (Show, Read)+data ResizableTall a = ResizableTall+    { _nmaster :: Int       -- ^ number of master windows+    , _delta  :: Rational   -- ^ change when resizing by 'Shrink', 'Expand',+                            -- 'MirrorShrink', 'MirrorExpand'+    , _frac   :: Rational   -- ^ width of master+    , _slaves :: [Rational] -- ^ fraction to multiply the window+                            -- height that would be given when divided equally.+                            --+                            -- slave windows are assigned their modified+                            -- heights in order, from top to bottom+                            --+                            -- unspecified values are replaced by 1+    } deriving (Show, Read)+ instance LayoutClass ResizableTall a where     doLayout (ResizableTall nmaster _ frac mfrac) r =         return . (\x->(x,Nothing)) .@@ -95,7 +107,7 @@ splitVertically _ n r | n < 2 = [r] splitVertically (f:fx) n (Rectangle sx sy sw sh) = Rectangle sx sy sw smallh :     splitVertically fx (n-1) (Rectangle sx (sy+fromIntegral smallh) sw (sh-smallh))-  where smallh = floor $ fromIntegral (sh `div` fromIntegral n) * f --hmm, this is a fold or map.+  where smallh = min sh (floor $ fromIntegral (sh `div` fromIntegral n) * f) --hmm, this is a fold or map.  splitHorizontallyBy :: RealFrac r => r -> Rectangle -> (Rectangle, Rectangle) splitHorizontallyBy f (Rectangle sx sy sw sh) =
XMonad/Layout/Roledex.hs view
@@ -10,14 +10,15 @@ -- Stability   :  unstable -- Portability :  unportable ----- Screenshot  :  <http://www.timthelion.com/rolodex.png>--- -- This is a completely pointless layout which acts like Microsoft's Flip 3D -----------------------------------------------------------------------------  module XMonad.Layout.Roledex (     -- * Usage     -- $usage++    -- * Screenshots+    -- $screenshot     Roledex(Roledex)) where  import XMonad@@ -27,17 +28,20 @@ -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: ----- > import XMonad.Layout.Roledex +-- > import XMonad.Layout.Roledex -- -- Then edit your @layoutHook@ by adding the Roledex layout: ----- > myLayouts =  Roledex ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout =  Roledex ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" +-- $screenshot+-- <<http://www.timthelion.com/rolodex.png>>+ data Roledex a = Roledex deriving ( Show, Read )  instance LayoutClass Roledex Window where@@ -51,8 +55,8 @@  where ups    = W.up ws        dns    = W.down ws        c = length ups + length dns-       rect = fst $ splitHorizontallyBy (2%3 :: Ratio Int) $ fst (splitVerticallyBy (2%3 :: Ratio Int) sc) -       gw = div' (w - rw) (fromIntegral c) +       rect = fst $ splitHorizontallyBy (2%3 :: Ratio Int) $ fst (splitVerticallyBy (2%3 :: Ratio Int) sc)+       gw = div' (w - rw) (fromIntegral c)             where             (Rectangle _ _ w _) = sc             (Rectangle _ _ rw _) = rect@@ -60,12 +64,12 @@             where             (Rectangle _ _ _ h) = sc             (Rectangle _ _ _ rh) = rect-       mainPane = mrect (gw * fromIntegral c) (gh * fromIntegral c) rect +       mainPane = mrect (gw * fromIntegral c) (gh * fromIntegral c) rect        mrect  mx my (Rectangle x y w h) = Rectangle (x + (fromIntegral mx)) (y + (fromIntegral my)) w h        tops    = map f $ cd c (length dns)        bottoms = map f $ [0..(length dns)]        f n = mrect (gw * (fromIntegral n)) (gh * (fromIntegral n)) rect-       cd n m = if n > m +       cd n m = if n > m                 then (n - 1) : (cd (n-1) m)                 else [] 
XMonad/Layout/ShowWName.hs view
@@ -45,7 +45,7 @@ showWName = ModifiedLayout (SWN True defaultSWNConfig Nothing)  -- | A layout modifier to show the workspace name when switching. It--- is possible to provide a costum configuration.+-- is possible to provide a custom configuration. showWName' :: SWNConfig -> l a -> ModifiedLayout ShowWName l a showWName' c = ModifiedLayout (SWN True c Nothing) @@ -70,8 +70,6 @@ instance LayoutModifier ShowWName a where     redoLayout      sn r _ wrs = doShow sn r wrs -    emptyLayoutMod  sn r   wrs = doShow sn r wrs-     handleMess (SWN _ c (Just (i,w))) m         | Just e    <- fromMessage m = handleTimer i e (deleteWindow w >> return Nothing)         | Just Hide <- fromMessage m = do deleteWindow w@@ -89,7 +87,7 @@ flashName :: SWNConfig -> Rectangle -> [(a, Rectangle)] -> X ([(a, Rectangle)], Maybe (ShowWName a)) flashName c (Rectangle _ _ wh ht) wrs = do   d <- asks display-  n <- withWindowSet (return . S.tag . S.workspace . S.current)+  n <- withWindowSet (return . S.currentTag)   f <- initXMF (swn_font c)   width   <- textWidthXMF d f n   (as,ds) <- textExtentsXMF f n
XMonad/Layout/SimpleFloat.hs view
@@ -38,8 +38,8 @@ -- -- Then edit your @layoutHook@ by adding the SimpleFloat layout: ----- > myLayouts = simpleFloat ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = simpleFloat ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
XMonad/Layout/Simplest.hs view
@@ -29,8 +29,8 @@ -- -- Then edit your @layoutHook@ by adding the Simplest layout: ----- > myLayouts = Simplest ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = Simplest ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
XMonad/Layout/SimplestFloat.hs view
@@ -23,6 +23,7 @@ import qualified XMonad.StackSet as S import XMonad.Layout.WindowArranger import XMonad.Layout.LayoutModifier+import XMonad.Util.XUtils (fi)  -- $usage -- You can use this module with the following in your@@ -32,8 +33,8 @@ -- -- Then edit your @layoutHook@ by adding the SimplestFloat layout: ----- > myLayouts = simplestFloat ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = simplestFloat ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -42,12 +43,12 @@ -- | A simple floating layout where every window is placed according -- to the window's initial attributes. simplestFloat :: Eq a => (ModifiedLayout WindowArranger SimplestFloat) a-simplestFloat = (windowArrangeAll $ SF)+simplestFloat = windowArrangeAll SF  data SimplestFloat a = SF deriving (Show, Read) instance LayoutClass SimplestFloat Window where-    doLayout SF sc (S.Stack w l r) = do wrs <- mapM (getSize sc) (w : reverse l ++ r)-                                        return (wrs, Nothing)+    doLayout SF sc (S.Stack w l r) = fmap (flip (,) Nothing)+                                   $ mapM (getSize sc) (w : reverse l ++ r)     description _ = "SimplestFloat"  getSize :: Rectangle -> Window -> X (Window,Rectangle)@@ -60,5 +61,3 @@       wh = (fi $ wa_width  wa) + (bw * 2)       ht = (fi $ wa_height wa) + (bw * 2)   return (w, Rectangle x y wh ht)-  where-    fi x = fromIntegral x
+ XMonad/Layout/Spacing.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.Spacing+-- Copyright   :  (c) Brent Yorgey+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  <byorgey@gmail.com>+-- Stability   :  unstable+-- Portability :  portable+--+-- Add a configurable amount of space around windows.+-----------------------------------------------------------------------------++module XMonad.Layout.Spacing (+                               -- * Usage+                               -- $usage++                               spacing++                             ) where++import Graphics.X11 (Rectangle(..))+import Control.Arrow (second)++import XMonad.Layout.LayoutModifier++-- $usage+-- You can use this module by importing it into your @~\/.xmonad\/xmonad.hs@ file:+--+-- > import XMonad.Layout.Spacing+--+-- and modifying your layoutHook as follows (for example):+--+-- > layoutHook = spacing 2 $ Tall 1 (3/100) (1/2)+-- >                      -- put a 2px space around every window+--++-- | Surround all windows by a certain number of pixels of blank space.+spacing :: Int -> l a -> ModifiedLayout Spacing l a+spacing p = ModifiedLayout (Spacing p)++data Spacing a = Spacing Int deriving (Show, Read)++instance LayoutModifier Spacing a where++    pureModifier (Spacing p) _ _ wrs = (map (second $ shrinkRect p) wrs, Nothing)++    modifierDescription (Spacing p) = "Spacing " ++ show p++shrinkRect :: Int -> Rectangle -> Rectangle+shrinkRect p (Rectangle x y w h) = Rectangle (x+fi p) (y+fi p) (w-2*fi p) (h-2*fi p)+  where fi n = fromIntegral n   -- avoid the DMR
XMonad/Layout/Spiral.hs view
@@ -34,8 +34,8 @@ -- -- Then edit your @layoutHook@ by adding the Spiral layout: ----- > myLayouts =  spiral (6/7) ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout =  spiral (6/7) ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
XMonad/Layout/StackTile.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}  ----------------------------------------------------------------------------- -- |@@ -12,7 +11,7 @@ -- Portability :  unportable -- -- A stacking layout, like dishes but with the ability to resize master pane.--- Moastly usefull on small screens.+-- Mostly useful on small screens. -- ----------------------------------------------------------------------------- @@ -33,8 +32,8 @@ -- -- Then edit your @layoutHook@ by adding the StackTile layout: ----- > myLayouts =  StackTile 1 (3/100) (1/2) ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout =  StackTile 1 (3/100) (1/2) ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --
+ XMonad/Layout/SubLayouts.hs view
@@ -0,0 +1,506 @@+{-# LANGUAGE PatternGuards, ParallelListComp, DeriveDataTypeable, FlexibleInstances, FlexibleContexts, MultiParamTypeClasses, TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.SubLayouts+-- Copyright   :  (c) 2009 Adam Vogt+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  vogt.adam@gmail.com+-- Stability   :  unstable+-- Portability :  unportable+--+-- A layout combinator that allows layouts to be nested.+--+-----------------------------------------------------------------------------++module XMonad.Layout.SubLayouts (+    -- * Usage+    -- $usage+    subLayout,+    subTabbed,++    pushGroup, pullGroup,+    pushWindow, pullWindow,+    onGroup, toSubl, mergeDir,++    GroupMsg(..),+    Broadcast(..),++    defaultSublMap,++    -- * Screenshots+    -- $screenshots++    -- * Todo+    -- $todo+    )+    where++import XMonad.Layout.Circle () -- so haddock can find the link++import XMonad.Layout.Decoration(Decoration, DefaultShrinker)+import XMonad.Layout.LayoutModifier(LayoutModifier(handleMess, modifyLayout,+                                    redoLayout),+                                    ModifiedLayout(..))+import XMonad.Layout.Simplest(Simplest(..))+import XMonad.Layout.Tabbed(defaultTheme, shrinkText,+                            TabbedDecoration, addTabs)+import XMonad.Layout.WindowNavigation(Navigate(Apply))+import XMonad.Util.Invisible(Invisible(..))+import XMonad.Util.Types(Direction2D(..))+import XMonad+import Control.Applicative((<$>),(<*))+import Control.Arrow(Arrow(second, (&&&)))+import Control.Monad(Monad(return), Functor(..),+                     MonadPlus(mplus), (=<<), sequence, foldM, guard, when, join)+import Data.Function((.), ($), flip, id, on)+import Data.List((++), foldr, filter, map, concatMap, elem,+                 notElem, null, nubBy, (\\), find)+import Data.Maybe(Maybe(..), isNothing, maybe, fromMaybe, listToMaybe,+                  mapMaybe)+import Data.Traversable(sequenceA)++import qualified XMonad.Layout.BoringWindows as B+import qualified XMonad.StackSet as W+import qualified Data.Map as M+import Data.Map(Map)++-- $screenshots+--+-- <<http://haskell.org/sitewiki/images/thumb/8/8b/Xmonad-SubLayouts-xinerama.png/480px-Xmonad-SubLayouts-xinerama.png>>+--+-- Larger version: <http://haskell.org/sitewiki/images/8/8b/Xmonad-SubLayouts-xinerama.png>++-- $todo+--  /Issue 288/+--+--  "XMonad.Layout.ResizableTile" assumes that its environment+--  contains only the windows it is running: sublayouts are currently run with+--  the stack containing only the windows passed to it in its environment, but+--  any changes that the layout makes are not merged back.+--+--  Should the behavior be made optional?+--+--  /Features/+--+--   * suggested managehooks for merging specific windows, or the apropriate+--     layout based hack to find out the number of groups currently showed, but+--     the size of current window groups is not available (outside of this+--     growing module)+--+--  /SimpleTabbed as a SubLayout/+--+--  'subTabbed' works well, but it would be more uniform to avoid the use of+--  addTabs, with the sublayout being Simplest (but+--  'XMonad.Layout.Tabbed.simpleTabbed' is this...).  The only thing to be+--  gained by fixing this issue is the ability to mix and match decoration+--  styles. Better compatibility with some other layouts of which I am not+--  aware could be another benefit.+--+--  'simpleTabbed' (and other decorated layouts) fail horribly when used as+--  subLayouts:+--+--    * decorations stick around: layout is run after being told to Hide+--+--    * mouse events do not change focus: the group-ungroup does not respect+--      the focus changes it wants?+--+--    * sending ReleaseResources before running it makes xmonad very slow, and+--      still leaves borders sticking around+--++-- $usage+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.SubLayouts+-- > import XMonad.Layout.WindowNavigation+--+-- Using "XMonad.Layout.BoringWindows" is optional and it allows you to add a+-- keybinding to skip over the non-visible windows.+--+-- > import XMonad.Layout.BoringWindows+--+-- Then edit your @layoutHook@ by adding the 'subTabbed' layout modifier:+--+-- > myLayout = windowNavigation $ subTabbed $ boringWindows $+-- >                        Tall 1 (3/100) (1/2) ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout }+--+-- "XMonad.Layout.WindowNavigation" is used to specify which windows to merge,+-- and it is not integrated into the modifier because it can be configured, and+-- works best as the outer modifier.+--+-- Then to your keybindings add:+--+--  > , ((modm .|. controlMask, xK_h), sendMessage $ pullGroup L)+--  > , ((modm .|. controlMask, xK_l), sendMessage $ pullGroup R)+--  > , ((modm .|. controlMask, xK_k), sendMessage $ pullGroup U)+--  > , ((modm .|. controlMask, xK_j), sendMessage $ pullGroup D)+--  >+--  > , ((modm .|. controlMask, xK_m), withFocused (sendMessage . MergeAll))+--  > , ((modm .|. controlMask, xK_u), withFocused (sendMessage . UnMerge))+--  >+--  > , ((modm .|. controlMask, xK_period), onGroup W.focusUp')+--  > , ((modm .|. controlMask, xK_comma), onGroup W.focusDown')+--+--  These additional keybindings require the optional+--  "XMonad.Layout.BoringWindows" layoutModifier. The focus will skip over the+--  windows that are not focused in each sublayout.+--+--  > , ((modm, xK_j), focusDown)+--  > , ((modm, xK_k), focusUp)+--+--  A 'submap' can be used to make modifying the sublayouts using 'onGroup' and+--  'toSubl' simpler:+--+--  > ,((modm, xK_s), submap $ defaultSublMap conf)+--+--  /NOTE:/ is there some reason that @asks config >>= submap . defaultSublMap@+--  could not be used in the keybinding instead? It avoids having to explicitly+--  pass the conf.+--+-- For more detailed instructions, see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+-- "XMonad.Doc.Extending#Adding_key_bindings"++-- | The main layout modifier arguments:+--+-- @subLayout advanceInnerLayouts innerLayout outerLayout@+--+--  [@advanceInnerLayouts@] When a new group at index @n@ in the outer layout+--  is created (even with one element), the @innerLayout@ is used as the+--  layout within that group after being advanced with @advanceInnerLayouts !!+--  n@ 'NextLayout' messages. If there is no corresponding element in the+--  @advanceInnerLayouts@ list, then @innerLayout@ is not given any 'NextLayout'+--  messages.+--+--  [@innerLayout@] The single layout given to be run as a sublayout.+--+--  [@outerLayout@] The layout that determines the rectangles given to each+--  group.+--+--  Ex. The second group is 'Tall', the third is 'Circle', all others are tabbed+--  with:+--+--  > myLayout = addTabs shrinkText defaultTheme+--  >          $ subLayout [0,1,2] (Simplest ||| Tall 1 0.2 0.5 ||| Circle)+--  >          $ Tall 1 0.2 0.5 ||| Full+subLayout :: [Int] -> subl a -> l a -> ModifiedLayout (Sublayout subl) l a+subLayout nextLayout sl x = ModifiedLayout (Sublayout (I []) (nextLayout,sl) []) x++-- | @subTabbed@ is a use of 'subLayout' with 'addTabs' to show decorations.+subTabbed :: (Eq a, LayoutModifier (Sublayout Simplest) a, LayoutClass l a) =>+    l a -> ModifiedLayout (Decoration TabbedDecoration DefaultShrinker)+                          (ModifiedLayout (Sublayout Simplest) l) a+subTabbed  x = addTabs shrinkText defaultTheme $ subLayout [] Simplest x++-- | @defaultSublMap@ is an attempt to create a set of keybindings like the+-- defaults ones but to be used as a 'submap' for sending messages to the+-- sublayout.+defaultSublMap :: XConfig l -> Map (KeyMask, KeySym) (X ())+defaultSublMap (XConfig { modMask = modm }) = M.fromList+         [((modm, xK_space), toSubl NextLayout),+          ((modm, xK_j), onGroup W.focusDown'),+          ((modm, xK_k), onGroup W.focusUp'),+          ((modm, xK_h), toSubl Shrink),+          ((modm, xK_l), toSubl Expand),+          ((modm, xK_Tab), onGroup W.focusDown'),+          ((modm .|. shiftMask, xK_Tab), onGroup W.focusUp'),+          ((modm, xK_m), onGroup focusMaster'),+          ((modm, xK_comma), toSubl $ IncMasterN 1),+          ((modm, xK_period), toSubl $ IncMasterN (-1)),+          ((modm, xK_Return), onGroup swapMaster')+         ]+        where+         -- should these go into XMonad.StackSet?+         focusMaster' st = let (f:fs) = W.integrate st+            in W.Stack f [] fs+         swapMaster' (W.Stack f u d) = W.Stack f [] $ reverse u ++ d++data Sublayout l a = Sublayout+    { delayMess :: Invisible [] (SomeMessage,a)+                          -- ^ messages are handled when running the layout,+                          -- not in the handleMessage, I'm not sure that this+                          -- is necessary+    , def :: ([Int], l a) -- ^ how many NextLayout messages to send to newly+                          -- populated layouts. If there is no corresponding+                          -- index, then don't send any.+    , subls :: [(l a,W.Stack a)]+                          -- ^ The sublayouts and the stacks they manage+    }+    deriving (Read,Show)++-- | Groups assumes this invariant:+--     M.keys gs == map W.focus (M.elems gs)  (ignoring order)+--     All windows in the workspace are in the Map+--+-- The keys are visible windows, the rest are hidden.+--+-- This representation probably simplifies the internals of the modifier.+type Groups a = Map a (W.Stack a)++-- | GroupMsg take window parameters to determine which group the action should+-- be applied to+data GroupMsg a+    = UnMerge a -- ^ free the focused window from its tab stack+    | UnMergeAll a+                -- ^ separate the focused group into singleton groups+    | Merge a a -- ^ merge the first group into the second group+    | MergeAll a+                -- ^ make one large group, keeping the parameter focused+    | Migrate a a+                -- ^ used to the window named in the first argument to the+                -- second argument's group, this may be replaced by a+                -- combination of 'UnMerge' and 'Merge'+    | WithGroup (W.Stack a -> X (W.Stack a)) a+    | SubMessage SomeMessage  a+                -- ^ the sublayout with the given window will get the message+    deriving (Typeable)++-- | merge the window that would be focused by the function when applied to the+-- W.Stack of all windows, with the current group removed. The given window+-- should be focused by a sublayout. Example usage: @withFocused (sendMessage .+-- mergeDir W.focusDown')@+mergeDir :: (W.Stack Window -> W.Stack Window) -> Window -> GroupMsg Window+mergeDir f w = WithGroup g w+ where g cs = do+        let onlyOthers = W.filter (`notElem` W.integrate cs)+        flip whenJust (sendMessage . Merge (W.focus cs) . W.focus . f)+            =<< fmap (onlyOthers =<<) currentStack+        return cs++data Broadcast = Broadcast SomeMessage -- ^ send a message to all sublayouts+    deriving (Typeable)++instance Message Broadcast+instance Typeable a => Message (GroupMsg a)++-- | @pullGroup@, @pushGroup@ allow you to merge windows or groups inheriting+-- the position of the current window (pull) or the other window (push).+--+-- @pushWindow@ and @pullWindow@ move individual windows between groups. They+-- are less effective at preserving window positions.+pullGroup,pushGroup,pullWindow,pushWindow :: Direction2D -> Navigate+pullGroup = mergeNav (\o c -> sendMessage $ Merge o c)+pushGroup = mergeNav (\o c -> sendMessage $ Merge c o)+pullWindow = mergeNav (\o c -> sendMessage $ Migrate o c)+pushWindow = mergeNav (\o c -> sendMessage $ Migrate c o)++mergeNav :: (Window -> Window -> X ()) -> Direction2D -> Navigate+mergeNav f = Apply (\o -> withFocused (f o))++-- | Apply a function on the stack belonging to the currently focused group. It+-- works for rearranging windows and for changing focus.+onGroup :: (W.Stack Window -> W.Stack Window) -> X ()+onGroup f = withFocused (sendMessage . WithGroup (return . f))++-- | Send a message to the currently focused sublayout.+toSubl :: (Message a) => a -> X ()+toSubl m = withFocused (sendMessage . SubMessage (SomeMessage m))++instance (Read (l Window), Show (l Window), LayoutClass l Window) => LayoutModifier (Sublayout l) Window where+    modifyLayout (Sublayout { subls = osls }) (W.Workspace i la st) r = do+            let gs' = updateGroup st $ toGroups osls+                st' = W.filter (`elem` M.keys gs') =<< st+            updateWs gs'+            oldStack <- gets $ W.stack . W.workspace . W.current . windowset+            setStack st'+            runLayout (W.Workspace i la st') r <* setStack oldStack+            -- FIXME: merge back reordering, deletions?++    redoLayout (Sublayout { delayMess = I ms, def = defl, subls = osls }) _r st arrs = do+        let gs' = updateGroup st $ toGroups osls+        sls <- fromGroups defl st gs' osls++        let newL :: LayoutClass l Window => Rectangle -> WorkspaceId -> (l Window) -> Bool+                    -> (Maybe (W.Stack Window)) -> X ([(Window, Rectangle)], l Window)+            newL rect n ol isNew sst = do+                orgStack <- currentStack+                let handle l (y,_)+                        | not isNew = fromMaybe l <$> handleMessage l y+                        | otherwise = return l+                    kms = filter ((`elem` M.keys gs') . snd) ms+                setStack sst+                nl <- foldM handle ol $ filter ((`elem` W.integrate' sst) . snd) kms+                result <- runLayout (W.Workspace n nl sst) rect+                setStack orgStack -- FIXME: merge back reordering, deletions?+                return $ fromMaybe nl `second` result++            (urls,ssts) = unzip [ (newL gr i l isNew sst, sst)+                    | (isNew,(l,_st)) <- sls+                    | i <- map show [ 0 :: Int .. ]+                    | (k,gr) <- arrs, let sst = M.lookup k gs' ]++        arrs' <- sequence urls+        sls' <- return . Sublayout (I []) defl . map snd <$> fromGroups defl st gs'+                        [ (l,s) | (_,l) <- arrs' | (Just s) <- ssts ]+        return (concatMap fst arrs', sls')++    handleMess (Sublayout (I ms) defl sls) m+        | Just (SubMessage sm w) <- fromMessage m =+            return $ Just $ Sublayout (I ((sm,w):ms)) defl sls++        | Just (Broadcast sm) <- fromMessage m = do+            ms' <- fmap (zip (repeat sm) . W.integrate') currentStack+            return $ if null ms' then Nothing+                else Just $ Sublayout (I $ ms' ++ ms) defl sls++        | Just B.UpdateBoring <- fromMessage m = do+            let bs = concatMap unfocused $ M.elems gs+            ws <- gets (W.workspace . W.current . windowset)+            flip sendMessageWithNoRefresh ws $ B.Replace "Sublayouts" bs+            return Nothing++        | Just (WithGroup f w) <- fromMessage m+        , Just g <- M.lookup w gs = do+            g' <- f g+            let gs' = M.insert (W.focus g') g' $ M.delete (W.focus g) gs+            when (gs' /= gs) $ updateWs gs'+            when (w /= W.focus g') $ windows (W.focusWindow $ W.focus g')+            return Nothing++        | Just (MergeAll w) <- fromMessage m =+            let gs' = fmap (M.singleton w)+                    $ (focusWindow' w =<<) $ W.differentiate+                    $ concatMap W.integrate $ M.elems gs+            in maybe (return Nothing) fgs gs'++        | Just (UnMergeAll w) <- fromMessage m =+            let ws = concatMap W.integrate $ M.elems gs+                _ = w :: Window+                mkSingleton f = M.singleton f (W.Stack f [] [])+            in fgs $ M.unions $ map mkSingleton ws++        | Just (Merge x y) <- fromMessage m+        , Just (W.Stack _ xb xn) <- findGroup x+        , Just yst <- findGroup y =+            let zs = W.Stack x xb (xn ++ W.integrate yst)+            in fgs $ M.insert x zs $ M.delete (W.focus yst) gs++        | Just (UnMerge x) <- fromMessage m =+            fgs . M.fromList . map (W.focus &&& id) . M.elems+                    $ M.mapMaybe (W.filter (x/=)) gs++        -- XXX sometimes this migrates an incorrect window, why?+        | Just (Migrate x y) <- fromMessage m+        , Just xst <- findGroup x+        , Just (W.Stack yf yu yd) <- findGroup y =+            let zs = W.Stack x (yf:yu) yd+                nxsAdd = maybe id (\e -> M.insert (W.focus e) e) $ W.filter (x/=) xst+            in fgs $ nxsAdd $ M.insert x zs $ M.delete yf gs+++        | otherwise = fmap join $ sequenceA $ catchLayoutMess <$> fromMessage m+     where gs = toGroups sls+           fgs gs' = do+                st <- currentStack+                Just . Sublayout (I ms) defl . map snd <$> fromGroups defl st gs' sls++           findGroup z = mplus (M.lookup z gs) $ listToMaybe+                    $ M.elems $ M.filter ((z `elem`) . W.integrate) gs+           -- catchLayoutMess :: LayoutMessages -> X (Maybe (Sublayout l Window))+           --  This l must be the same as from the instance head,+           --  -XScopedTypeVariables should bring it into scope, but we are+           --  trying to avoid warnings with ghc-6.8.2 and avoid CPP+           catchLayoutMess x = do+            let m' = x `asTypeOf` (undefined :: LayoutMessages)+            ms' <- zip (repeat $ SomeMessage m') . W.integrate'+                    <$> currentStack+            return $ do guard $ not $ null ms'+                        Just $ Sublayout (I $ ms' ++ ms) defl sls++currentStack :: X (Maybe (W.Stack Window))+currentStack = gets (W.stack . W.workspace . W.current . windowset)++-- | update Group to follow changes in the workspace+updateGroup :: Ord a => Maybe (W.Stack a) -> Groups a -> Groups a+updateGroup mst gs =+        let flatten = concatMap W.integrate . M.elems+            news = W.integrate' mst \\ flatten gs+            deads = flatten gs \\ W.integrate' mst++            uniNew = M.union (M.fromList $ map (\n -> (n,single n)) news)+            single x = W.Stack x [] []++            -- pass through a list to update/remove keys+            remDead = M.fromList . map (\w -> (W.focus w,w))+                        . mapMaybe (W.filter (`notElem` deads)) . M.elems++            -- update the current tab group's order and focus+            followFocus hs = fromMaybe hs $ do+                f' <- W.focus `fmap` mst+                xs <- find (elem f' . W.integrate) $ M.elems hs+                xs' <- W.filter (`elem` W.integrate xs) =<< mst+                return $ M.insert f' xs' $ M.delete (W.focus xs) hs++        in remDead $ uniNew $ followFocus gs++-- | rearrange the windowset to put the groups of tabs next to eachother, so+-- that the stack of tabs stays put.+updateWs :: Groups Window -> X ()+updateWs = windowsMaybe . updateWs'++updateWs' :: Groups Window -> WindowSet -> Maybe WindowSet+updateWs' gs ws = do+    f <- W.peek ws+    let w = W.index ws+        nes = concatMap W.integrate $ mapMaybe (flip M.lookup gs) w+        ws' = W.focusWindow f $ foldr W.insertUp (foldr W.delete' ws nes) nes+    guard $ W.index ws' /= W.index ws+    return ws'++-- | focusWindow'. focus an element of a stack, is Nothing if that element is+-- absent. See also 'W.focusWindow'+focusWindow' :: (Eq a) => a -> W.Stack a -> Maybe (W.Stack a)+focusWindow' w st = do+    guard $ not $ null $ filter (w==) $ W.integrate st+    if W.focus st == w then Just st+        else focusWindow' w $ W.focusDown' st++-- update only when Just+windowsMaybe :: (WindowSet -> Maybe WindowSet) -> X ()+windowsMaybe f = do+    xst <- get+    ws <- gets windowset+    let up fws = put xst { windowset = fws }+    maybe (return ()) up $ f ws++unfocused :: W.Stack a -> [a]+unfocused x = W.up x ++ W.down x++toGroups :: (Ord a) => [(a1, W.Stack a)] -> Map a (W.Stack a)+toGroups ws = M.fromList . map (W.focus &&& id) . nubBy (on (==) W.focus)+                    $ map snd ws++-- | restore the default layout for each group. It needs the X monad to switch+-- the default layout to a specific one (handleMessage NextLayout)+fromGroups :: (LayoutClass layout a, Ord k) =>+              ([Int], layout a)+              -> Maybe (W.Stack k)+              -> Groups k+              -> [(layout a, b)]+              -> X [(Bool,(layout a, W.Stack k))]+fromGroups (skips,defl) st gs sls = do+    defls <- mapM (iterateM nextL defl !!) skips+    return $ fromGroups' defl defls st gs (map fst sls)+        where nextL l = fromMaybe l <$> handleMessage l (SomeMessage NextLayout)+              iterateM f = iterate (>>= f) . return++fromGroups' :: (Ord k) => a -> [a] -> Maybe (W.Stack k) -> Groups k -> [a]+                    -> [(Bool,(a, W.Stack k))]+fromGroups' defl defls st gs sls =+    [ (isNew,fromMaybe2 (dl, single w) (l, M.lookup w gs))+        | l <- map Just sls ++ repeat Nothing, let isNew = isNothing l+        | dl <- defls ++ repeat defl+        | w <- W.integrate' $ W.filter (`notElem` unfocs) =<< st ]+    where unfocs = unfocused =<< M.elems gs+          single w = W.Stack w [] []+          fromMaybe2 (a,b) (x,y) = (fromMaybe a x, fromMaybe b y)+++-- this would be much cleaner with some kind of data-accessor+setStack :: Maybe (W.Stack Window) -> X ()+setStack x = modify (\s -> s { windowset = (windowset s)+                { W.current = (W.current $ windowset s)+                { W.workspace = (W.workspace $ W.current $ windowset s) { W.stack = x }}}})
XMonad/Layout/Tabbed.hs view
@@ -6,7 +6,7 @@ -- Copyright   :  (c) 2007 David Roundy, Andrea Rossato -- License     :  BSD-style (see xmonad/LICENSE) ----- Maintainer  :  droundy@darcs.net, andrea.rossato@unibz.it+-- Maintainer  :  andrea.rossato@unibz.it -- Stability   :  unstable -- Portability :  unportable --@@ -43,19 +43,23 @@ -- -- Then edit your @layoutHook@ by adding the Tabbed layout: ----- > myLayouts = simpleTabbed ||| Full ||| etc..+-- > myLayout = simpleTabbed ||| Full ||| etc.. -- -- or, if you want a specific theme for you tabbed layout: ----- > myLayouts = tabbed shrinkText defaultTheme ||| Full ||| etc..+-- > myLayout = tabbed shrinkText defaultTheme ||| Full ||| etc.. -- -- and then: ----- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > main = xmonad defaultConfig { layoutHook = myLayout } --+-- This layout has hardcoded behaviour for mouse clicks on tab decorations:+-- Left click on the tab switches focus to that window.+-- Middle click on the tab closes the window.+-- -- The default Tabbar behaviour is to hide it when only one window is open -- on the workspace.  To have it always shown, use one of the layouts or--- modifiers ending in "Always".+-- modifiers ending in @Always@. -- -- For more detailed instructions on editing the layoutHook see: --@@ -95,21 +99,21 @@  -- | A layout decorated with tabs and the possibility to set a custom -- shrinker and theme.-tabbed     :: (Eq a, Shrinker s) => s -> Theme +tabbed     :: (Eq a, Shrinker s) => s -> Theme            -> ModifiedLayout (Decoration TabbedDecoration s) Simplest a tabbed s c = addTabs s c Simplest -tabbedAlways     :: (Eq a, Shrinker s) => s -> Theme +tabbedAlways     :: (Eq a, Shrinker s) => s -> Theme                  -> ModifiedLayout (Decoration TabbedDecoration s) Simplest a tabbedAlways s c = addTabsAlways s c Simplest  -- | A layout decorated with tabs at the bottom and the possibility to set a custom -- shrinker and theme.-tabbedBottom     :: (Eq a, Shrinker s) => s -> Theme +tabbedBottom     :: (Eq a, Shrinker s) => s -> Theme                  -> ModifiedLayout (Decoration TabbedDecoration s) Simplest a tabbedBottom s c = addTabsBottom s c Simplest -tabbedBottomAlways     :: (Eq a, Shrinker s) => s -> Theme +tabbedBottomAlways     :: (Eq a, Shrinker s) => s -> Theme                        -> ModifiedLayout (Decoration TabbedDecoration s) Simplest a tabbedBottomAlways s c = addTabsBottomAlways s c Simplest @@ -151,8 +155,18 @@ instance Eq a => DecorationStyle TabbedDecoration a where     describeDeco (Tabbed Top _ ) = "Tabbed"     describeDeco (Tabbed Bottom _ ) = "Tabbed Bottom"+    decorationMouseFocusHook _ ds ButtonEvent { ev_window     = ew+                                             , ev_event_type = et+                                             , ev_button     = eb }+        | et == buttonPress+        , Just ((w,_),_) <-findWindowByDecoration ew ds =+           if eb == button2+               then killWindow w+               else focus w+    decorationMouseFocusHook _ _ _ = return ()+     decorationMouseDragHook _ _ _ = return ()-    pureDecoration (Tabbed lc sh) _ ht _ s wrs (w,r@(Rectangle x y wh hh)) +    pureDecoration (Tabbed lc sh) _ ht _ s wrs (w,r@(Rectangle x y wh hh))         = if ((sh == Always && numWindows > 0) || numWindows > 1)           then Just $ case lc of                         Top -> upperTab@@ -165,7 +179,7 @@               upperTab = Rectangle nx y wid (fi ht)               lowerTab = Rectangle nx (y+fi(hh-ht)) wid (fi ht)               numWindows = length ws-    shrink (Tabbed loc _ ) (Rectangle _ _ _ dh) (Rectangle x y w h) +    shrink (Tabbed loc _ ) (Rectangle _ _ _ dh) (Rectangle x y w h)         = case loc of             Top -> Rectangle x (y + fi dh) w (h - dh)             Bottom -> Rectangle x y w (h - dh)
XMonad/Layout/ThreeColumns.hs view
@@ -5,18 +5,22 @@ -- Module      :  XMonad.Layout.ThreeColumns -- Copyright   :  (c) Kai Grossjohann <kai@emptydomain.de> -- License     :  BSD3-style (see LICENSE)--- +-- -- Maintainer  :  ? -- Stability   :  unstable -- Portability :  unportable ----- A layout similar to tall but with three columns.---+-- A layout similar to tall but with three columns. With 2560x1600 pixels this+-- layout can be used for a huge main window and up to six reasonable sized+-- slave windows. -----------------------------------------------------------------------------  module XMonad.Layout.ThreeColumns (                               -- * Usage                               -- $usage++                              -- * Screenshots+                              -- $screenshot                               ThreeCol(..)                              ) where @@ -34,44 +38,70 @@ -- -- Then edit your @layoutHook@ by adding the ThreeCol layout: ----- > myLayouts = ThreeCol 1 (3/100) (1/2) ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = ThreeCol 1 (3/100) (1/2) ||| ThreeColMid 1 (3/100) (1/2) ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } --+-- The first argument specifies how many windows initially appear in the main+-- window. The second argument argument specifies the amount to resize while+-- resizing and the third argument specifies the initial size of the columns.+-- A positive size designates the fraction of the screen that the main window+-- should occupy, but if the size is negative the absolute value designates the+-- fraction a slave column should occupy. If both slave columns are visible,+-- they always occupy the same amount of space.+--+-- The ThreeColMid variant places the main window between the slave columns.+-- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" -data ThreeCol a = ThreeCol !Int !Rational !Rational deriving (Show,Read) +-- $screenshot+-- <<http://server.c-otto.de/xmonad/ThreeColumnsMiddle.png>>++-- | Arguments are nmaster, delta, fraction+data ThreeCol a = ThreeColMid { threeColNMaster :: !Int, threeColDelta :: !Rational, threeColFrac :: !Rational}+                | ThreeCol    { threeColNMaster :: !Int, threeColDelta :: !Rational, threeColFrac :: !Rational}+    deriving (Show,Read)+ instance LayoutClass ThreeCol a where-    doLayout (ThreeCol nmaster _ frac) r =-        return . (\x->(x,Nothing)) .-        ap zip (tile3 frac r nmaster . length) . W.integrate-    handleMessage (ThreeCol nmaster delta frac) m =+    pureLayout (ThreeCol n _ f) r    = doL False n f r+    pureLayout (ThreeColMid n _ f) r = doL True n f r+    handleMessage l m =         return $ msum [fmap resize     (fromMessage m)                       ,fmap incmastern (fromMessage m)]-            where resize Shrink = ThreeCol nmaster delta (max 0 $ frac-delta)-                  resize Expand = ThreeCol nmaster delta (min 1 $ frac+delta)-                  incmastern (IncMasterN d) = ThreeCol (max 0 (nmaster+d)) delta frac+            where resize Shrink = l { threeColFrac = max (-0.5) $ f-d }+                  resize Expand = l { threeColFrac = min 1 $ f+d }+                  incmastern (IncMasterN x) = l { threeColNMaster = max 0 (n+x) }+                  n = threeColNMaster l+                  d = threeColDelta l+                  f = threeColFrac l     description _ = "ThreeCol" +doL :: Bool-> Int-> Rational-> Rectangle-> W.Stack a-> [(a, Rectangle)]+doL m n f r = ap zip (tile3 m f r n . length) . W.integrate+ -- | tile3.  Compute window positions using 3 panes-tile3 :: Rational -> Rectangle -> Int -> Int -> [Rectangle]-tile3 f r nmaster n +tile3 :: Bool -> Rational -> Rectangle -> Int -> Int -> [Rectangle]+tile3 middle f r nmaster n     | n <= nmaster || nmaster == 0 = splitVertically n r     | n <= nmaster+1 = splitVertically nmaster s1 ++ splitVertically (n-nmaster) s2-    | otherwise = splitVertically nmaster r1 ++ splitVertically nmid r2 ++ splitVertically nright r3-  where (r1, r2, r3) = split3HorizontallyBy f r-        (s1, s2) = splitHorizontallyBy f r-        nslave = (n - nmaster)-        nmid = ceiling (nslave % 2)-        nright = (n - nmaster - nmid)+    | otherwise = splitVertically nmaster r1 ++ splitVertically nslave1 r2 ++ splitVertically nslave2 r3+        where (r1, r2, r3) = split3HorizontallyBy middle (if f<0 then 1+2*f else f) r+              (s1, s2) = splitHorizontallyBy (if f<0 then 1+f else f) r+              nslave = (n - nmaster)+              nslave1 = ceiling (nslave % 2)+              nslave2 = (n - nmaster - nslave1) -split3HorizontallyBy :: Rational -> Rectangle -> (Rectangle, Rectangle, Rectangle)-split3HorizontallyBy f (Rectangle sx sy sw sh) =-    ( Rectangle sx sy leftw sh-    , Rectangle (sx + fromIntegral leftw) sy midw sh-    , Rectangle (sx + fromIntegral leftw + fromIntegral midw) sy rightw sh )-  where leftw = ceiling $ fromIntegral sw * (2/3) * f-        midw = ceiling ( (sw - leftw) % 2 )-        rightw = sw - leftw - midw+split3HorizontallyBy :: Bool -> Rational -> Rectangle -> (Rectangle, Rectangle, Rectangle)+split3HorizontallyBy middle f (Rectangle sx sy sw sh) =+    if middle+    then ( Rectangle (sx + fromIntegral r3w) sy r1w sh+         , Rectangle (sx + fromIntegral r3w + fromIntegral r1w) sy r2w sh+         , Rectangle sx sy r3w sh )+    else ( Rectangle sx sy r1w sh+         , Rectangle (sx + fromIntegral r1w) sy r2w sh+         , Rectangle (sx + fromIntegral r1w + fromIntegral r2w) sy r3w sh )+        where r1w = ceiling $ fromIntegral sw * f+              r2w = ceiling ( (sw - r1w) % 2 )+              r3w = sw - r1w - r2w
XMonad/Layout/ToggleLayouts.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -30,8 +29,8 @@ -- -- Then edit your @layoutHook@ by adding the ToggleLayouts layout: ----- > myLayouts = toggleLayouts Full (Tall 1 (3/100) (1/2)) ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = toggleLayouts Full (Tall 1 (3/100) (1/2)) ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -39,11 +38,11 @@ -- -- To toggle between layouts add a key binding like ----- >    , ((modMask x .|. controlMask, xK_space), sendMessage ToggleLayout)+-- >    , ((modm .|. controlMask, xK_space), sendMessage ToggleLayout) -- -- or a key binding like ----- >    , ((modMask x .|. controlMask, xK_space), sendMessage (Toggle "Full"))+-- >    , ((modm .|. controlMask, xK_space), sendMessage (Toggle "Full")) -- -- For detailed instruction on editing the key binding see: --
XMonad/Layout/TwoPane.hs view
@@ -5,7 +5,7 @@ -- Module      :  XMonad.Layout.TwoPane -- Copyright   :  (c) Spencer Janssen <spencerjanssen@gmail.com> -- License     :  BSD3-style (see LICENSE)--- +-- -- Maintainer  :  Spencer Janssen <spencerjanssen@gmail.com> -- Stability   :  unstable -- Portability :  unportable@@ -32,15 +32,15 @@ -- -- Then edit your @layoutHook@ by adding the TwoPane layout: ----- > myLayouts = TwoPane (3/100) (1/2)  ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = TwoPane (3/100) (1/2)  ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" -data TwoPane a = -    TwoPane Rational Rational +data TwoPane a =+    TwoPane Rational Rational     deriving ( Show, Read )  instance LayoutClass TwoPane a where@@ -53,7 +53,7 @@                                       [] -> [(focus st, rect)]               where (left, right) = splitHorizontallyBy split rect -    handleMessage (TwoPane delta split) x = +    handleMessage (TwoPane delta split) x =         return $ case fromMessage x of                    Just Shrink -> Just (TwoPane delta (split - delta))                    Just Expand -> Just (TwoPane delta (split + delta))
XMonad/Layout/WindowArranger.hs view
@@ -1,8 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- for deriving Typeable-{-# LANGUAGE PatternGuards           #-}-{-# LANGUAGE FlexibleInstances       #-}-{-# LANGUAGE MultiParamTypeClasses   #-}-{-# LANGUAGE TypeSynonymInstances    #-}+{-# LANGUAGE DeriveDataTypeable, PatternGuards, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances    #-} ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.WindowArranger@@ -57,20 +53,20 @@ -- You may also want to define some key binding to move or resize -- windows. These are good defaults: ----- >        , ((modMask x .|. controlMask              , xK_s    ), sendMessage  Arrange         )--- >        , ((modMask x .|. controlMask .|. shiftMask, xK_s    ), sendMessage  DeArrange       )--- >        , ((modMask x .|. controlMask              , xK_Left ), sendMessage (MoveLeft      1))--- >        , ((modMask x .|. controlMask              , xK_Right), sendMessage (MoveRight     1))--- >        , ((modMask x .|. controlMask              , xK_Down ), sendMessage (MoveDown      1))--- >        , ((modMask x .|. controlMask              , xK_Up   ), sendMessage (MoveUp        1))--- >        , ((modMask x                 .|. shiftMask, xK_Left ), sendMessage (IncreaseLeft  1))--- >        , ((modMask x                 .|. shiftMask, xK_Right), sendMessage (IncreaseRight 1))--- >        , ((modMask x                 .|. shiftMask, xK_Down ), sendMessage (IncreaseDown  1))--- >        , ((modMask x                 .|. shiftMask, xK_Up   ), sendMessage (IncreaseUp    1))--- >        , ((modMask x .|. controlMask .|. shiftMask, xK_Left ), sendMessage (DecreaseLeft  1))--- >        , ((modMask x .|. controlMask .|. shiftMask, xK_Right), sendMessage (DecreaseRight 1))--- >        , ((modMask x .|. controlMask .|. shiftMask, xK_Down ), sendMessage (DecreaseDown  1))--- >        , ((modMask x .|. controlMask .|. shiftMask, xK_Up   ), sendMessage (DecreaseUp    1))+-- >        , ((modm .|. controlMask              , xK_s    ), sendMessage  Arrange         )+-- >        , ((modm .|. controlMask .|. shiftMask, xK_s    ), sendMessage  DeArrange       )+-- >        , ((modm .|. controlMask              , xK_Left ), sendMessage (MoveLeft      1))+-- >        , ((modm .|. controlMask              , xK_Right), sendMessage (MoveRight     1))+-- >        , ((modm .|. controlMask              , xK_Down ), sendMessage (MoveDown      1))+-- >        , ((modm .|. controlMask              , xK_Up   ), sendMessage (MoveUp        1))+-- >        , ((modm                 .|. shiftMask, xK_Left ), sendMessage (IncreaseLeft  1))+-- >        , ((modm                 .|. shiftMask, xK_Right), sendMessage (IncreaseRight 1))+-- >        , ((modm                 .|. shiftMask, xK_Down ), sendMessage (IncreaseDown  1))+-- >        , ((modm                 .|. shiftMask, xK_Up   ), sendMessage (IncreaseUp    1))+-- >        , ((modm .|. controlMask .|. shiftMask, xK_Left ), sendMessage (DecreaseLeft  1))+-- >        , ((modm .|. controlMask .|. shiftMask, xK_Right), sendMessage (DecreaseRight 1))+-- >        , ((modm .|. controlMask .|. shiftMask, xK_Down ), sendMessage (DecreaseDown  1))+-- >        , ((modm .|. controlMask .|. shiftMask, xK_Up   ), sendMessage (DecreaseUp    1)) -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -109,9 +105,9 @@ data WindowArranger a = WA Bool ArrangeAll [ArrangedWindow a] deriving (Read, Show)  instance (Show a, Read a, Eq a) => LayoutModifier WindowArranger a where-    pureModifier (WA True b   []) _  _              wrs = arrangeWindows b wrs+    pureModifier (WA True b   []) _ (Just _)               wrs = arrangeWindows b wrs -    pureModifier (WA True b awrs) _ (S.Stack w _ _) wrs = curry process wrs awrs+    pureModifier (WA True b awrs) _ (Just (S.Stack w _ _)) wrs = curry process wrs awrs         where           wins         = map fst       *** map awrWin           update (a,r) = mkNewAWRs b a *** removeAWRs r >>> uncurry (++)@@ -203,7 +199,7 @@ memberFromList f g l = foldr (h l) []     where h x y ys = if g (f y) x then [y] else ys --- | Get the list of elements to be deleted and the list ef elements to+-- | Get the list of elements to be deleted and the list of elements to -- be added to the first list in order to get the second list. diff :: Eq a => ([a],[a]) -> ([a],[a]) diff (x,y) = (x \\ y, y \\ x)
XMonad/Layout/WindowNavigation.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances, PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -19,7 +18,7 @@                                    -- * Usage                                    -- $usage                                    windowNavigation, configurableNavigation,-                                   Navigate(..), Direction(..),+                                   Navigate(..), Direction2D(..),                                    MoveWindowToWindow(..),                                    navigateColor, navigateBrightness,                                    noNavigateBorders, defaultWNConfig@@ -30,10 +29,9 @@ import qualified XMonad.StackSet as W import XMonad.Layout.LayoutModifier import XMonad.Util.Invisible+import XMonad.Util.Types (Direction2D(..)) import XMonad.Util.XUtils -import XMonad.Hooks.ManageDocks (Direction(..))- -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: --@@ -42,8 +40,8 @@ -- Then edit your @layoutHook@ by adding the WindowNavigation layout modifier -- to some layout: ----- > myLayouts = windowNavigation (Tall 1 (3/100) (1/2))  ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = windowNavigation (Tall 1 (3/100) (1/2))  ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -51,14 +49,14 @@ -- -- In keybindings: ----- >    , ((modMask x,                 xK_Right), sendMessage $ Go R)--- >    , ((modMask x,                 xK_Left ), sendMessage $ Go L)--- >    , ((modMask x,                 xK_Up   ), sendMessage $ Go U)--- >    , ((modMask x,                 xK_Down ), sendMessage $ Go D)--- >    , ((modMask x .|. controlMask, xK_Right), sendMessage $ Swap R)--- >    , ((modMask x .|. controlMask, xK_Left ), sendMessage $ Swap L)--- >    , ((modMask x .|. controlMask, xK_Up   ), sendMessage $ Swap U)--- >    , ((modMask x .|. controlMask, xK_Down ), sendMessage $ Swap D)+-- >    , ((modm,                 xK_Right), sendMessage $ Go R)+-- >    , ((modm,                 xK_Left ), sendMessage $ Go L)+-- >    , ((modm,                 xK_Up   ), sendMessage $ Go U)+-- >    , ((modm,                 xK_Down ), sendMessage $ Go D)+-- >    , ((modm .|. controlMask, xK_Right), sendMessage $ Swap R)+-- >    , ((modm .|. controlMask, xK_Left ), sendMessage $ Swap L)+-- >    , ((modm .|. controlMask, xK_Up   ), sendMessage $ Swap U)+-- >    , ((modm .|. controlMask, xK_Down ), sendMessage $ Swap D) -- -- For detailed instruction on editing the key binding see: --@@ -68,7 +66,9 @@ data MoveWindowToWindow a = MoveWindowToWindow a a deriving ( Read, Show, Typeable ) instance Typeable a => Message (MoveWindowToWindow a) -data Navigate = Go Direction | Swap Direction | Move Direction deriving ( Read, Show, Typeable )+data Navigate = Go Direction2D | Swap Direction2D | Move Direction2D+              | Apply (Window -> X()) Direction2D -- ^ Apply action with destination window+        deriving ( Typeable ) instance Message Navigate  data WNConfig =@@ -88,9 +88,7 @@     WNC Nothing c c c c  navigateBrightness :: Double -> WNConfig-navigateBrightness f | f > 1 = navigateBrightness 1-                     | f < 0 = navigateBrightness 0-navigateBrightness f = defaultWNConfig { brightness = Just f }+navigateBrightness f = defaultWNConfig { brightness = Just $ max 0 $ min 1 f }  defaultWNConfig :: WNConfig defaultWNConfig = WNC (Just 0.4) "#0000FF" "#00FFFF" "#FF0000" "#FF00FF"@@ -106,7 +104,7 @@ configurableNavigation conf = ModifiedLayout (WindowNavigation conf (I Nothing))  instance LayoutModifier WindowNavigation Window where-    redoLayout (WindowNavigation conf (I state)) rscr s origwrs =+    redoLayout (WindowNavigation conf (I state)) rscr (Just s) origwrs =         do XConf { normalBorder = nbc, focusedBorder = fbc, display = dpy } <- ask            [uc,dc,lc,rc] <-                case brightness conf of@@ -127,15 +125,16 @@                wrs = filter ((`elem` existing_wins) . fst) $ filter ((/=r) . snd) $                      filter ((/=w) . fst) origwrs                wnavigable = nub $ concatMap-                            (\d -> truncHead $ navigable d pt wrs) [U,D,R,L]+                            (\d -> take 1 $ navigable d pt wrs) [U,D,R,L]                wnavigablec = nub $ concatMap                             (\d -> map (\(win,_) -> (win,dirc d)) $-                                   truncHead $ navigable d pt wrs) [U,D,R,L]+                                   take 1 $ navigable d pt wrs) [U,D,R,L]                wothers = case state of Just (NS _ wo) -> map fst wo                                        _              -> []            mapM_ (sc nbc) (wothers \\ map fst wnavigable)            mapM_ (\(win,c) -> sc c win) wnavigablec            return (origwrs, Just $ WindowNavigation conf $ I $ Just $ NS pt wnavigable)+    redoLayout _ _ _ origwrs = return (origwrs, Nothing)      handleMessOrMaybeModifyIt (WindowNavigation conf (I (Just (NS pt wrs)))) m         | Just (Go d) <- fromMessage m =@@ -176,6 +175,10 @@              ((w,_):_) -> do mst <- gets (W.stack . W.workspace . W.current . windowset)                              return $ do st <- mst                                          Just $ Right $ SomeMessage $ MoveWindowToWindow (W.focus st) w+        | Just (Apply f d) <- fromMessage m =+             case navigable d pt wrs of+             []         -> return Nothing+             ((w,_):_)  -> f w >> return Nothing         | Just Hide <- fromMessage m =                        do XConf { normalBorder = nbc } <- ask                           mapM_ (sc nbc . fst) wrs@@ -184,24 +187,20 @@                handleMessOrMaybeModifyIt (WindowNavigation conf (I $ Just (NS pt wrs))) (SomeMessage Hide)     handleMessOrMaybeModifyIt _ _ = return Nothing -navigable :: Direction -> Point -> [(Window, Rectangle)] -> [(Window, Rectangle)]+navigable :: Direction2D -> Point -> [(Window, Rectangle)] -> [(Window, Rectangle)] navigable d pt = sortby d . filter (inr d pt . snd) -truncHead :: [a] -> [a]-truncHead (x:_) = [x]-truncHead [] = []- sc :: Pixel -> Window -> X () sc c win = withDisplay $ \dpy -> io $ setWindowBorder dpy win c  center :: Rectangle -> Point center (Rectangle x y w h) = P (fromIntegral x + fromIntegral w/2)  (fromIntegral y + fromIntegral h/2) -centerd :: Direction -> Point -> Rectangle -> Point+centerd :: Direction2D -> Point -> Rectangle -> Point centerd d (P xx yy) (Rectangle x y w h) | d == U || d == D = P xx (fromIntegral y + fromIntegral h/2)                                         | otherwise = P (fromIntegral x + fromIntegral w/2) yy -inr :: Direction -> Point -> Rectangle -> Bool+inr :: Direction2D -> Point -> Rectangle -> Bool inr D (P x y) (Rectangle l yr w h) = x >= fromIntegral l && x < fromIntegral l + fromIntegral w &&                                      y <  fromIntegral yr + fromIntegral h inr U (P x y) (Rectangle l yr w _) = x >= fromIntegral l && x < fromIntegral l + fromIntegral w &&@@ -215,7 +214,7 @@ inrect (P x y) (Rectangle a b w h) = x >  fromIntegral a && x < fromIntegral a + fromIntegral w &&                                      y >  fromIntegral b && y < fromIntegral b + fromIntegral h -sortby :: Direction -> [(a,Rectangle)] -> [(a,Rectangle)]+sortby :: Direction2D -> [(a,Rectangle)] -> [(a,Rectangle)] sortby U = sortBy (\(_,Rectangle _ y _ _) (_,Rectangle _ y' _ _) -> compare y' y) sortby D = sortBy (\(_,Rectangle _ y _ _) (_,Rectangle _ y' _ _) -> compare y y') sortby R = sortBy (\(_,Rectangle x _ _ _) (_,Rectangle x' _ _ _) -> compare x x')
XMonad/Layout/WorkspaceDir.hs view
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-} -- For deriving Data/Typeable-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances, PatternGuards #-}  ----------------------------------------------------------------------------- -- |@@ -37,7 +36,7 @@ import XMonad.Prompt ( XPConfig ) import XMonad.Prompt.Directory ( directoryPrompt ) import XMonad.Layout.LayoutModifier-import XMonad.StackSet ( tag, current, workspace )+import XMonad.StackSet ( tag, currentTag )  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:@@ -47,8 +46,8 @@ -- Then edit your @layoutHook@ by adding the Workspace layout modifier -- to some layout: ----- > myLayouts = workspaceDir "~" (Tall 1 (3/100) (1/2))  ||| Full ||| etc..--- > main = xmonad defaultConfig { layoutHook = myLayouts }+-- > myLayout = workspaceDir "~" (Tall 1 (3/100) (1/2))  ||| Full ||| etc..+-- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: --@@ -57,7 +56,7 @@ -- WorkspaceDir provides also a prompt. To use it you need to import -- "XMonad.Prompt" and add something like this to your key bindings: ----- >  , ((modMask x .|. shiftMask, xK_x     ), changeDir defaultXPConfig)+-- >  , ((modm .|. shiftMask, xK_x     ), changeDir defaultXPConfig) -- -- For detailed instruction on editing the key binding see: --@@ -69,7 +68,7 @@ data WorkspaceDir a = WorkspaceDir String deriving ( Read, Show )  instance LayoutModifier WorkspaceDir Window where-    modifyLayout (WorkspaceDir d) w r = do tc <- gets (tag.workspace.current.windowset)+    modifyLayout (WorkspaceDir d) w r = do tc <- gets (currentTag.windowset)                                            when (tc == tag w) $ scd d                                            runLayout w r     handleMess (WorkspaceDir _) m
XMonad/Prompt.hs view
@@ -5,7 +5,7 @@ -- Copyright   :  (C) 2007 Andrea Rossato -- License     :  BSD3 ----- Maintainer  :  andrea.rossato@unibz.it+-- Maintainer  :  Spencer Janssen <spencerjanssen@gmail.com> -- Stability   :  unstable -- Portability :  unportable --@@ -18,11 +18,21 @@       -- $usage       mkXPrompt     , mkXPromptWithReturn+    , amberXPConfig     , defaultXPConfig+    , greenXPConfig     , XPType (..)     , XPPosition (..)     , XPConfig (..)     , XPrompt (..)+    , XP+    , defaultXPKeymap+    , quit+    , killBefore, killAfter, startOfLine, endOfLine+    , pasteString, copyString, moveCursor+    , moveWord, killWord, deleteString+    , moveHistory, setSuccess, setDone+    , Direction1D(..)     , ComplFunction     -- * X Utilities     -- $xutils@@ -44,27 +54,38 @@     , decodeInput     , encodeOutput     , historyCompletion+    , historyCompletionP+    -- * History filters+    , deleteAllDuplicates+    , deleteConsecutive     ) where -import XMonad  hiding (config, io)+import Prelude hiding (catch)++import XMonad  hiding (config, io, numlockMask, cleanMask)+import qualified XMonad as X (numlockMask,config) import qualified XMonad.StackSet as W import XMonad.Util.Font-import XMonad.Util.XSelection (getSelection)+import XMonad.Util.Types+import XMonad.Util.XSelection (getSelection, putSelection) -import Control.Arrow ((&&&))+import Control.Arrow ((&&&),first) import Control.Concurrent (threadDelay) import Control.Monad.Reader import Control.Monad.State import Control.Applicative ((<$>)) import Data.Char-import Data.Bits ((.&.))+import Data.Bits import Data.Maybe import Data.List import Data.Set (fromList, toList)-import System.Environment (getEnv)+import System.Directory import System.IO import System.Posix.Files+import Control.Exception hiding (handle) +import qualified Data.Map as M+ -- $usage -- For usage examples see "XMonad.Prompt.Shell", -- "XMonad.Prompt.XMonad" or "XMonad.Prompt.Ssh"@@ -83,13 +104,16 @@         , complWin           :: Maybe Window         , complWinDim        :: Maybe ComplWindowDim         , completionFunction :: String -> IO [String]+        , showComplWin       :: Bool         , gcon               :: !GC         , fontS              :: !XMonadFont         , xptype             :: !XPType-        , command            :: String+        , commandHistory     :: W.Stack String         , offset             :: !Int-        , history            :: [History]         , config             :: XPConfig+        , successful         :: Bool+        , numlockMask        :: KeyMask+        , done               :: Bool         }  data XPConfig =@@ -103,10 +127,17 @@         , position          :: XPPosition -- ^ Position: 'Top' or 'Bottom'         , height            :: !Dimension -- ^ Window height         , historySize       :: !Int       -- ^ The number of history entries to be saved+        , historyFilter     :: [String] -> [String]+                                         -- ^ a filter to determine which+                                         -- history entries to remember+        , promptKeymap      :: M.Map (KeyMask,KeySym) (XP ())+                                         -- ^ Mapping from key combinations to actions+        , completionKey     :: KeySym     -- ^ Key that should trigger completion         , defaultText       :: String     -- ^ The text by default in the prompt line         , autoComplete      :: Maybe Int  -- ^ Just x: if only one completion remains, auto-select it,-                                          --   and delay by x microseconds-        } deriving (Show, Read)+        , showCompletionOnTab :: Bool     -- ^ Only show list of completions when Tab was pressed+                                         --   and delay by x microseconds+        }  data XPType = forall p . XPrompt p => XPT p @@ -140,12 +171,12 @@     -- string presently in the command line and the list of     -- completion.     nextCompletion :: t -> String -> [String] -> String-    nextCompletion t c l = getNextOfLastWord t c l+    nextCompletion = getNextOfLastWord      -- | This method is used to generate the string to be passed to     -- the completion function.     commandToComplete :: t -> String -> String-    commandToComplete _ c = getLastWord c+    commandToComplete _ = getLastWord      -- | This method is used to process each completion in order to     -- generate the string that will be compared with the command@@ -161,26 +192,32 @@                 | Bottom                   deriving (Show,Read) -defaultXPConfig :: XPConfig+amberXPConfig, defaultXPConfig, greenXPConfig :: XPConfig+ defaultXPConfig =-    XPC { font              = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"-        , bgColor           = "#333333"-        , fgColor           = "#FFFFFF"-        , fgHLight          = "#000000"-        , bgHLight          = "#BBBBBB"-        , borderColor       = "#FFFFFF"+    XPC { font              = "-misc-fixed-*-*-*-*-12-*-*-*-*-*-*-*"+        , bgColor           = "grey22"+        , fgColor           = "grey80"+        , fgHLight          = "black"+        , bgHLight          = "grey"+        , borderColor       = "white"         , promptBorderWidth = 1+        , promptKeymap      = defaultXPKeymap+        , completionKey     = xK_Tab         , position          = Bottom         , height            = 18         , historySize       = 256+        , historyFilter     = id         , defaultText       = []         , autoComplete      = Nothing-        }+        , showCompletionOnTab = False }+greenXPConfig = defaultXPConfig { fgColor = "green", bgColor = "black" }+amberXPConfig = defaultXPConfig { fgColor = "#ca8f2d", bgColor = "black", fgHLight = "#eaaf4c" }  type ComplFunction = String -> IO [String]  initState :: XPrompt p => Display -> Window -> Window -> Rectangle -> ComplFunction-          -> GC -> XMonadFont -> p -> [History] -> XPConfig -> XPState+          -> GC -> XMonadFont -> p -> [String] -> XPConfig -> XPState initState d rw w s compl gc fonts pt h c =     XPS { dpy                = d         , rootw              = rw@@ -189,15 +226,27 @@         , complWin           = Nothing         , complWinDim        = Nothing         , completionFunction = compl+        , showComplWin       = not (showCompletionOnTab c)         , gcon               = gc         , fontS              = fonts         , xptype             = XPT pt-        , command            = defaultText c+        , commandHistory     = W.Stack { W.focus = defaultText c+                                       , W.up    = []+                                       , W.down  = h }         , offset             = length (defaultText c)-        , history            = h         , config             = c+        , successful         = False+        , done               = False+        , numlockMask        = X.numlockMask defaultConfig         } +-- this would be much easier with functional references+command :: XPState -> String+command = W.focus . commandHistory++setCommand :: String -> XPState -> XPState+setCommand xs s = s { commandHistory = (commandHistory s) { W.focus = xs }}+ -- | Same as 'mkXPrompt', except that the action function can have --   type @String -> X a@, for any @a@, and the final action returned --   by 'mkXPromptWithReturn' will have type @X (Maybe a)@.  @Nothing@@@ -210,25 +259,32 @@   let d = display c       rw = theRoot c   s <- gets $ screenRect . W.screenDetail . W.current . windowset+  hist <- liftIO readHistory   w <- liftIO $ createWin d rw conf s   liftIO $ selectInput d w $ exposureMask .|. keyPressMask   gc <- liftIO $ createGC d w   liftIO $ setGraphicsExposures d gc False-  (hist,h) <- liftIO $ readHistory   fs <- initXMF (font conf)-  let st = initState d rw w s compl gc fs (XPT t) hist conf+  numlock <- asks $ X.numlockMask . X.config+  let hs = fromMaybe [] $ M.lookup (showXPrompt t) hist+      st = (initState d rw w s compl gc fs (XPT t) hs conf)+           { numlockMask = numlock }   st' <- liftIO $ execStateT runXP st    releaseXMF fs   liftIO $ freeGC d gc-  liftIO $ hClose h-  if (command st' /= "")+  if successful st'     then do-      let htw = take (historySize conf) (history st')-      liftIO $ writeHistory htw+      liftIO $ writeHistory $ M.insertWith+                                (\xs ys -> take (historySize conf)+                                        . historyFilter conf $ xs ++ ys)+                                (showXPrompt t) (historyFilter conf [command st'])+                                hist+                                -- we need to apply historyFilter before as well, since+                                -- otherwise the filter would not be applied if+                                -- there is no history       Just <$> action (command st')-    else-      return Nothing+    else return Nothing  -- | Creates a prompt given: --@@ -271,42 +327,54 @@                         else return (Nothing, "")               return (ks,s,ev)   action (fromMaybe xK_VoidSymbol keysym,string) event+  gets done >>= flip unless (eventLoop handle) +-- | Removes numlock and capslock from a keymask.+-- Duplicate of cleanMask from core, but in the+-- XP monad instead of X.+cleanMask :: KeyMask -> XP KeyMask+cleanMask msk = do+  numlock <- gets numlockMask+  let highMasks = 1 `shiftL` 12 - 1+  return (complement (numlock .|. lockMask) .&. msk .&. highMasks)+ -- Main event handler handle :: KeyStroke -> Event -> XP ()-handle k@(ks,_) e@(KeyEvent {ev_event_type = t})-    | t == keyPress && ks == xK_Tab    = do+handle ks@(sym,_) e@(KeyEvent {ev_event_type = t, ev_state = m}) = do+  complKey <- gets $ completionKey . config   c <- getCompletions-  completionHandle c k e-handle ks (KeyEvent {ev_event_type = t, ev_state = m})-    | t == keyPress = keyPressHandle m ks+  when (length c > 1) $ modify (\s -> s { showComplWin = True })+  if complKey == sym+     then completionHandle c ks e+     else when (t == keyPress) $ keyPressHandle m ks handle _ (ExposeEvent {ev_window = w}) = do   st <- get   when (win st == w) updateWindows-  eventLoop handle-handle _  _ = eventLoop handle+handle _  _ = return ()  -- completion event handler completionHandle ::  [String] -> KeyStroke -> Event -> XP ()-completionHandle c (ks,_) (KeyEvent {ev_event_type = t})-    | t == keyPress && ks == xK_Tab = do-  st <- get-  let updateState l = do let new_command = nextCompletion (xptype st) (command st) l-                         modify $ \s ->  s { command = new_command, offset = length new_command }-      updateWins  l = do redrawWindows l-                         eventLoop (completionHandle l)-  case c of-    []  -> updateWindows   >> eventLoop handle-    [x] -> updateState [x] >> getCompletions >>= updateWins-    l   -> updateState l   >> updateWins l--- key release-    | t == keyRelease && ks == xK_Tab = eventLoop (completionHandle c)--- other keys-completionHandle _ ks (KeyEvent {ev_event_type = t, ev_state = m})-    | t == keyPress = keyPressHandle m ks+completionHandle c ks@(sym,_) (KeyEvent { ev_event_type = t, ev_state = m }) = do+  complKey <- gets $ completionKey . config+  case () of+    () | t == keyPress && sym == complKey ->+          do+            st <- get+            let updateState l =+                    let new_command = nextCompletion (xptype st) (command st) l+                    in modify $ \s -> setCommand new_command $ s { offset = length new_command }+                updateWins  l = redrawWindows l >>+                                eventLoop (completionHandle l)+            case c of+              []  -> updateWindows   >> eventLoop handle+              [x] -> updateState [x] >> getCompletions >>= updateWins+              l   -> updateState l   >> updateWins l+      | t == keyRelease && sym == complKey -> eventLoop (completionHandle c)+      | otherwise -> keyPressHandle m ks -- some other key, handle it normally -- some other event: go back to main loop completionHandle _ k e = handle k e + tryAutoComplete :: XP Bool tryAutoComplete = do     ac <- gets (autoComplete . config)@@ -319,73 +387,85 @@   where runCompleted cmd delay = do             st <- get             let new_command = nextCompletion (xptype st) (command st) [cmd]-            modify $ \s -> s { command = "autocompleting..." }+            modify $ setCommand "autocompleting..."             updateWindows             io $ threadDelay delay-            modify $ \s -> s { command = new_command }-            historyPush+            modify $ setCommand new_command             return True  -- KeyPresses -data Direction = Prev | Next deriving (Eq,Show,Read)+defaultXPKeymap :: M.Map (KeyMask,KeySym) (XP ())+defaultXPKeymap = M.fromList $+  map (first $ (,) controlMask) -- control + <key>+  [ (xK_u, killBefore)+  , (xK_k, killAfter)+  , (xK_a, startOfLine)+  , (xK_e, endOfLine)+  , (xK_y, pasteString)+  , (xK_c, copyString)+  , (xK_Right, moveWord Next)+  , (xK_Left, moveWord Prev)+  , (xK_Delete, killWord Next)+  , (xK_BackSpace, killWord Prev)+  , (xK_w, killWord Prev)+  , (xK_q, quit)+  ] +++  map (first $ (,) 0)+  [ (xK_Return, setSuccess True >> setDone True)+  , (xK_KP_Enter, setSuccess True >> setDone True)+  , (xK_BackSpace, deleteString Prev)+  , (xK_Delete, deleteString Next)+  , (xK_Left, moveCursor Prev)+  , (xK_Right, moveCursor Next)+  , (xK_Home, startOfLine)+  , (xK_End, endOfLine)+  , (xK_Down, moveHistory W.focusUp')+  , (xK_Up, moveHistory W.focusDown')+  , (xK_Escape, quit)+  ]  keyPressHandle :: KeyMask -> KeyStroke -> XP ()--- commands: ctrl + ... todo-keyPressHandle mask (ks,_)-    | (mask .&. controlMask) > 0 =-        -- control sequences-        case () of-          _ | ks == xK_u               -> killBefore    >> go-            | ks == xK_k               -> killAfter     >> go-            | ks == xK_a               -> startOfLine   >> go-            | ks == xK_e               -> endOfLine     >> go-            | ks == xK_y               -> pasteString   >> go-            | ks == xK_Right           -> moveWord Next >> go-            | ks == xK_Left            -> moveWord Prev >> go-            | ks == xK_Delete          -> killWord Next >> go-            | ks == xK_BackSpace       -> killWord Prev >> go-            | ks == xK_w               -> killWord Prev >> go-            | ks == xK_g || ks == xK_c -> quit-            | otherwise  -> eventLoop handle -- unhandled control sequence-    | ks == xK_Return    = historyPush       >> return ()-    | ks == xK_BackSpace = deleteString Prev >> go-    | ks == xK_Delete    = deleteString Next >> go-    | ks == xK_Left      = moveCursor   Prev >> go-    | ks == xK_Right     = moveCursor   Next >> go-    | ks == xK_Up        = moveHistory  Prev >> go-    | ks == xK_Down      = moveHistory  Next >> go-    | ks == xK_Home      = startOfLine       >> go-    | ks == xK_End       = endOfLine         >> go-    | ks == xK_Escape    = quit-    where-      go   = updateWindows >> eventLoop handle-      quit = flushString   >> return () -- quit and discard everything--- insert a character-keyPressHandle _ (_,s)-    | s == "" = eventLoop handle-    | otherwise = do insertString (decodeInput s)-                     updateWindows-                     completed <- tryAutoComplete-                     unless completed $ eventLoop handle+keyPressHandle m (ks,str) = do+  km <- gets (promptKeymap . config)+  mask <- cleanMask m+  case M.lookup (mask,ks) km of+    Just action -> action >> updateWindows+    Nothing -> case str of+                 "" -> eventLoop handle+                 _ -> when (mask .&. controlMask == 0) $ do+                                 insertString (decodeInput str)+                                 updateWindows+                                 completed <- tryAutoComplete+                                 when completed $ setSuccess True >> setDone True +setSuccess :: Bool -> XP ()+setSuccess b = modify $ \s -> s { successful = b }++setDone :: Bool -> XP ()+setDone b = modify $ \s -> s { done = b }+ -- KeyPress and State +-- | Quit.+quit :: XP ()+quit = flushString >> setSuccess False >> setDone True+ -- | Kill the portion of the command before the cursor killBefore :: XP () killBefore =-  modify $ \s -> s { command = drop (offset s) (command s)-                   , offset  = 0 }+  modify $ \s -> setCommand (drop (offset s) (command s)) $ s { offset  = 0 }  -- | Kill the portion of the command including and after the cursor killAfter :: XP () killAfter =-  modify $ \s -> s { command = take (offset s) (command s) }+  modify $ \s -> setCommand (take (offset s) (command s)) s  -- | Kill the next\/previous word-killWord :: Direction -> XP ()+killWord :: Direction1D -> XP () killWord d = do-  XPS { command = c, offset = o } <- get+  o <- gets offset+  c <- gets command   let (f,ss)        = splitAt o c       delNextWord w =           case w of@@ -396,7 +476,7 @@           case d of             Next -> (f ++ delNextWord ss, o)             Prev -> (delPrevWord f ++ ss, length $ delPrevWord f) -- laziness!!-  modify $ \s -> s { command = ncom, offset = noff}+  modify $ \s -> setCommand ncom $ s { offset = noff}  -- | Put the cursor at the end of line endOfLine :: XP ()@@ -410,13 +490,12 @@  -- |  Flush the command string and reset the offset flushString :: XP ()-flushString = do-  modify $ \s -> s { command = "", offset = 0}+flushString = modify $ \s -> setCommand "" $ s { offset = 0}  -- | Insert a character at the cursor position insertString :: String -> XP () insertString str =-  modify $ \s -> s { command = c (command s) (offset s), offset = o (offset s)}+  modify $ \s -> setCommand (c (command s) (offset s)) $ s { offset = o (offset s)}   where o oo = oo + length str         c oc oo | oo >= length oc = oc ++ str                 | otherwise = f ++ str ++ ss@@ -424,12 +503,16 @@  -- | Insert the current X selection string at the cursor position. pasteString :: XP ()-pasteString = join $ io $ liftM insertString $ getSelection+pasteString = join $ io $ liftM insertString getSelection +-- | Copy the currently entered string into the X selection.+copyString :: XP ()+copyString = gets command >>= io . putSelection+ -- | Remove a character at the cursor position-deleteString :: Direction -> XP ()+deleteString :: Direction1D -> XP () deleteString d =-  modify $ \s -> s { command = c (command s) (offset s), offset = o (offset s)}+  modify $ \s -> setCommand (c (command s) (offset s)) $ s { offset = o (offset s)}   where o oo = if d == Prev then max 0 (oo - 1) else oo         c oc oo             | oo >= length oc && d == Prev = take (oo - 1) oc@@ -439,13 +522,13 @@             where (f,ss) = splitAt oo oc  -- | move the cursor one position-moveCursor :: Direction -> XP ()+moveCursor :: Direction1D -> XP () moveCursor d =   modify $ \s -> s { offset = o (offset s) (command s)}   where o oo c = if d == Prev then max 0 (oo - 1) else min (length c) (oo + 1)  -- | move the cursor one word-moveWord :: Direction -> XP ()+moveWord :: Direction1D -> XP () moveWord d = do   c <- gets command   o <- gets offset@@ -455,21 +538,14 @@                  ' ':x -> 1 + lenToS x                  x     -> lenToS x       newoff = case d of-                 Prev -> o - (ln reverse f )-                 Next -> o + (ln id      ss)+                 Prev -> o - ln reverse f+                 Next -> o + ln id ss   modify $ \s -> s { offset = newoff } -moveHistory :: Direction -> XP ()-moveHistory d = do-  h <- getHistory-  c <- gets command-  let str = if h /= [] then head h else c-  let nc = case elemIndex c h of-             Just i -> case d of-                         Prev -> h !! (if (i + 1) > (length h - 1) then 0 else i + 1)-                         Next -> h !! (max (i - 1) 0)-             Nothing -> str-  modify $ \s -> s { command = nc, offset = length nc}+moveHistory :: (W.Stack String -> W.Stack String) -> XP ()+moveHistory f = modify $ \s -> let ch = f $ commandHistory s+                               in s { commandHistory = ch+                                    , offset         = length $ W.focus ch }  -- X Stuff @@ -550,7 +626,7 @@ getCompletions :: XP [String] getCompletions = do   s <- get-  io $ (completionFunction s) (commandToComplete (xptype s) (command s))+  io $ completionFunction s (commandToComplete (xptype s) (command s))        `catch` \_ -> return []  setComplWin :: Window -> ComplWindowDim -> XP ()@@ -590,9 +666,9 @@    tws <- mapM (textWidthXMF (dpy st) fs) compl   let max_compl_len =  fromIntegral ((fi ht `div` 2) + maximum tws)-      columns = max 1 $ wh `div` (fi max_compl_len)+      columns = max 1 $ wh `div` fi max_compl_len       rem_height =  rect_height scr - ht-      (rows,r) = (length compl) `divMod` fi columns+      (rows,r) = length compl `divMod` fi columns       needed_rows = max 1 (rows + if r == 0 then 0 else 1)       actual_max_number_of_rows = rem_height `div` ht       actual_rows = min actual_max_number_of_rows (fi needed_rows)@@ -624,7 +700,7 @@   p <- io $ createPixmap d w wh ht                          (defaultDepthOfScreen scr)   io $ fillDrawable d p gc border bgcolor (fi bw) wh ht-  let ac = splitInSubListsAt (length yy) (take ((length xx) * (length yy)) compl)+  let ac = splitInSubListsAt (length yy) (take (length xx * length yy) compl)   printComplList d p gc (fgColor c) (bgColor c) xx yy ac   io $ copyArea d p w gc 0 0 wh ht 0 0   io $ freePixmap d p@@ -636,7 +712,7 @@   let recreate = do destroyComplWin                     w <- createComplWin nwi                     drawComplWin w compl-  if (compl /= [] )+  if compl /= [] && showComplWin st      then case complWin st of             Just w -> case complWinDim st of                         Just wi -> if nwi == wi -- complWinDim did not change@@ -673,41 +749,28 @@  -- History -data History =-    H { prompt :: String-      , command_history :: String-      } deriving (Show, Read, Eq)+type History = M.Map String [String] -historyPush :: XP ()-historyPush = do-  c <- gets command-  when (c /= []) $ modify (\s -> s { history = nub $ H (showXPrompt (xptype s)) c : history s })+emptyHistory :: History+emptyHistory = M.empty -getHistory :: XP [String]-getHistory = do-  hist <- gets history-  pt <- gets xptype-  return $ map command_history . filter (\h -> prompt h == showXPrompt pt) $ hist+getHistoryFile :: IO FilePath+getHistoryFile = fmap (++ "/history") $ getAppUserDataDirectory "xmonad" -readHistory :: IO ([History],Handle)-readHistory = do-  home <- getEnv "HOME"-  let path = home ++ "/.xmonad/history"-  f <- fileExist path-  if f then do h <- openFile path ReadMode-               str <- hGetContents h-               case (reads str) of-                 [(hist,_)] -> return (hist,h)-                 [] -> return ([],h)-                 _ -> return ([],h)-       else do h <- openFile path WriteMode-               return ([],h)+readHistory :: IO History+readHistory = catch readHist (const (return emptyHistory))+ where+    readHist = do+        path <- getHistoryFile+        xs <- bracket (openFile path ReadMode) hClose hGetLine+        readIO xs -writeHistory :: [History] -> IO ()+writeHistory :: History -> IO () writeHistory hist = do-  home <- getEnv "HOME"-  let path = home ++ "/.xmonad/history"-  catch (writeFile path (show hist)) (\_ -> do putStrLn "error in writing"; return ())+  path <- getHistoryFile+  catch (writeFile path (show hist)) $ const $ hPutStrLn stderr "error in writing"+  setFileMode path mode+    where mode = ownerReadMode .|. ownerWriteMode  -- $xutils @@ -802,18 +865,27 @@       where (s1, s2 ) = break isSpace s             (s1',s2') = breakAtSpace $ tail s2 --- | Sort a list and remove duplicates.-uniqSort :: Ord a => [a] -> [a]-uniqSort = toList . fromList- -- | 'historyCompletion' provides a canned completion function much like---   getShellCompl; you pass it to mkXPrompt, and it will make completions work---   from the query history stored in ~/.xmonad/history.+--   'getShellCompl'; you pass it to mkXPrompt, and it will make completions work+--   from the query history stored in ~\/.xmonad\/history. historyCompletion :: ComplFunction-historyCompletion = \x -> liftM (filter $ isInfixOf x) readHistoryIO+historyCompletion = historyCompletionP (const True) --- We need to define this locally because there is no function with the type "XP a -> IO a", and--- 'getHistory' is uselessly of the type "XP [String]".-readHistoryIO :: IO [String]-readHistoryIO = do (hist,_) <- readHistory-                   return $ map command_history hist+-- | Like 'historyCompletion' but only uses history data from Prompts whose+-- name satisfies the given predicate.+historyCompletionP :: (String -> Bool) -> ComplFunction+historyCompletionP p x = fmap (toComplList . M.filterWithKey (const . p)) readHistory+    where toComplList = deleteConsecutive . filter (isInfixOf x) . M.fold (++) []++-- | Sort a list and remove duplicates. Like 'deleteAllDuplicates', but trades off+--   laziness and stability for efficiency.+uniqSort :: Ord a => [a] -> [a]+uniqSort = toList . fromList++-- | Functions to be used with the 'historyFilter' setting.+-- 'deleteAllDuplicates' will remove all duplicate entries.+-- 'deleteConsecutive' will only remove duplicate elements+-- immediately next to each other.+deleteAllDuplicates, deleteConsecutive :: [String] -> [String]+deleteAllDuplicates = nub+deleteConsecutive = map head . group
XMonad/Prompt/AppLauncher.hs view
@@ -8,14 +8,14 @@ -- Stability   :  unstable -- Portability :  unportable ----- A module for launch applicationes that receive parameters in the command +-- A module for launch applicationes that receive parameters in the command -- line. The launcher call a prompt to get the parameters. -- ----------------------------------------------------------------------------- module XMonad.Prompt.AppLauncher ( -- * Usage                                     -- $usage                                     launchApp-                                   +                                   ,module XMonad.Prompt                                   -- * Use case: launching gimp with file                                   -- $tip                                   ) where@@ -31,7 +31,7 @@    you want to open a image in gimp program, you can open gimp and then use    the File Menu to open the image or you can use this module to select    the image in the command line.-   +    We use Prompt to get the user command line. This also allow to autoexpand    the names of the files when we are writing the command line.  -}
XMonad/Prompt/AppendFile.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD-style (see LICENSE) -- -- Maintainer  :  <byorgey@gmail.com>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- A prompt for appending a single line of text to a file.  Useful for@@ -41,7 +41,7 @@ -- -- and adding an appropriate keybinding, for example: ----- >  , ((modMask x .|. controlMask, xK_n), appendFilePrompt defaultXPConfig "/home/me/NOTES")+-- >  , ((modm .|. controlMask, xK_n), appendFilePrompt defaultXPConfig "/home/me/NOTES") -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -61,6 +61,4 @@  -- | Append a string to a file. doAppend :: FilePath -> String -> X ()-doAppend fn s = io $ bracket (openFile fn AppendMode)-                             hClose-                             (flip hPutStrLn s)+doAppend fn = io . bracket (openFile fn AppendMode) hClose . flip hPutStrLn
XMonad/Prompt/Directory.hs view
@@ -4,7 +4,7 @@ -- Copyright   :  (C) 2007 Andrea Rossato, David Roundy -- License     :  BSD3 ----- Maintainer  :  droundy@darcs.net+-- Maintainer  :   -- Stability   :  unstable -- Portability :  unportable --@@ -31,7 +31,7 @@     showXPrompt (Dir x) = x  directoryPrompt :: XPConfig -> String -> (String -> X ()) -> X ()-directoryPrompt c prom job = mkXPrompt (Dir prom) c getDirCompl job+directoryPrompt c prom = mkXPrompt (Dir prom) c getDirCompl  getDirCompl :: String -> IO [String] getDirCompl s = (filter notboring . lines) `fmap`
XMonad/Prompt/Email.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD-style (see LICENSE) -- -- Maintainer  :  <byorgey@gmail.com>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- A prompt for sending quick, one-line emails, via the standard GNU@@ -36,7 +36,7 @@ -- -- and adding an appropriate keybinding, for example: ----- >  , ((modMask x .|. controlMask, xK_e), emailPrompt defaultXPConfig addresses)+-- >  , ((modm .|. controlMask, xK_e), emailPrompt defaultXPConfig addresses) -- -- where @addresses@ is a list of email addresses that should -- autocomplete, for example:
XMonad/Prompt/Input.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD-style (see LICENSE) -- -- Maintainer  :  <byorgey@gmail.com>--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- A generic framework for prompting the user for input and passing it@@ -59,7 +59,7 @@ -- Now all he has to do is add a keybinding to @firingPrompt@ (or -- @firingPrompt'@), such as ----- >  , ((modMask x .|. controlMask, xK_f),  firingPrompt)+-- >  , ((modm .|. controlMask, xK_f),  firingPrompt) -- -- Now when Mr. Big hits mod-ctrl-f, a prompt will pop up saying -- \"Fire: \", waiting for him to type the name of someone to fire.
XMonad/Prompt/Layout.hs view
@@ -4,7 +4,7 @@ -- Copyright   :  (C) 2007 Andrea Rossato, David Roundy -- License     :  BSD3 ----- Maintainer  :  droundy@darcs.net+-- Maintainer  :   -- Stability   :  unstable -- Portability :  unportable --@@ -30,7 +30,7 @@ -- > import XMonad.Prompt -- > import XMonad.Prompt.Layout ----- >   , ((modMask x .|. shiftMask, xK_m     ), layoutPrompt defaultXPConfig)+-- >   , ((modm .|. shiftMask, xK_m     ), layoutPrompt defaultXPConfig) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -50,7 +50,4 @@  layoutPrompt :: XPConfig -> X () layoutPrompt c = do ls <- gets (map (description . layout) . workspaces . windowset)-                    mkXPrompt (Wor "") c (mkCompl $ sort $ nub ls) (sendMessage . JumpToLayout)--mkCompl :: [String] -> String -> IO [String]-mkCompl l s = return $ filter (\x -> take (length s) x == s) l+                    mkXPrompt (Wor "") c (mkComplFunFromList' $ sort $ nub ls) (sendMessage . JumpToLayout)
XMonad/Prompt/Man.hs view
@@ -44,7 +44,7 @@ -- -- 2. In your keybindings add something like: ----- >     , ((modMask x, xK_F1), manPrompt defaultXPConfig)+-- >     , ((modm, xK_F1), manPrompt defaultXPConfig) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -88,12 +88,12 @@ -- better\/more idiomatic.) getCommandOutput :: String -> IO String getCommandOutput s = do-  (pin, pout, perr, ph) <- runInteractiveCommand s+  -- we can ignore the process handle because we ignor SIGCHLD+  (pin, pout, perr, _) <- runInteractiveCommand s   hClose pin   output <- hGetContents pout   E.evaluate (length output)   hClose perr-  waitForProcess ph   return output  stripExt :: String -> String
XMonad/Prompt/RunOrRaise.hs view
@@ -25,7 +25,7 @@ import XMonad.Actions.WindowGo (runOrRaise) import XMonad.Util.Run (runProcessWithInput) -import Control.Monad (liftM2)+import Control.Monad (liftM, liftM2) import Data.Maybe import System.Directory (doesDirectoryExist, doesFileExist, executable, getPermissions) @@ -37,7 +37,7 @@  2. In your keybindings add something like: ->   , ((modMask x .|. controlMask, xK_x), runOrRaisePrompt defaultXPConfig)+>   , ((modm .|. controlMask, xK_x), runOrRaisePrompt defaultXPConfig)  For detailed instruction on editing the key binding see "XMonad.Doc.Extending#Editing_key_bindings". -}@@ -47,15 +47,15 @@     showXPrompt RRP = "Run or Raise: "  runOrRaisePrompt :: XPConfig -> X ()-runOrRaisePrompt c = do cmds <- io $ getCommands+runOrRaisePrompt c = do cmds <- io getCommands                         mkXPrompt RRP c (getShellCompl cmds) open open :: String -> X ()-open path = (io $ isNormalFile path) >>= \b ->+open path = io (isNormalFile path) >>= \b ->             if b             then spawn $ "xdg-open \"" ++ path ++ "\""             else uncurry runOrRaise . getTarget $ path     where-      isNormalFile f = exists f >>= \e -> if e then (notExecutable f) else return False+      isNormalFile f = exists f >>= \e -> if e then notExecutable f else return False       exists f = fmap or $ sequence [doesFileExist f,doesDirectoryExist f]       notExecutable = fmap (not . executable) . getPermissions       getTarget x = (x,isApp x)@@ -66,12 +66,12 @@ isApp x = liftM2 (==) pid $ pidof x  pidof :: String -> Query Int-pidof x = io $ (runProcessWithInput "pidof" [x] [] >>= readIO) `catch` (\_ -> return $ 0)+pidof x = io $ (runProcessWithInput "pidof" [x] [] >>= readIO) `catch` (\_ -> return 0)  pid :: Query Int pid = ask >>= (\w -> liftX $ withDisplay $ \d -> getPID d w)     where getPID d w = getAtom "_NET_WM_PID" >>= \a -> io $-                       getWindowProperty32 d a w >>= return . getPID'+                       liftM getPID' (getWindowProperty32 d a w)           getPID' (Just (x:_)) = fromIntegral x           getPID' (Just [])     = -1           getPID' (Nothing)     = -1
XMonad/Prompt/Shell.hs view
@@ -15,7 +15,8 @@ module XMonad.Prompt.Shell     ( -- * Usage       -- $usage-      shellPrompt+      Shell (..)+    , shellPrompt     , getCommands     , getBrowser     , getEditor@@ -43,7 +44,7 @@ -- -- 2. In your keybindings add something like: ----- >   , ((modMask x .|. controlMask, xK_x), shellPrompt defaultXPConfig)+-- >   , ((modm .|. controlMask, xK_x), shellPrompt defaultXPConfig) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -56,7 +57,7 @@  shellPrompt :: XPConfig -> X () shellPrompt c = do-    cmds <- io $ getCommands+    cmds <- io getCommands     mkXPrompt Shell c (getShellCompl cmds) (spawn . encodeOutput)  -- | See safe and unsafeSpawn. prompt is an alias for safePrompt;@@ -66,8 +67,8 @@ -- is the program to be run with the interactive input. -- You would use these like this: ----- >     , ((modMask,               xK_b), safePrompt "firefox" greenXPConfig)--- >     , ((modMask .|. shiftMask, xK_c), prompt ("xterm" ++ " -e") greenXPConfig)+-- >     , ((modm,               xK_b), safePrompt "firefox" greenXPConfig)+-- >     , ((modm .|. shiftMask, xK_c), prompt ("xterm" ++ " -e") greenXPConfig) -- -- Note that you want to use safePrompt for Firefox input, as Firefox -- wants URLs, and unsafePrompt for the XTerm example because this allows@@ -76,7 +77,7 @@ prompt, unsafePrompt, safePrompt :: FilePath -> XPConfig -> X () prompt = unsafePrompt safePrompt c config = mkXPrompt Shell config (getShellCompl [c]) run-    where run = safeSpawn c . encodeOutput+    where run = safeSpawn c . return . encodeOutput unsafePrompt c config = mkXPrompt Shell config (getShellCompl [c]) run     where run a = unsafeSpawn $ c ++ " " ++ encodeOutput a @@ -117,13 +118,12 @@  escape :: String -> String escape []       = ""-escape (' ':xs) = "\\ " ++ escape xs escape (x:xs)     | isSpecialChar x = '\\' : x : escape xs     | otherwise       = x : escape xs  isSpecialChar :: Char -> Bool-isSpecialChar =  flip elem "\\@\"'#?$*()[]{};"+isSpecialChar =  flip elem " &\\@\"'#?$*()[]{};"  -- | Ask the shell environment for env :: String -> String -> IO String
XMonad/Prompt/Ssh.hs view
@@ -37,7 +37,7 @@ -- -- 2. In your keybindings add something like: ----- >   , ((modMask x .|. controlMask, xK_s), sshPrompt defaultXPConfig)+-- >   , ((modm .|. controlMask, xK_s), sshPrompt defaultXPConfig) -- -- Keep in mind, that if you want to use the completion you have to -- disable the "HashKnownHosts" option in your ssh_config@@ -54,11 +54,11 @@  sshPrompt :: XPConfig -> X () sshPrompt c = do-  sc <- io $ sshComplList+  sc <- io sshComplList   mkXPrompt Ssh c (mkComplFunFromList sc) ssh  ssh :: String -> X ()-ssh s = runInTerm "" ("ssh " ++ s)+ssh = runInTerm "" . ("ssh " ++ )  sshComplList :: IO [String] sshComplList = uniqSort `fmap` liftM2 (++) sshComplListLocal sshComplListGlobal
XMonad/Prompt/Theme.hs view
@@ -35,7 +35,7 @@ -- -- in your keybindings add: ----- >   , ((modMask x .|. controlMask, xK_t), themePrompt defaultXPConfig)+-- >   , ((modm .|. controlMask, xK_t), themePrompt defaultXPConfig) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".
XMonad/Prompt/Window.hs view
@@ -19,7 +19,8 @@     -- * Usage     -- $usage     windowPromptGoto,-    windowPromptBring+    windowPromptBring,+    windowPromptBringCopy     ) where  import qualified Data.Map as M@@ -28,6 +29,7 @@ import qualified XMonad.StackSet as W import XMonad import XMonad.Prompt+import XMonad.Actions.CopyWindow import XMonad.Actions.WindowBringer  -- $usage@@ -42,12 +44,12 @@ -- -- and in the keys definition: ----- > , ((modMask x .|. shiftMask, xK_g     ), windowPromptGoto  defaultXPConfig)--- > , ((modMask x .|. shiftMask, xK_b     ), windowPromptBring defaultXPConfig)+-- > , ((modm .|. shiftMask, xK_g     ), windowPromptGoto  defaultXPConfig)+-- > , ((modm .|. shiftMask, xK_b     ), windowPromptBring defaultXPConfig) -- -- The autoComplete option is a handy complement here: ----- > , ((modMask x .|. shiftMask, xK_g     ), windowPromptGoto+-- > , ((modm .|. shiftMask, xK_g     ), windowPromptGoto -- >                                            defaultXPConfig { autoComplete = Just 500000 } ) -- -- The \'500000\' is the number of microseconds to pause before sending you to@@ -57,16 +59,18 @@ -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings". -data WindowPrompt = Goto | Bring+data WindowPrompt = Goto | Bring | BringCopy instance XPrompt WindowPrompt where     showXPrompt Goto      = "Go to window: "-    showXPrompt Bring     = "Bring me here: "+    showXPrompt Bring     = "Bring window: "+    showXPrompt BringCopy = "Bring a copy: "     commandToComplete _ c = c     nextCompletion      _ = getNextCompletion -windowPromptGoto, windowPromptBring :: XPConfig -> X ()-windowPromptGoto  c = doPrompt Goto  c-windowPromptBring c = doPrompt Bring c+windowPromptGoto, windowPromptBring, windowPromptBringCopy :: XPConfig -> X ()+windowPromptGoto  = doPrompt Goto+windowPromptBring = doPrompt Bring+windowPromptBringCopy = doPrompt BringCopy  -- | Pops open a prompt with window titles. Choose one, and you will be -- taken to the corresponding workspace.@@ -75,6 +79,7 @@   a <- case t of          Goto  -> fmap gotoAction  windowMap          Bring -> fmap bringAction windowMap+         BringCopy -> fmap bringCopyAction windowMap   wm <- windowMap   mkXPrompt t c (compList wm) a @@ -82,5 +87,11 @@       winAction a m    = flip whenJust (windows . a) . flip M.lookup m       gotoAction       = winAction W.focusWindow       bringAction      = winAction bringWindow+      bringCopyAction  = winAction bringCopyWindow        compList m s = return . filter (isPrefixOf s) . map fst . M.toList $ m+++-- | Brings a copy of the specified window into the current workspace.+bringCopyWindow :: Window -> WindowSet -> WindowSet+bringCopyWindow w ws = copyWindow w (W.currentTag ws) ws
XMonad/Prompt/Workspace.hs view
@@ -4,7 +4,7 @@ -- Copyright   :  (C) 2007 Andrea Rossato, David Roundy -- License     :  BSD3 ----- Maintainer  :  droundy@darcs.net+-- Maintainer  :   -- Stability   :  unstable -- Portability :  unportable --@@ -29,7 +29,7 @@ -- > import XMonad.Prompt -- > import XMonad.Prompt.Workspace ----- >   , ((modMask x .|. shiftMask, xK_m     ), workspacePrompt defaultXPConfig (windows . W.shift))+-- >   , ((modm .|. shiftMask, xK_m     ), workspacePrompt defaultXPConfig (windows . W.shift)) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".@@ -43,7 +43,4 @@ workspacePrompt c job = do ws <- gets (workspaces . windowset)                            sort <- getSortByIndex                            let ts = map tag $ sort ws-                           mkXPrompt (Wor "") c (mkCompl ts) job--mkCompl :: [String] -> String -> IO [String]-mkCompl l s = return $ filter (\x -> take (length s) x == s) l+                           mkXPrompt (Wor "") c (mkComplFunFromList' ts) job
XMonad/Prompt/XMonad.hs view
@@ -32,7 +32,7 @@ -- -- in your keybindings add: ----- >   , ((modMask x .|. controlMask, xK_x), xmonadPrompt defaultXPConfig)+-- >   , ((modm .|. controlMask, xK_x), xmonadPrompt defaultXPConfig) -- -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings".
+ XMonad/Util/Cursor.hs view
@@ -0,0 +1,46 @@+----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.Cursor+-- Copyright   :  (c) 2009 Collabora Ltd+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  Andres Salomon <dilinger@collabora.co.uk>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A module for setting the default mouse cursor.+--+-- Some ideas shamelessly stolen from Nils Schweinsberg; thanks!+-----------------------------------------------------------------------------++module XMonad.Util.Cursor+    ( -- * Usage:+      -- $usage+      module Graphics.X11.Xlib.Cursor,+      setDefaultCursor+    ) where++import Graphics.X11.Xlib.Cursor+import XMonad++-- $usage+--+-- >   setDefaultCursor xC_left_ptr+--+--   For example, to override the default gnome cursor:+--+-- >   import XMonad.Util.Cursor+-- >   main = xmonad gnomeConfig { startupHook = setDefaultCursor xC_pirate }+--+--   Arrr!++-- | Set the default (root) cursor+setDefaultCursor :: Glyph -> X ()+setDefaultCursor glyph = do+    dpy <- asks display+    rootw <- asks theRoot+    liftIO $ do+        curs <- createFontCursor dpy glyph+        defineCursor dpy rootw curs+        flush dpy+        freeCursor dpy curs
XMonad/Util/Dmenu.hs view
@@ -15,10 +15,10 @@ -----------------------------------------------------------------------------  module XMonad.Util.Dmenu (-                            -- * Usage-                            -- $usage-                            dmenu, dmenuXinerama, dmenuMap-                           ) where+                -- * Usage+                -- $usage+                dmenu, dmenuXinerama, dmenuMap, menu, menuMap+               ) where  import XMonad import qualified XMonad.StackSet as W@@ -40,9 +40,17 @@     io $ runProcessWithInput "dmenu" ["-xs", show (curscreen+1)] (unlines opts)  dmenu :: [String] -> X String-dmenu opts = io $ runProcessWithInput "dmenu" [] (unlines opts)+dmenu opts = menu "dmenu" opts -dmenuMap :: M.Map String a -> X (Maybe a)-dmenuMap selectionMap = do-  selection <- dmenu (M.keys selectionMap)+menu :: String -> [String] -> X String+menu menuCmd opts = io $ runProcessWithInput menuCmd [] (unlines opts)++menuMap :: String -> M.Map String a -> X (Maybe a)+menuMap menuCmd selectionMap = do+  selection <- menuFunction (M.keys selectionMap)   return $ M.lookup selection selectionMap+      where+        menuFunction = menu menuCmd++dmenuMap :: M.Map String a -> X (Maybe a)+dmenuMap selectionMap = menuMap "dmenu" selectionMap
XMonad/Util/Dzen.hs view
@@ -5,7 +5,7 @@ -- License     :  BSD -- -- Maintainer  :  glasser@mit.edu--- Stability   :  unstable+-- Stability   :  stable -- Portability :  unportable -- -- Handy wrapper for dzen. Requires dzen >= 0.2.4.
XMonad/Util/EZConfig.hs view
@@ -27,13 +27,16 @@                              -- * Emacs-style keybinding specifications                               mkKeymap, checkKeymap,+                             mkNamedKeymap                             ) where  import XMonad import XMonad.Actions.Submap +import XMonad.Util.NamedActions+ import qualified Data.Map as M-import Data.List (foldl', intersperse, sortBy, groupBy, nub)+import Data.List (foldl', sortBy, groupBy, nub) import Data.Ord (comparing) import Data.Maybe import Control.Arrow (first, (&&&))@@ -56,7 +59,7 @@ -- provided, suitable for adding to your 'startupHook', which can warn -- you of any parse errors or duplicate bindings in your keymap. ----- For more information and usage eamples, see the documentation+-- For more information and usage examples, see the documentation -- provided with each exported function, and check the xmonad config -- archive (<http://haskell.org/haskellwiki/Xmonad/Config_archive>) -- for some real examples of use.@@ -134,11 +137,16 @@ --   the key sequence descriptions contained in the Strings.  The key --   sequence descriptions are \"emacs-style\": @M-@, @C-@, @S-@, and --   @M\#-@ denote mod, control, shift, and mod1-mod5 (where @\#@ is---   replaced by the appropriate number) respectively; some special---   keys can be specified by enclosing their name in angle brackets.+--   replaced by the appropriate number) respectively.  Note that if+--   you want to make a keybinding using \'alt\' even though you use a+--   different key (like the \'windows\' key) for \'mod\', you can use+--   something like @\"M1-x\"@ for alt+x (check the output of @xmodmap@+--   to see which mod key \'alt\' is bound to). Some special keys can+--   also be specified by enclosing their name in angle brackets. -----   For example, @\"M-C-x\"@ denotes mod+ctrl+x; @\"S-\<Escape\>\"@ denotes---   shift-escape.+--   For example, @\"M-C-x\"@ denotes mod+ctrl+x; @\"S-\<Escape\>\"@+--   denotes shift-escape; @\"M1-C-\<Delete\>\"@ denotes alt+ctrl+delete+--   (assuming alt is bound to mod1, which is common). -- --   Sequences of keys can also be specified by separating the key --   descriptions with spaces. For example, @\"M-x y \<Down\>\"@ denotes the@@ -159,7 +167,10 @@ -- create a keymap and add it to your config. -- -- Here is a complete list of supported special keys.  Note that a few--- keys, such as the arrow keys, have synonyms:+-- keys, such as the arrow keys, have synonyms.  If there are other+-- special keys you would like to see supported, feel free to submit a+-- patch, or ask on the xmonad mailing list; adding special keys is+-- quite simple. -- -- > <Backspace> -- > <Tab>@@ -167,6 +178,7 @@ -- > <Pause> -- > <Scroll_lock> -- > <Sys_Req>+-- > <Print> -- > <Escape>, <Esc> -- > <Delete> -- > <Home>@@ -208,30 +220,158 @@ -- > <KP_Subtract> -- > <KP_Decimal> -- > <KP_Divide>--- > <KP_0>--- > <KP_1>--- > <KP_2>--- > <KP_3>--- > <KP_4>--- > <KP_5>--- > <KP_6>--- > <KP_7>--- > <KP_8>--- > <KP_9>+-- > <KP_0>-<KP_9>+--+-- Long list of multimedia keys. Please note that not all keys may be+-- present in your particular setup although most likely they will do.+--+-- > <XF86ModeLock>+-- > <XF86MonBrightnessUp>+-- > <XF86MonBrightnessDown>+-- > <XF86KbdLightOnOff>+-- > <XF86KbdBrightnessUp>+-- > <XF86KbdBrightnessDown>+-- > <XF86Standby>+-- > <XF86AudioLowerVolume>+-- > <XF86AudioMute>+-- > <XF86AudioRaiseVolume>+-- > <XF86AudioPlay>+-- > <XF86AudioStop>+-- > <XF86AudioPrev>+-- > <XF86AudioNext>+-- > <XF86HomePage>+-- > <XF86Mail>+-- > <XF86Start>+-- > <XF86Search>+-- > <XF86AudioRecord>+-- > <XF86Calculator>+-- > <XF86Memo>+-- > <XF86ToDoList>+-- > <XF86Calendar>+-- > <XF86PowerDown>+-- > <XF86ContrastAdjust>+-- > <XF86RockerUp>+-- > <XF86RockerDown>+-- > <XF86RockerEnter>+-- > <XF86Back>+-- > <XF86Forward>+-- > <XF86Stop>+-- > <XF86Refresh>+-- > <XF86PowerOff>+-- > <XF86WakeUp>+-- > <XF86Eject>+-- > <XF86ScreenSaver>+-- > <XF86WWW>+-- > <XF86Sleep>+-- > <XF86Favorites>+-- > <XF86AudioPause>+-- > <XF86AudioMedia>+-- > <XF86MyComputer>+-- > <XF86VendorHome>+-- > <XF86LightBulb>+-- > <XF86Shop>+-- > <XF86History>+-- > <XF86OpenURL>+-- > <XF86AddFavorite>+-- > <XF86HotLinks>+-- > <XF86BrightnessAdjust>+-- > <XF86Finance>+-- > <XF86Community>+-- > <XF86AudioRewind>+-- > <XF86XF86BackForward>+-- > <XF86Launch0>-<XF86Launch9>, <XF86LaunchA>-<XF86LaunchF>+-- > <XF86ApplicationLeft>+-- > <XF86ApplicationRight>+-- > <XF86Book>+-- > <XF86CD>+-- > <XF86Calculater>+-- > <XF86Clear>+-- > <XF86Close>+-- > <XF86Copy>+-- > <XF86Cut>+-- > <XF86Display>+-- > <XF86DOS>+-- > <XF86Documents>+-- > <XF86Excel>+-- > <XF86Explorer>+-- > <XF86Game>+-- > <XF86Go>+-- > <XF86iTouch>+-- > <XF86LogOff>+-- > <XF86Market>+-- > <XF86Meeting>+-- > <XF86MenuKB>+-- > <XF86MenuPB>+-- > <XF86MySites>+-- > <XF86New>+-- > <XF86News>+-- > <XF86OfficeHome>+-- > <XF86Open>+-- > <XF86Option>+-- > <XF86Paste>+-- > <XF86Phone>+-- > <XF86Q>+-- > <XF86Reply>+-- > <XF86Reload>+-- > <XF86RotateWindows>+-- > <XF86RotationPB>+-- > <XF86RotationKB>+-- > <XF86Save>+-- > <XF86ScrollUp>+-- > <XF86ScrollDown>+-- > <XF86ScrollClick>+-- > <XF86Send>+-- > <XF86Spell>+-- > <XF86SplitScreen>+-- > <XF86Support>+-- > <XF86TaskPane>+-- > <XF86Terminal>+-- > <XF86Tools>+-- > <XF86Travel>+-- > <XF86UserPB>+-- > <XF86User1KB>+-- > <XF86User2KB>+-- > <XF86Video>+-- > <XF86WheelButton>+-- > <XF86Word>+-- > <XF86Xfer>+-- > <XF86ZoomIn>+-- > <XF86ZoomOut>+-- > <XF86Away>+-- > <XF86Messenger>+-- > <XF86WebCam>+-- > <XF86MailForward>+-- > <XF86Pictures>+-- > <XF86Music>+-- > <XF86_Switch_VT_1>-<XF86_Switch_VT_12>+-- > <XF86_Ungrab>+-- > <XF86_ClearGrab>+-- > <XF86_Next_VMode>+-- > <XF86_Prev_VMode>  mkKeymap :: XConfig l -> [(String, X ())] -> M.Map (KeyMask, KeySym) (X ()) mkKeymap c = M.fromList . mkSubmaps . readKeymap c +mkNamedKeymap :: XConfig l -> [(String, NamedAction)] -> [((KeyMask, KeySym), NamedAction)]+mkNamedKeymap c = mkNamedSubmaps . readKeymap c+ -- | Given a list of pairs of parsed key sequences and actions, --   group them into submaps in the appropriate way.++mkNamedSubmaps :: [([(KeyMask, KeySym)], NamedAction)] -> [((KeyMask, KeySym), NamedAction)]+mkNamedSubmaps = mkSubmaps' submapName+ mkSubmaps :: [ ([(KeyMask,KeySym)], X ()) ] -> [((KeyMask, KeySym), X ())]-mkSubmaps binds = map combine gathered+mkSubmaps = mkSubmaps' $ submap . M.fromList++mkSubmaps' ::  (Ord a) => ([(a, c)] -> c) -> [([a], c)] -> [(a, c)]+mkSubmaps' subm binds = map combine gathered   where gathered = groupBy fstKey                  . sortBy (comparing fst)                  $ binds         combine [([k],act)] = (k,act)         combine ks = (head . fst . head $ ks,-                      submap . M.fromList . mkSubmaps $ map (first tail) ks)+                      subm . mkSubmaps' subm $ map (first tail) ks)         fstKey = (==) `on` (head . fst)  on :: (a -> a -> b) -> (c -> a) -> c -> c -> b@@ -241,7 +381,7 @@ --   description, action) pairs, parse the key sequences into lists of --   @(KeyMask,KeySym)@ pairs.  Key sequences which fail to parse will --   be ignored.-readKeymap :: XConfig l -> [(String, X())] -> [([(KeyMask,KeySym)], X())]+readKeymap :: XConfig l -> [(String, t)] -> [([(KeyMask, KeySym)], t)] readKeymap c = mapMaybe (maybeKeys . first (readKeySequence c))   where maybeKeys (Nothing,_) = Nothing         maybeKeys (Just k, act) = Just (k, act)@@ -273,7 +413,8 @@                +++ do char 'M'                       n <- satisfy (`elem` ['1'..'5'])                       char '-'-                      return (mod1Mask + (read [n]) - 1)+                      return $ indexMod (read [n] - 1)+    where indexMod = (!!) [mod1Mask,mod2Mask,mod3Mask,mod4Mask,mod5Mask]  -- | Parse an unmodified basic key, like @\"x\"@, @\"<F1>\"@, etc. parseKey :: ReadP KeySym@@ -296,12 +437,12 @@  -- | A list of all special key names and their associated KeySyms. keyNames :: [(String, KeySym)]-keyNames = functionKeys ++ specialKeys+keyNames = functionKeys ++ specialKeys ++ multimediaKeys  -- | A list pairing function key descriptor strings (e.g. @\"<F2>\"@) with --   the associated KeySyms. functionKeys :: [(String, KeySym)]-functionKeys = [ ("F" ++ show n, k)+functionKeys = [ ('F' : show n, k)                | (n,k) <- zip ([1..24] :: [Int]) [xK_F1..] ]  -- | A list of special key names and their corresponding KeySyms.@@ -312,6 +453,7 @@               , ("Pause"      , xK_Pause)               , ("Scroll_lock", xK_Scroll_Lock)               , ("Sys_Req"    , xK_Sys_Req)+              , ("Print"      , xK_Print)               , ("Escape"     , xK_Escape)               , ("Esc"        , xK_Escape)               , ("Delete"     , xK_Delete)@@ -369,6 +511,160 @@               , ("KP_9"       , xK_KP_9)               ] +-- | List of multimedia keys. If X server does not know about some+-- | keysym it's omitted from list. (stringToKeysym returns noSymbol in this case)+multimediaKeys :: [(String, KeySym)]+multimediaKeys = filter ((/= noSymbol) . snd) . map (id &&& stringToKeysym) $+                 [ "XF86ModeLock"+                 , "XF86MonBrightnessUp"+                 , "XF86MonBrightnessDown"+                 , "XF86KbdLightOnOff"+                 , "XF86KbdBrightnessUp"+                 , "XF86KbdBrightnessDown"+                 , "XF86Standby"+                 , "XF86AudioLowerVolume"+                 , "XF86AudioMute"+                 , "XF86AudioRaiseVolume"+                 , "XF86AudioPlay"+                 , "XF86AudioStop"+                 , "XF86AudioPrev"+                 , "XF86AudioNext"+                 , "XF86HomePage"+                 , "XF86Mail"+                 , "XF86Start"+                 , "XF86Search"+                 , "XF86AudioRecord"+                 , "XF86Calculator"+                 , "XF86Memo"+                 , "XF86ToDoList"+                 , "XF86Calendar"+                 , "XF86PowerDown"+                 , "XF86ContrastAdjust"+                 , "XF86RockerUp"+                 , "XF86RockerDown"+                 , "XF86RockerEnter"+                 , "XF86Back"+                 , "XF86Forward"+                 , "XF86Stop"+                 , "XF86Refresh"+                 , "XF86PowerOff"+                 , "XF86WakeUp"+                 , "XF86Eject"+                 , "XF86ScreenSaver"+                 , "XF86WWW"+                 , "XF86Sleep"+                 , "XF86Favorites"+                 , "XF86AudioPause"+                 , "XF86AudioMedia"+                 , "XF86MyComputer"+                 , "XF86VendorHome"+                 , "XF86LightBulb"+                 , "XF86Shop"+                 , "XF86History"+                 , "XF86OpenURL"+                 , "XF86AddFavorite"+                 , "XF86HotLinks"+                 , "XF86BrightnessAdjust"+                 , "XF86Finance"+                 , "XF86Community"+                 , "XF86AudioRewind"+                 , "XF86BackForward"+                 , "XF86Launch0"+                 , "XF86Launch1"+                 , "XF86Launch2"+                 , "XF86Launch3"+                 , "XF86Launch4"+                 , "XF86Launch5"+                 , "XF86Launch6"+                 , "XF86Launch7"+                 , "XF86Launch8"+                 , "XF86Launch9"+                 , "XF86LaunchA"+                 , "XF86LaunchB"+                 , "XF86LaunchC"+                 , "XF86LaunchD"+                 , "XF86LaunchE"+                 , "XF86LaunchF"+                 , "XF86ApplicationLeft"+                 , "XF86ApplicationRight"+                 , "XF86Book"+                 , "XF86CD"+                 , "XF86Calculater"+                 , "XF86Clear"+                 , "XF86Close"+                 , "XF86Copy"+                 , "XF86Cut"+                 , "XF86Display"+                 , "XF86DOS"+                 , "XF86Documents"+                 , "XF86Excel"+                 , "XF86Explorer"+                 , "XF86Game"+                 , "XF86Go"+                 , "XF86iTouch"+                 , "XF86LogOff"+                 , "XF86Market"+                 , "XF86Meeting"+                 , "XF86MenuKB"+                 , "XF86MenuPB"+                 , "XF86MySites"+                 , "XF86New"+                 , "XF86News"+                 , "XF86OfficeHome"+                 , "XF86Open"+                 , "XF86Option"+                 , "XF86Paste"+                 , "XF86Phone"+                 , "XF86Q"+                 , "XF86Reply"+                 , "XF86Reload"+                 , "XF86RotateWindows"+                 , "XF86RotationPB"+                 , "XF86RotationKB"+                 , "XF86Save"+                 , "XF86ScrollUp"+                 , "XF86ScrollDown"+                 , "XF86ScrollClick"+                 , "XF86Send"+                 , "XF86Spell"+                 , "XF86SplitScreen"+                 , "XF86Support"+                 , "XF86TaskPane"+                 , "XF86Terminal"+                 , "XF86Tools"+                 , "XF86Travel"+                 , "XF86UserPB"+                 , "XF86User1KB"+                 , "XF86User2KB"+                 , "XF86Video"+                 , "XF86WheelButton"+                 , "XF86Word"+                 , "XF86Xfer"+                 , "XF86ZoomIn"+                 , "XF86ZoomOut"+                 , "XF86Away"+                 , "XF86Messenger"+                 , "XF86WebCam"+                 , "XF86MailForward"+                 , "XF86Pictures"+                 , "XF86Music"+                 , "XF86_Switch_VT_1"+                 , "XF86_Switch_VT_2"+                 , "XF86_Switch_VT_3"+                 , "XF86_Switch_VT_4"+                 , "XF86_Switch_VT_5"+                 , "XF86_Switch_VT_6"+                 , "XF86_Switch_VT_7"+                 , "XF86_Switch_VT_8"+                 , "XF86_Switch_VT_9"+                 , "XF86_Switch_VT_10"+                 , "XF86_Switch_VT_11"+                 , "XF86_Switch_VT_12"+                 , "XF86_Ungrab"+                 , "XF86_ClearGrab"+                 , "XF86_Next_VMode"+                 , "XF86_Prev_VMode" ]+ -- | Given a configuration record and a list of (key sequence --   description, action) pairs, check the key sequence descriptions --   for validity, and warn the user (via a popup xmessage window) of@@ -408,7 +704,7 @@                             ++ msg "duplicate" dup ++ "'"         msg _ [] = ""         msg m xs = m ++ " keybindings detected: " ++ showBindings xs-        showBindings = concat . intersperse " " . map ((++"\"") . ("\""++))+        showBindings = unwords . map (("\""++) . (++"\""))  -- | Given a config and a list of (key sequence description, action) --   pairs, check the key sequence descriptions for validity,
XMonad/Util/Font.hsc view
@@ -43,10 +43,9 @@ import Graphics.X11.Xrender #endif -#if defined XFT || defined UTF8 import Codec.Binary.UTF8.String (encodeString, decodeString)-#endif + -- Hide the Core Font/Xft switching here data XMonadFont = Core FontStruct                 | Utf8 FontSet@@ -92,7 +91,7 @@   d <- asks display   io $ freeFontSet d fs --- | When initXMF gets a font name that starts with 'xft:' it switchs to the Xft backend+-- | When initXMF gets a font name that starts with 'xft:' it switches to the Xft backend -- Example: 'xft: Sans-10' initXMF :: String -> X XMonadFont initXMF s =@@ -103,11 +102,7 @@         return (Xft xftdraw)   else #endif-#ifdef UTF8       fmap Utf8 $ initUtf8Font s-#else-      fmap Core $ initCoreFont s-#endif #ifdef XFT   where xftPrefix = "xft:" #endif@@ -195,18 +190,10 @@ #endif  decodeInput :: String -> String-#if defined XFT || defined UTF8 decodeInput = decodeString-#else-decodeInput = id-#endif  encodeOutput :: String -> String-#if defined XFT || defined UTF8 encodeOutput = encodeString-#else-encodeOutput = id-#endif  -- | Short-hand for 'fromIntegral' fi :: (Integral a, Num b) => a -> b
XMonad/Util/Invisible.hs view
@@ -5,8 +5,8 @@ -- Module      :  XMonad.Util.Invisible -- Copyright   :  (c) 2007 Andrea Rossato, David Roundy -- License     :  BSD-style (see xmonad/LICENSE)--- --- Maintainer  :  andrea.rossato@unibz.it, droundy@darcs.net+--+-- Maintainer  :  andrea.rossato@unibz.it -- Stability   :  unstable -- Portability :  unportable --@@ -14,7 +14,7 @@ -- ----------------------------------------------------------------------------- -module XMonad.Util.Invisible ( +module XMonad.Util.Invisible (                              -- * Usage:                              -- $usage                              Invisible (..)
XMonad/Util/Loggers.hs view
@@ -1,61 +1,123 @@ ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Util.Loggers--- Copyright   :  (c) Brent Yorgey+-- Copyright   :  (c) Brent Yorgey, Wirt Wolff -- License     :  BSD-style (see LICENSE) -- -- Maintainer  :  <byorgey@gmail.com> -- Stability   :  unstable -- Portability :  unportable ----- A collection of simple logger functions which can be used in the--- 'XMonad.Hooks.DynamicLog.ppExtras' field of a pretty-printing status--- logger format. See "XMonad.Hooks.DynamicLog" for more information.+-- A collection of simple logger functions and formatting utilities+-- which can be used in the 'XMonad.Hooks.DynamicLog.ppExtras' field of+-- a pretty-printing status logger format. See "XMonad.Hooks.DynamicLog"+-- for more information. -----------------------------------------------------------------------------  module XMonad.Util.Loggers (-                            -- * Usage-                            -- $usage+    -- * Usage+    -- $usage -                             Logger+      Logger -                           , date-                           , loadAvg-                           , battery-                           , logCmd+    -- * System Loggers+    -- $system+    , aumixVolume+    , battery+    , date+    , loadAvg+    , maildirNew, maildirUnread+    , logCmd , logFileCount -                           ) where+    -- * XMonad Loggers+    -- $xmonad+    , logCurrent, logLayout, logTitle +    -- * Formatting Utilities+    -- $format+    , onLogger+    , wrapL, fixedWidthL+    , logSp, padL+    , shortenL+    , dzenColorL, xmobarColorL++    , (<$>)++  ) where++import XMonad (liftIO) import XMonad.Core+import qualified XMonad.StackSet as W+import XMonad.Hooks.DynamicLog+import XMonad.Util.Font (Align (..))+import XMonad.Util.NamedWindows (getName) -import System.Time+import Control.Applicative ((<$>))+import Data.List (isPrefixOf, isSuffixOf)+import Data.Maybe (fromMaybe)+import Data.Traversable (traverse)+import System.Directory (getDirectoryContents) import System.IO-import System.Process import System.Locale+import System.Process (runInteractiveCommand)+import System.Time  -- $usage--- You can use this module by importing it into your @~\/.xmonad\/xmonad.hs@:+-- Use this module by importing it into your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Util.Loggers -- -- Then, add one or more loggers to the -- 'XMonad.Hooks.DynamicLog.ppExtras' field of your--- 'XMonad.Hooks.DynamicLoc.PP' format.  For example:+-- 'XMonad.Hooks.DynamicLoc.PP', possibly with extra formatting .+-- For example: ----- >     -- display load averages and a pithy quote along with xmonad status.--- >   , logHook = dynamicLogWithPP $ defaultPP { ppExtras = [ loadAvg, logCmd "fortune -n 40 -s" ] }+-- >   -- display load averages and a pithy quote along with xmonad status.+-- >   , logHook = dynamicLogWithPP $ defaultPP {+-- >                  ppExtras = [ padL loadAvg, logCmd "fortune -n 40 -s" ]+-- >                }+-- >   -- gives something like " 3.27 3.52 3.26 Drive defensively.  Buy a tank." --+-- See the formatting section below for another example using+-- a @where@ block to define some formatted loggers for a top-level+-- @myLogHook@.+--+-- Loggers are named either for their function, as in 'battery',+-- 'aumixVolume', and 'maildirNew', or are prefixed with \"log\" when+-- making use of other functions or by analogy with the pp* functions.+-- For example, the logger version of 'XMonad.Hooks.DynamicLog.ppTitle'+-- is 'logTitle', and 'logFileCount' loggerizes the result of file+-- counting code.+--+-- Formatting utility names are generally as short as possible and+-- carry the suffix \"L\". For example, the logger version of+-- 'XMonad.Hooks.DynamicLog.shorten' is 'shortenL'.+-- -- Of course, there is nothing really special about these so-called--- \'loggers\': they are just @X (Maybe String)@ actions.  So you can+-- \"loggers\": they are just @X (Maybe String)@ actions.  So you can -- use them anywhere you would use an @X (Maybe String)@, not just -- with DynamicLog. -- -- Additional loggers welcome!--- ++ -- | 'Logger' is just a convenient synonym for @X (Maybe String)@. type Logger = X (Maybe String) +-- $system++-- | Get the current volume with @aumix@. <http://jpj.net/~trevor/aumix.html>+aumixVolume :: Logger+aumixVolume = logCmd "aumix -vq"++-- | Get the battery status (percent charge and charging\/discharging+--   status). This is an ugly hack and may not work for some people.+--   At some point it would be nice to make this more general\/have+--   fewer dependencies (assumes @\/usr\/bin\/acpi@ and @sed@ are installed.)+battery :: Logger+battery = logCmd "/usr/bin/acpi | sed -r 's/.*?: (.*%).*/\\1/; s/discharging, ([0-9]+%)/\\1-/; s/charging, ([0-9]+%)/\\1+/; s/charged, //'"+ -- | Get the current date and time, and format them via the --   given format string.  The format used is the same as that used --   by the C library function strftime; for example,@@ -73,16 +135,164 @@ loadAvg :: Logger loadAvg = logCmd "/usr/bin/uptime | sed 's/.*: //; s/,//g'" --- | Get the battery status (percent charge and charging\/discharging---   status). This is an ugly hack and may not work for some people.---   At some point it would be nice to make this more general\/have---   fewer dependencies.-battery :: Logger-battery = logCmd "/usr/bin/acpi | sed -r 's/.*?: (.*%).*/\\1/; s/discharging, ([0-9]+%)/\\1-/; s/charging, ([0-9]+%)/\\1+/; s/charged, //'"- -- | Create a 'Logger' from an arbitrary shell command. logCmd :: String -> Logger-logCmd c = io $ do (_, out, _, proc) <- runInteractiveCommand c-                   output <- hGetLine out-                   waitForProcess proc-                   return $ Just output+logCmd c = io $ do (_, out, _, _) <- runInteractiveCommand c+                   fmap Just (hGetLine out) `catch` (const $ return Nothing)+                   -- no need to waitForProcess, we ignore SIGCHLD++-- | Get a count of filtered files in a directory.+-- See 'maildirUnread' and 'maildirNew' source for usage examples.+logFileCount :: FilePath          -- ^ directory in which to count files+             -> (String -> Bool)  -- ^ predicate to match if file should be counted+             -> Logger+logFileCount d p = do+    c <- liftIO ( getDirectoryContents d)+    let n = length $ Prelude.filter p c+    case n of+        0 -> return Nothing+        _ -> return $ Just $ show n++-- | Get a count of unread mails in a maildir. For maildir format+-- details, to write loggers for other classes of mail, see+-- <http://cr.yp.to/proto/maildir.html> and 'logFileCount'.+maildirUnread :: FilePath -> Logger+maildirUnread mdir = logFileCount (mdir ++ "/cur/") (isSuffixOf ",")++-- | Get a count of new mails in a maildir.+maildirNew :: FilePath -> Logger+maildirNew mdir = logFileCount (mdir ++ "/new/") (not . isPrefixOf ".")++-- $xmonad+--+-- A very small sample of what you can log since you have access to X. For+-- example you can loggerize the number of windows on each workspace, or+-- titles on other workspaces, or the id of the previously focused workspace....++-- | Get the title (name) of the focused window.+logTitle :: Logger+logTitle = withWindowSet $ traverse (fmap show . getName) . W.peek++-- | Get the name of the current layout.+logLayout :: Logger+logLayout = withWindowSet $ return . Just . ld+  where ld = description . W.layout . W.workspace . W.current++-- | Get the name of the current workspace.+logCurrent :: Logger+logCurrent = withWindowSet $ return . Just . W.currentTag++-- $format+-- Combine logger formatting functions to make your+-- 'XMonad.Hooks.DynamicLog.ppExtras' more colorful and readable.+-- (For convenience this module exports 'Control.Applicative.<$>' to+-- use instead of \'.\' or \'$\' in hard to read formatting lines.+-- For example:+--+-- > myLogHook = dynamicLogWithPP defaultPP {+-- >     -- skipped+-- >     , ppExtras = [lLoad, lTitle, logSp 3, wrapL "[" "]" $ date "%a %d %b"]+-- >     , ppOrder = \(ws,l,_,xs) -> [l,ws] ++ xs+-- >     }+-- >   where+-- >     -- lTitle = fixedWidthL AlignCenter "." 99 . dzenColorL "cornsilk3" "" . padL . shortenL 80 $ logTitle+-- >     -- or something like:+-- >     lTitle = fixedWidthL AlignCenter "." 99 <$> dzenColorL "cornsilk3" "" <$> padL . shortenL 80 $ logTitle+-- >+-- >     lLoad = dzenColorL "#6A5ACD" "" . wrapL loadIcon "   " . padL $ loadAvg+-- >     loadIcon = " ^i(/home/me/.dzen/icons/load.xbm)"+--+-- Note: When applying 'shortenL' or 'fixedWidthL' to logger strings+-- containing colors or other formatting commands, apply the formatting+-- /after/ the length adjustment, or include \"invisible\" characters+-- in the length specification, e.g. in the above \'^fg(cornsilk3)\' and+-- \'^fg()' yields 19 invisible and 80 visible characters.++-- | Use a string formatting function to edit a 'Logger' string.+-- For example, to create a tag function to prefix or label loggers,+-- as in \'tag: output\', use:+--+-- > tagL l = onLogger $ wrap (l ++ ": ") ""+-- >+-- >    tagL "bat" battery+-- >    tagL "load" loadAvg+--+-- If you already have a (String -> String) function you want to+-- apply to a logger:+--+-- > revL = onLogger trim+--+-- See formatting utility source code for more 'onLogger' usage examples.+onLogger :: (String -> String) -> Logger -> Logger+onLogger = fmap . fmap++-- | Wrap a logger's output in delimiters, unless it is @X (Nothing)@+-- or @X (Just \"\")@. Some examples:+--+-- >    wrapL " | " " | " (date "%a %d %b") -- ' | Tue 19 Feb | '+-- >+-- >    wrapL "bat: " "" battery            -- ' bat: battery_logger_output'+wrapL :: String -> String -> Logger -> Logger+wrapL l r = onLogger $ wrap l r++-- | Make a logger's output constant width by padding with the given string,+-- /even if the logger is/ @X (Nothing)@ /or/ @X (Just \"\")@. Useful to+-- reduce visual noise as a title logger shrinks and grows, to use a fixed+-- width for a logger that sometimes becomes Nothing, or even to create+-- fancy spacers or character based art effects.+--+-- It fills missing logger output with a repeated character like \".\",+-- \":\" or pattern, like \" -.-\". The cycling padding string is reversed on+-- the left of the logger output. This is mainly useful with AlignCenter.+fixedWidthL :: Align  -- ^ AlignCenter, AlignRight, or AlignLeft+            -> String -- ^ String to cycle to pad missing logger output+            -> Int    -- ^ Fixed length to output (including invisible formatting characters)+            -> Logger -> Logger+fixedWidthL a str n logger = do+    mbl <- logger+    let l = fromMaybe "" mbl+    case a of+       AlignCenter -> toL (take n $ padhalf l ++ l ++ cs)+       AlignRight -> toL (reverse (take n $ reverse l ++ cs))+       AlignLeft -> toL (take n $ l ++ cs)+  where+    toL = return . Just+    cs  = cycle str+    padhalf x = reverse $ take ((n - length x) `div` 2) cs++-- | Create a \"spacer\" logger, e.g. @logSp 3 -- loggerizes \'   \'@.+-- For more complex \"spacers\", use 'fixedWidthL' with @return Nothing@.+logSp :: Int -> Logger+logSp n = return . Just . take n $ cycle " "++-- | Pad a logger's output with a leading and trailing space, unless it+-- is @X (Nothing)@ or @X (Just \"\")@.+padL :: Logger -> Logger+padL = onLogger pad++-- | Limit a logger's length, adding \"...\" if truncated.+shortenL :: Int -> Logger -> Logger+shortenL = onLogger . shorten++-- | Color a logger's output with dzen foreground and background colors.+--+-- >  dzenColorL "green" "#2A4C3F" battery+dzenColorL :: String -> String -> Logger -> Logger+dzenColorL fg bg = onLogger $ dzenColor fg bg++-- | Color a logger's output with xmobar foreground and background colors.+--+-- >  xmobarColorL "#6A5ACD" "gray6" loadAverage+xmobarColorL :: String -> String -> Logger -> Logger+xmobarColorL fg bg = onLogger $ xmobarColor fg bg++-- todo+-- * dynamicLogXinerama logger? Or sorted onscreen Id's with "current" indicator?+-- is logCurrent really useful at all?+--+-- * ppVisible, etc. Resolve code dup. somehow. Refactor DynamicLog so can+-- be used for regular PP stuff /and/ loggers?+--+-- * fns for "ppExtras as a whole", combine loggers more nicely.+--+-- * parsers  to use with fixedWidthL to be smarter about invisible characters?
+ XMonad/Util/NamedActions.hs view
@@ -0,0 +1,315 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE ExistentialQuantification, FlexibleContexts, FlexibleInstances, StandaloneDeriving #-}+--------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.NamedActions+-- Copyright   :  2009 Adam Vogt <vogt.adam@gmail.com>+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Adam Vogt <vogt.adam@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A wrapper for keybinding configuration that can list the available+-- keybindings.+--------------------------------------------------------------------++module XMonad.Util.NamedActions (+    -- * Usage:+    -- $usage+    sendMessage',+    spawn',+    submapName,+    addDescrKeys,+    xMessage,++    showKmSimple,+    showKm,++    noName,+    oneName,+    addName,++    separator,+    subtitle,++    (^++^),++    NamedAction(..),+    HasName,+    defaultKeysDescr+    ) where+++import XMonad.Actions.Submap(submap)+import XMonad(KeySym, KeyMask, X, Layout, Message,+              XConfig(keys, layoutHook, modMask, terminal, workspaces, XConfig),+              io, spawn, whenJust, ChangeLayout(NextLayout), IncMasterN(..),+              Resize(..), kill, refresh, screenWorkspace, sendMessage, setLayout,+              windows, withFocused, controlMask, mod1Mask, mod2Mask, mod3Mask,+              mod4Mask, mod5Mask, shiftMask, xK_1, xK_9, xK_Return, xK_Tab, xK_c,+              xK_comma, xK_e, xK_h, xK_j, xK_k, xK_l, xK_m, xK_n, xK_p,+              xK_period, xK_q, xK_r, xK_space, xK_t, xK_w, keysymToString)+import System.Posix.Process(executeFile, forkProcess)+import Control.Arrow(Arrow((&&&), second, (***)))+import Data.Bits(Bits((.&.), complement, (.|.)))+import Data.Function((.), const, ($), flip, id)+import Data.List((++), filter, zip, map, concatMap, null, unlines,+                 groupBy)+import System.Exit(ExitCode(ExitSuccess), exitWith)++import Control.Applicative ((<*>))++import qualified Data.Map as M+import qualified XMonad.StackSet as W+import qualified XMonad++-- $usage+-- Here is an example config that demonstrates the usage of 'sendMessage'',+-- 'mkNamedKeymap', 'addDescrKeys', and '^++^'+--+-- > import XMonad+-- > import XMonad.Util.NamedActions+-- > import XMonad.Util.EZConfig+-- >+-- > main = xmonad $ addDescrKeys ((mod4Mask, xK_F1), xMessage) myKeys+-- >                    defaultConfig { modMask = mod4Mask }+-- >+-- > myKeys c = (subtitle "Custom Keys":) $ mkNamedKeymap c $+-- >    [("M-x a", addName "useless message" $ spawn "xmessage foo"),+-- >     ("M-c", sendMessage' Expand)]+-- >     ^++^+-- >    [("<XF86AudioPlay>", spawn "mpc toggle" :: X ()),+-- >     ("<XF86AudioNext>", spawn "mpc next")]+--+-- Using '^++^', you can combine bindings whose actions are @X ()@+-- as well as actions that have descriptions. However you cannot mix the two in+-- a single list, unless each is prefixed with 'addName' or 'noName'.+--+-- If you don't like EZConfig, you can still use '^++^' with the basic XMonad+-- keybinding configuration too.+--+-- Also note the unfortunate necessity of a type annotation, since 'spawn' is+-- too general.++-- TODO: squeeze titles that have no entries (consider titles containing \n)+--+-- Output to Multiple columns+--+-- Devin Mullin's suggestions:+--+-- Reduce redundancy wrt mkNamedSubmaps, mkSubmaps and mkNamedKeymap to have a+-- HasName context (and leave mkKeymap as a specific case of it?)+--    Currently kept separate to aid error messages, common lines factored out+--+-- Suggestions for UI:+--+-- - An IO () -> IO () that wraps the main xmonad action and wrests control+--   from it if the user asks for --keys.+--+-- Just a separate binary: keep this as the only way to show keys for simplicity+--+-- - An X () that toggles a cute little overlay like the ? window for gmail+--   and reader.+--+-- Add dzen binding++deriving instance Show XMonad.Resize+deriving instance Show XMonad.IncMasterN++-- | 'sendMessage' but add a description that is @show message@. Note that not+-- all messages have show instances.+sendMessage' :: (Message a, Show a) => a -> NamedAction+sendMessage' x = NamedAction $ (XMonad.sendMessage x,show x)++-- | 'spawn' but the description is the string passed+spawn' :: String -> NamedAction+spawn' x = addName x $ spawn x++class HasName a where+    showName :: a -> [String]+    showName = const [""]+    getAction :: a -> X ()++instance HasName (X ()) where+    getAction = id++instance HasName (IO ()) where+    getAction = io++instance HasName [Char] where+    getAction _ = return ()+    showName = (:[])++instance HasName (X (),String) where+    showName = (:[]) . snd+    getAction = fst++instance HasName (X (),[String]) where+    showName = snd+    getAction = fst++-- show only the outermost description+instance HasName (NamedAction,String) where+    showName = (:[]) . snd+    getAction = getAction . fst++instance HasName NamedAction where+    showName (NamedAction x) = showName x+    getAction (NamedAction x) = getAction x++-- | An existential wrapper so that different types can be combined in lists,+-- and maps+data NamedAction = forall a. HasName a => NamedAction a++-- | 'submap', but propagate the descriptions of the actions. Does this belong+-- in "XMonad.Actions.Submap"?+submapName :: (HasName a) => [((KeyMask, KeySym), a)] -> NamedAction+submapName = NamedAction . (submap . M.map getAction . M.fromList &&& showKm)+                . map (second NamedAction)++-- | Combine keymap lists with actions that may or may not have names+(^++^) :: (HasName b, HasName b1) =>+     [(d, b)] -> [(d, b1)] -> [(d, NamedAction)]+a ^++^ b = map (second NamedAction) a ++ map (second NamedAction) b++-- | Or allow another lookup table?+modToString :: KeyMask -> String+modToString mask = concatMap (++"-") $ filter (not . null)+                $ map (uncurry pick)+                [(mod1Mask, "M1")+                ,(mod2Mask, "M2")+                ,(mod3Mask, "M3")+                ,(mod4Mask, "M4")+                ,(mod5Mask, "M5")+                ,(controlMask, "C")+                ,(shiftMask,"Shift")]+    where pick m str = if m .&. complement mask == 0 then str else ""++keyToString :: (KeyMask, KeySym) -> [Char]+keyToString = uncurry (++) . (modToString *** keysymToString)++showKmSimple :: [((KeyMask, KeySym), NamedAction)] -> [[Char]]+showKmSimple = concatMap (\(k,e) -> if snd k == 0 then "":showName e else map ((keyToString k ++) . smartSpace) $ showName e)++smartSpace :: String -> String+smartSpace [] = []+smartSpace xs = ' ':xs++_test :: String+_test = unlines $ showKm $ defaultKeysDescr XMonad.defaultConfig { XMonad.layoutHook = XMonad.Layout $ XMonad.layoutHook XMonad.defaultConfig }++showKm :: [((KeyMask, KeySym), NamedAction)] -> [String]+showKm keybindings = padding $ do+    (k,e) <- keybindings+    if snd k == 0 then map ((,) "") $ showName e+        else map ((,) (keyToString k) . smartSpace) $ showName e+    where padding = let pad n (k,e) = if null k then "\n>> "++e else take n (k++repeat ' ') ++ e+                        expand xs n = map (pad n) xs+                        getMax = map (maximum . map (length . fst))+            in concat . (zipWith expand <*> getMax) . groupBy (const $ not . null . fst)++-- | An action to send to 'addDescrKeys' for showing the keybindings. See also 'showKm' and 'showKmSimple'+xMessage :: [((KeyMask, KeySym), NamedAction)] -> NamedAction+xMessage x = addName "Show Keybindings" $ io $ do+    forkProcess $ executeFile "xmessage" True ["-default", "okay", unlines $ showKm x] Nothing+    return ()++-- | Merge the supplied keys with 'defaultKeysDescr', also adding a keybinding+-- to run an action for showing the keybindings.+addDescrKeys :: (HasName b1, HasName b) =>+    ((KeyMask, KeySym),[((KeyMask, KeySym), NamedAction)] -> b)+    -> (XConfig Layout -> [((KeyMask, KeySym), b1)])+    -> XConfig l+    -> XConfig l+addDescrKeys k ks = addDescrKeys' k (\l -> defaultKeysDescr l ^++^ ks l)++-- | Without merging with 'defaultKeysDescr'+addDescrKeys' :: (HasName b) =>+    ((KeyMask, KeySym),[((KeyMask, KeySym), NamedAction)] -> b)+    -> (XConfig Layout -> [((KeyMask, KeySym), NamedAction)]) -> XConfig l -> XConfig l+addDescrKeys' (k,f) ks conf =+    let shk l = f $ [(k,f $ ks l)] ^++^ ks l+        keylist l = M.map getAction $ M.fromList $ ks l ^++^ [(k, shk l)]+    in conf { keys = keylist }++-- | A version of the default keys from 'XMonad.Config.defaultConfig', but with+-- 'NamedAction'  instead of @X ()@+defaultKeysDescr :: XConfig Layout -> [((KeyMask, KeySym), NamedAction)]+defaultKeysDescr conf@(XConfig {XMonad.modMask = modm}) =+    [ subtitle "launching and killing programs"+    , ((modm .|. shiftMask, xK_Return), addName "Launch Terminal" $ spawn $ XMonad.terminal conf) -- %! Launch terminal+    , ((modm,               xK_p     ), addName "Launch dmenu" $ spawn "exe=`dmenu_path | dmenu` && eval \"exec $exe\"") -- %! Launch dmenu+    , ((modm .|. shiftMask, xK_p     ), addName "Launch gmrun" $ spawn "gmrun") -- %! Launch gmrun+    , ((modm .|. shiftMask, xK_c     ), addName "Close the focused window" kill) -- %! Close the focused window++    , subtitle "changing layouts"+    , ((modm,               xK_space ), sendMessage' NextLayout) -- %! Rotate through the available layout algorithms+    , ((modm .|. shiftMask, xK_space ), addName "Reset the layout" $ setLayout $ XMonad.layoutHook conf) -- %!  Reset the layouts on the current workspace to default++    , separator+    , ((modm,               xK_n     ), addName "Refresh" refresh) -- %! Resize viewed windows to the correct size++    , subtitle "move focus up or down the window stack"+    , ((modm,               xK_Tab   ), addName "Focus down" $ windows W.focusDown) -- %! Move focus to the next window+    , ((modm .|. shiftMask, xK_Tab   ), addName "Focus up"   $ windows W.focusUp  ) -- %! Move focus to the previous window+    , ((modm,               xK_j     ), addName "Focus down" $ windows W.focusDown) -- %! Move focus to the next window+    , ((modm,               xK_k     ), addName "Focus up"   $ windows W.focusUp  ) -- %! Move focus to the previous window+    , ((modm,               xK_m     ), addName "Focus the master" $ windows W.focusMaster  ) -- %! Move focus to the master window++    , subtitle "modifying the window order"+    , ((modm,               xK_Return), addName "Swap with the master" $ windows W.swapMaster) -- %! Swap the focused window and the master window+    , ((modm .|. shiftMask, xK_j     ), addName "Swap down" $ windows W.swapDown  ) -- %! Swap the focused window with the next window+    , ((modm .|. shiftMask, xK_k     ), addName "Swap up"   $ windows W.swapUp    ) -- %! Swap the focused window with the previous window++    , subtitle "resizing the master/slave ratio"+    , ((modm,               xK_h     ), sendMessage' Shrink) -- %! Shrink the master area+    , ((modm,               xK_l     ), sendMessage' Expand) -- %! Expand the master area++    , subtitle "floating layer support"+    , ((modm,               xK_t     ), addName "Push floating to tiled" $ withFocused $ windows . W.sink) -- %! Push window back into tiling++    , subtitle "change the number of windows in the master area"+    , ((modm              , xK_comma ), sendMessage' (IncMasterN 1)) -- %! Increment the number of windows in the master area+    , ((modm              , xK_period), sendMessage' (IncMasterN (-1))) -- %! Deincrement the number of windows in the master area++    , subtitle "quit, or restart"+    , ((modm .|. shiftMask, xK_q     ), addName "Quit" $ io (exitWith ExitSuccess)) -- %! Quit xmonad+    , ((modm              , xK_q     ), addName "Restart" $ spawn "xmonad --recompile && xmonad --restart") -- %! Restart xmonad+    ]++    -- mod-[1..9] %! Switch to workspace N+    -- mod-shift-[1..9] %! Move client to workspace N+    +++    subtitle "switching workspaces":+    [((m .|. modm, k), addName (n ++ i) $ windows $ f i)+        | (f, m, n) <- [(W.greedyView, 0, "Switch to workspace "), (W.shift, shiftMask, "Move client to workspace ")]+        , (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]]+    -- mod-{w,e,r} %! Switch to physical/Xinerama screens 1, 2, or 3+    -- mod-shift-{w,e,r} %! Move client to screen 1, 2, or 3+   +++   subtitle "switching screens" :+   [((m .|. modm, key), addName (n ++ show sc) $ screenWorkspace sc >>= flip whenJust (windows . f))+        | (f, m, n) <- [(W.view, 0, "Switch to screen number "), (W.shift, shiftMask, "Move client to screen number ")]+        , (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]]++-- | For a prettier presentation: keymask, keysym of 0 are reserved for this+-- purpose: they do not happen, afaik, and keysymToString 0 would raise an+-- error otherwise+separator :: ((KeyMask,KeySym), NamedAction)+separator = ((0,0), NamedAction (return () :: X (),[] :: [String]))++subtitle ::  String -> ((KeyMask, KeySym), NamedAction)+subtitle x = ((0,0), NamedAction $ x ++ ":")++-- | These are just the @NamedAction@ constructor but with a more specialized+-- type, so that you don't have to supply any annotations, for ex coercing+-- spawn to @X ()@ from the more general @MonadIO m => m ()@+noName :: X () -> NamedAction+noName = NamedAction++oneName :: (X (), String) -> NamedAction+oneName = NamedAction++addName :: String -> X () -> NamedAction+addName = flip (curry NamedAction)
+ XMonad/Util/NamedScratchpad.hs view
@@ -0,0 +1,158 @@+{-# LANGUAGE PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.NamedScratchpad+-- Copyright   :  (c) Konstantin Sobolev <konstantin.sobolev@gmail.com>+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Konstantin Sobolev <konstantin.sobolev@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Named scratchpads that support several arbitrary applications at the same time.+--+-----------------------------------------------------------------------------++module XMonad.Util.NamedScratchpad (+  -- * Usage+  -- $usage+  NamedScratchpad(..),+  nonFloating,+  defaultFloating,+  customFloating,+  NamedScratchpads,+  namedScratchpadAction,+  namedScratchpadManageHook,+  namedScratchpadFilterOutWorkspace+  ) where++import XMonad+import XMonad.Core+import XMonad.ManageHook (composeAll,doFloat)+import XMonad.Hooks.ManageHelpers (doRectFloat)+import XMonad.Actions.DynamicWorkspaces (addHiddenWorkspace)++import Control.Monad (filterM)+import Data.Maybe (maybe,listToMaybe)++import qualified XMonad.StackSet as W+++-- $usage+-- Allows to have several floating scratchpads running different applications.+-- Bind a key to 'namedScratchpadSpawnAction'.+-- Pressing it will spawn configured application, or bring it to the current+-- workspace if it already exists.+-- Pressing the key with the application on the current workspace will+-- send it to a hidden workspace called @NSP@.+--+-- If you already have a workspace called @NSP@, it will use that.+-- @NSP@ will also appear in xmobar and dzen status bars. You can tweak your+-- @dynamicLog@ settings to filter it out if you like.+--+-- Create named scratchpads configuration in your xmonad.hs like this:+--+-- > import XMonad.StackSet as W+-- > import XMonad.ManageHook+-- > import XMonad.Util.NamedScratchpad+-- >+-- > scratchpads = [+-- > -- run htop in xterm, find it by title, use default floating window placement+-- >     NS "htop" "xterm -e htop" (title =? "htop") defaultFloating ,+-- >+-- > -- run stardict, find it by class name, place it in the floating window+-- > -- 1/6 of screen width from the left, 1/6 of screen height+-- > -- from the top, 2/3 of screen width by 2/3 of screen height+-- >     NS "stardict" "stardict" (className =? "Stardict")+-- >         (customFloating $ W.RationalRect (1/6) (1/6) (2/3) (2/3)) ,+-- >+-- > -- run gvim, find by role, don't float+-- >     NS "notes" "gvim --role notes ~/notes.txt" (role =? "notes") nonFloating+-- > ] where role = stringProperty "WM_WINDOW_ROLE"+--+-- Add keybindings:+--+-- >  , ((modm .|. controlMask .|. shiftMask, xK_t), namedScratchpadAction scratchpads "htop")+-- >  , ((modm .|. controlMask .|. shiftMask, xK_s), namedScratchpadAction scratchpads "stardict")+-- >  , ((modm .|. controlMask .|. shiftMask, xK_n), namedScratchpadAction scratchpads "notes")+--+-- ... and a manage hook:+--+-- >  , manageHook = namedScratchpadManageHook scratchpads+--+-- For detailed instruction on editing the key binding see+-- "XMonad.Doc.Extending#Editing_key_bindings"+--++-- | Single named scratchpad configuration+data NamedScratchpad = NS { name   :: String      -- ^ Scratchpad name+                          , cmd    :: String      -- ^ Command used to run application+                          , query  :: Query Bool  -- ^ Query to find already running application+                          , hook   :: ManageHook  -- ^ Manage hook called for application window, use it to define the placement. See @nonFloating@, @defaultFloating@ and @customFloating@+                          }++-- | Manage hook that makes the window non-floating+nonFloating :: ManageHook+nonFloating = idHook++-- | Manage hook that makes the window floating with the default placement+defaultFloating :: ManageHook+defaultFloating = doFloat++-- | Manage hook that makes the window floating with custom placement+customFloating :: W.RationalRect -> ManageHook+customFloating = doRectFloat++-- | Named scratchpads configuration+type NamedScratchpads = [NamedScratchpad]++-- | Finds named scratchpad configuration by name+findByName :: NamedScratchpads -> String -> Maybe NamedScratchpad+findByName c s = listToMaybe $ filter ((s==) . name) c++-- | Runs application which should appear in specified scratchpad+runApplication :: NamedScratchpad -> X ()+runApplication = spawn . cmd++-- | Action to pop up specified named scratchpad+namedScratchpadAction :: NamedScratchpads -- ^ Named scratchpads configuration+                      -> String           -- ^ Scratchpad name+                      -> X ()+namedScratchpadAction confs n+    | Just conf <- findByName confs n = withWindowSet $ \s -> do+        -- try to find it on the current workspace+        filterCurrent <- filterM (runQuery (query conf))+                            ( (maybe [] W.integrate . W.stack .+                                    W.workspace . W.current) s)+        case filterCurrent of+            (x:_) -> do+                -- create hidden workspace if it doesn't exist+                if null (filter ((== scratchpadWorkspaceTag) . W.tag) (W.workspaces s))+                    then addHiddenWorkspace scratchpadWorkspaceTag+                    else return ()+                -- push window there+                windows $ W.shiftWin scratchpadWorkspaceTag x+            [] -> do+                -- try to find it on all workspaces+                filterAll <- filterM (runQuery (query conf)) (W.allWindows s)+                case filterAll of+                    (x:_) -> windows $ W.shiftWin (W.currentTag s) x+                    []    -> runApplication conf++    | otherwise = return ()++-- tag of the scratchpad workspace+scratchpadWorkspaceTag :: String+scratchpadWorkspaceTag = "NSP"++-- | Manage hook to use with named scratchpads+namedScratchpadManageHook :: NamedScratchpads -- ^ Named scratchpads configuration+                          -> ManageHook+namedScratchpadManageHook = composeAll . fmap (\c -> query c --> hook c)++-- | Transforms a workspace list containing the NSP workspace into one that+-- doesn't contain it. Intended for use with logHooks.+namedScratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace]+namedScratchpadFilterOutWorkspace = filter (\(W.Workspace tag _ _) -> tag /= scratchpadWorkspaceTag)++-- vim:ts=4:shiftwidth=4:softtabstop=4:expandtab:foldlevel=20:
+ XMonad/Util/Paste.hs view
@@ -0,0 +1,94 @@+{- |+Module      :  XMonad.Util.Paste+Copyright   :  (C) 2008 Jérémy Bobbio, gwern+License     :  BSD3++Maintainer  :  gwern <gwern0@gmail.com>+Stability   :  unstable+Portability :  unportable++A module for sending key presses to windows. This modules provides generalized+and specialized functions for this task.+-}++module XMonad.Util.Paste ( -- * Usage+                           -- $usage+                           pasteSelection,+                           pasteString,+                           pasteChar,+                           sendKey,+                           sendKeyWindow,+                           noModMask+                         )+                           where++import XMonad (io, theRoot, withDisplay, X ())+import Graphics.X11+import Graphics.X11.Xlib.Extras (none, setEventType, setKeyEvent)+import Control.Monad.Reader (asks)+import XMonad.Operations (withFocused)+import Data.Char (isUpper)+import Graphics.X11.Xlib.Misc (stringToKeysym)+import XMonad.Util.XSelection (getSelection)++{- $usage++Import this module into your xmonad.hs as usual:++> import XMonad.Util.Paste++And use the functions. They all return 'X' (), and so are appropriate+for use as keybindings. Example:++>          , ((m,              xK_d), pasteString "foo bar") ]++Don't expect too much of the functions; they probably don't work on complex+texts.+-}++-- | Paste the current X mouse selection. Note that this uses 'getSelection' from+--   "XMonad.Util.XSelection" and so is heir to its flaws.+pasteSelection :: X ()+pasteSelection = getSelection >>= pasteString++-- | Send a string to the window which is currently focused. This function correctly+-- handles capitalization.+pasteString :: String -> X ()+pasteString = mapM_ (\x -> if isUpper x then pasteChar shiftMask x else pasteChar noModMask x)++{- | Send a character to the current window. This is more low-level.+   Remember that you must handle the case of capitalization appropriately.+   That is, from the window's perspective:++   > pasteChar mod2Mask 'F' ~> "f"++   You would want to do something like:++   > pasteChar shiftMask 'F'++   Note that this function makes use of 'stringToKeysym', and so will probably+   have trouble with any 'Char' outside ASCII.+-}+pasteChar :: KeyMask -> Char -> X ()+pasteChar m c = sendKey m $ stringToKeysym [c]++sendKey :: KeyMask -> KeySym -> X ()+sendKey = (withFocused .) . sendKeyWindow++-- | The primitive. Allows you to send any combination of 'KeyMask' and 'KeySym' to any 'Window' you specify.+sendKeyWindow :: KeyMask -> KeySym -> Window -> X ()+sendKeyWindow mods key w = withDisplay $ \d -> do+              rootw <- asks theRoot+              keycode <- io $ keysymToKeycode d key+              io $ allocaXEvent $ \ev -> do+                  setEventType ev keyPress+                  setKeyEvent ev w rootw none mods keycode True+                  sendEvent d w True keyPressMask ev+                  setEventType ev keyRelease+                  sendEvent d w True keyReleaseMask ev++-- | A null 'KeyMask'. Used when you don't want a character or string shifted, control'd, or what.+--+--   TODO: This really should be a function in the X11 binding. When noModMask shows up there, remove.+noModMask :: KeyMask+noModMask = 0
+ XMonad/Util/Replace.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.Replace+-- Copyright   :  (c) Jan Vornberger 2009+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Adam Vogt <vogt.adam@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Implements a @--replace@ behavior outside of core.+--+-----------------------------------------------------------------------------++-- refer to core patches:+-- http://article.gmane.org/gmane.comp.lang.haskell.xmonad/8358+module XMonad.Util.Replace+    ( -- * Usage+      -- $usage+      replace+ +      -- * Notes+      -- $shortcomings++      -- ** Implementing a @--replace@ flag+      -- $getArgs+    ) where++import XMonad+import Data.Function+import Control.Monad++-- $usage+-- You must run the 'replace' action before starting xmonad proper, this+-- results in xmonad replacing the currently running WM regardless of the+-- arguments it is run with:+--+-- > import XMonad+-- > import XMonad.Util.Replace+-- > main = do+-- >    replace+-- >    xmonad $ defaultConfig { .... }+--++-- $shortcomings+-- This doesn't seem to work for replacing WMs that have been started+-- from within xmonad, such as with @'restart' "openbox" False@, but no other+-- WMs that implements --replace manage this either. 'replace' works for+-- replacing metacity when the full gnome-session is started at least.++-- $getArgs+-- You can use 'System.Environment.getArgs' to watch for an explicit+-- @--replace@ flag:+-- +-- > import XMonad+-- > import XMonad.Util.Replace (replace)+-- > import Control.Monad (when)+-- > import System.Environment (getArgs)+-- >+-- > main = do+-- >    args <- getArgs+-- >    when ("--replace" `elem` args) replace+-- >    xmonad $ defaultConfig { .... }+--+--+-- Note that your @~\/.xmonad/xmonad-$arch-$os@ binary is not run with the same+-- flags as the @xmonad@ binary that calls it. You may be able to work around+-- this by running your @~\/.xmonad/xmonad-$arch-$os@ binary directly, which is+-- otherwise not recommended.++-- | @replace@ must be run before xmonad starts to signals to compliant window+-- managers that they must exit and let xmonad take over.+replace :: IO ()+replace = do+    dpy   <- openDisplay ""+    let dflt = defaultScreen dpy++    rootw  <- rootWindow dpy dflt++    -- check for other WM+    wmSnAtom <- internAtom dpy ("WM_S" ++ (show dflt)) False+    currentWmSnOwner <- xGetSelectionOwner dpy wmSnAtom+    when (currentWmSnOwner /= 0) $ do+        putStrLn $ "Screen " ++ (show dflt) ++ " on display \""+                    ++ (displayString dpy) ++ "\" already has a window manager."++        -- prepare to receive destroyNotify for old WM+        selectInput dpy currentWmSnOwner structureNotifyMask++        -- create off-screen window+        netWmSnOwner <- allocaSetWindowAttributes $ \attributes -> do+            set_override_redirect attributes True+            set_event_mask attributes propertyChangeMask+            let screen = defaultScreenOfDisplay dpy+            let visual = defaultVisualOfScreen screen+            let attrmask = cWOverrideRedirect .|. cWEventMask+            createWindow dpy rootw (-100) (-100) 1 1 0 copyFromParent copyFromParent visual attrmask attributes++        -- try to acquire wmSnAtom, this should signal the old WM to terminate+        putStrLn $ "Replacing existing window manager..."+        xSetSelectionOwner dpy wmSnAtom netWmSnOwner currentTime++        -- SKIPPED: check if we acquired the selection+        -- SKIPPED: send client message indicating that we are now the WM++        -- wait for old WM to go away+        putStr $ "Waiting for other window manager to terminate... "+        fix $ \again -> do+            evt <- allocaXEvent $ \event -> do+                windowEvent dpy currentWmSnOwner structureNotifyMask event+                get_EventType event++            when (evt /= destroyNotify) again+        putStrLn $ "done"+    closeDisplay dpy
XMonad/Util/Run.hs view
@@ -21,6 +21,7 @@                           runProcessWithInput,                           runProcessWithInputAndWait,                           safeSpawn,+                          safeSpawnProg,                           unsafeSpawn,                           runInTerm,                           safeRunInTerm,@@ -31,11 +32,11 @@                          ) where  import System.Posix.IO-import System.Posix.Process (executeFile)+import System.Posix.Process (executeFile, forkProcess, createSession) import Control.Concurrent (threadDelay)-import Control.Exception (try)+import Control.Exception (try) -- use OldException with base 4 import System.IO-import System.Process (runInteractiveProcess, waitForProcess)+import System.Process (runInteractiveProcess) import XMonad import Control.Monad @@ -51,32 +52,33 @@ -- "XMonad.Util.Dzen"  -- | Return output if the command succeeded, otherwise return @()@.--- This corresponds to dmenu's notion of exit code 1 for a cancelled invocation.+-- This corresponds to dmenu's notion of exit code 1 for a canceled invocation. runProcessWithInput :: FilePath -> [String] -> String -> IO String runProcessWithInput cmd args input = do-    (pin, pout, perr, ph) <- runInteractiveProcess cmd args Nothing Nothing+    (pin, pout, perr, _) <- runInteractiveProcess cmd args Nothing Nothing     hPutStr pin input     hClose pin     output <- hGetContents pout     when (output == output) $ return ()     hClose pout     hClose perr-    waitForProcess ph+    -- no need to waitForProcess, we ignore SIGCHLD     return output  -- | Wait is in µs (microseconds) runProcessWithInputAndWait :: FilePath -> [String] -> String -> Int -> IO () runProcessWithInputAndWait cmd args input timeout = do-    doubleFork $ do-        (pin, pout, perr, ph) <- runInteractiveProcess cmd args Nothing Nothing+    forkProcess $ do+        (pin, pout, perr, _) <- runInteractiveProcess cmd args Nothing Nothing         hPutStr pin input         hFlush pin         threadDelay timeout         hClose pin         hClose pout         hClose perr-        waitForProcess ph+        -- no need to waitForProcess, we ignore SIGCHLD         return ()+    return ()  -- | Multiplies by ONE MILLION, for functions that take microseconds. --@@ -98,16 +100,22 @@ of it can be, well, unsafe. Examples: -> , ((modMask, xK_Print), unsafeSpawn "import -window root $HOME/xwd-$(date +%s)$$.png")-> , ((modMask, xK_d    ), safeSpawn "firefox" "")+> , ((modm, xK_Print), unsafeSpawn "import -window root $HOME/xwd-$(date +%s)$$.png")+> , ((modm, xK_d    ), safeSpawn "firefox" "")  Note that the unsafeSpawn example must be unsafe and not safe because it makes use of shell interpretation by relying on @$HOME@ and interpolation, whereas the safeSpawn example can be safe because Firefox doesn't need any arguments if it is just being started. -}-safeSpawn :: MonadIO m => FilePath -> String -> m ()-safeSpawn prog arg = liftIO (try (doubleFork $ executeFile prog True [arg] Nothing) >> return ())+safeSpawn :: MonadIO m => FilePath -> [String] -> m ()+safeSpawn prog args = liftIO (try (forkProcess $ executeFile prog True args Nothing) >> return ()) +-- | Like 'safeSpawn', but only takes a program (and no arguments for it). eg.+--+-- > safeSpawnProg "firefox"+safeSpawnProg :: MonadIO m => FilePath -> m ()+safeSpawnProg = flip safeSpawn []+ unsafeSpawn :: MonadIO m => String -> m () unsafeSpawn = spawn @@ -119,7 +127,7 @@  -- | Run a given program in the preferred terminal emulator; see 'runInTerm'. This makes use of 'safeSpawn'. safeRunInTerm :: String -> String -> X ()-safeRunInTerm options command = asks (terminal . config) >>= \t -> safeSpawn t (options ++ " -e " ++ command)+safeRunInTerm options command = asks (terminal . config) >>= \t -> safeSpawn t [options, " -e " ++ command]  -- | Launch an external application through the system shell and return a @Handle@ to its standard input. spawnPipe :: String -> IO Handle@@ -128,7 +136,9 @@     setFdOption wr CloseOnExec True     h <- fdToHandle wr     hSetBuffering h LineBuffering-    doubleFork $ do+    forkProcess $ do+        createSession+        uninstallSignalHandlers         dupTo rd stdInput         executeFile "/bin/sh" False ["-c", x] Nothing     return h
XMonad/Util/Scratchpad.hs view
@@ -17,6 +17,7 @@   -- $usage   scratchpadSpawnAction   ,scratchpadSpawnActionTerminal+  ,scratchpadSpawnActionCustom   ,scratchpadManageHookDefault   ,scratchpadManageHook   ,scratchpadFilterOutWorkspace@@ -24,23 +25,19 @@  import XMonad import XMonad.Core-import XMonad.Hooks.ManageHelpers (doRectFloat)-import XMonad.Actions.DynamicWorkspaces (addHiddenWorkspace)--import Control.Monad (filterM)- import qualified XMonad.StackSet as W+import XMonad.Util.NamedScratchpad   -- $usage -- Bind a key to 'scratchpadSpawnAction' -- Pressing it will spawn the terminal, or bring it to the current -- workspace if it already exists.--- Pressing the key with the terminal on the current workspace will --- send it to a hidden workspace called @SP@.+-- Pressing the key with the terminal on the current workspace will+-- send it to a hidden workspace called @NSP@. ----- If you already have a workspace called @SP@, it will use that.--- @SP@ will also appear in xmobar and dzen status bars. You can tweak your+-- If you already have a workspace called @NSP@, it will use that.+-- @NSP@ will also appear in xmobar and dzen status bars. You can tweak your -- @dynamicLog@ settings to filter it out if you like. -- -- A tool like detach (<http://detach.sourceforge.net>) turns it@@ -60,7 +57,7 @@ -- > scratchpadSpawnAction conf -- -- Where @conf@ is the configuration.--- +-- -- And add one of the @scratchpadManageHook*@s to your ManageHook list. -- The default rectangle is half the screen wide and a quarter of the -- screen tall, centered.@@ -71,47 +68,24 @@ -- | Action to pop up the terminal, for the user to bind to a custom key. scratchpadSpawnAction :: XConfig l -- ^ The configuration, to retrieve the terminal                       -> X ()-scratchpadSpawnAction conf = -    scratchpadAction $ spawn $ terminal conf ++ " -name scratchpad"+scratchpadSpawnAction conf =+    scratchpadSpawnActionCustom $ terminal conf ++ " -name scratchpad"   -- | Action to pop up the terminal, with a directly specified terminal. scratchpadSpawnActionTerminal :: String -- ^ Name of the terminal program                                  -> X ()-scratchpadSpawnActionTerminal term = -    scratchpadAction $ spawn $ term ++ " -name scratchpad"------- The heart of the new summon/banish terminal. --- The logic is thus:--- 1. if the scratchpad is on the current workspace, send it to the hidden one.---    - if the scratchpad workspace doesn't exist yet, create it first.--- 2. if the scratchpad is elsewhere, bring it here. -scratchpadAction :: X () -> X ()-scratchpadAction action = withWindowSet $ \s -> do-  filterCurrent <- filterM (runQuery scratchpadQuery) -                     ( (maybe [] W.integrate -                        . W.stack -                        . W.workspace -                        . W.current) s)-  case filterCurrent of-    (x:_) -> do-      if null (filter ( (== scratchpadWorkspaceTag) . W.tag) (W.workspaces s))-         then addHiddenWorkspace scratchpadWorkspaceTag-         else return ()-      windows (W.shiftWin scratchpadWorkspaceTag x)-    []    -> do-      filterAll <- filterM (runQuery scratchpadQuery) (W.allWindows s)-      case filterAll of-        (x:_) -> windows (W.shiftWin (W.currentTag s) x)-        []    -> action -- run the provided action to spawn it.+scratchpadSpawnActionTerminal term =+    scratchpadSpawnActionCustom $ term ++ " -name scratchpad"  --- factored out since it appears in several places-scratchpadWorkspaceTag :: String-scratchpadWorkspaceTag = "SP"+-- | Action to pop up any program with the user specifying how to set+--   its resource to \"scratchpad\". For example, with gnome-terminal:+--+-- > scratchpadSpawnActionCustom "gnome-terminal --disable-factory --name scratchpad"+scratchpadSpawnActionCustom :: String -- ^ Command to spawn a program with resource \"scratchpad\"+                                 -> X ()+scratchpadSpawnActionCustom c = namedScratchpadAction [NS "scratchpad" c scratchpadQuery nonFloating] "scratchpad"  -- factored out since this is common to both the ManageHook and the action scratchpadQuery :: Query Bool@@ -121,22 +95,24 @@ -- | The ManageHook, with the default rectangle: -- Half the screen wide, a quarter of the screen tall, centered. scratchpadManageHookDefault :: ManageHook-scratchpadManageHookDefault = scratchpadManageHook scratchpadDefaultRect+scratchpadManageHookDefault = namedScratchpadManageHook [NS "" "" scratchpadQuery (customFloating scratchpadDefaultRect)]   -- | The ManageHook, with a user-specified StackSet.RationalRect,--- eg.+--   e.g., for a terminal 4/10 of the screen width from the left, half+--   the screen height from the top, and 6/10 of the screen width by+--   3/10 the screen height, use: ----- > scratchpadManageHook (W.RationalRect 0.25 0.375 0.5 0.25)+-- > scratchpadManageHook (W.RationalRect 0.4 0.5 0.6 0.3) scratchpadManageHook :: W.RationalRect -- ^ User-specified screen rectangle.                      -> ManageHook-scratchpadManageHook rect = scratchpadQuery --> doRectFloat rect+scratchpadManageHook rect = namedScratchpadManageHook [NS "" "" scratchpadQuery (customFloating rect)]   -- | Transforms a workspace list containing the SP workspace into one that -- doesn't contain it. Intended for use with logHooks. scratchpadFilterOutWorkspace :: [WindowSpace] -> [WindowSpace]-scratchpadFilterOutWorkspace = filter (\(W.Workspace tag _ _) -> tag /= scratchpadWorkspaceTag)+scratchpadFilterOutWorkspace = namedScratchpadFilterOutWorkspace   scratchpadDefaultRect :: W.RationalRect
+ XMonad/Util/StringProp.hs view
@@ -0,0 +1,56 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.StringProp+-- Copyright   :  (c) Nicolas Pouillard 2009+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Nicolas Pouillard <nicolas.pouillard@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Internal utility functions for storing Strings with the root window.+--+-- Used for global state like IORefs with string keys, but more latency,+-- persistent between xmonad restarts.++module XMonad.Util.StringProp (+    StringProp,+    getStringProp, setStringProp,+    getStringListProp, setStringListProp,+    ) where++import XMonad+import Control.Monad(liftM)+import Control.Applicative((<$>))+import Foreign.C.String (castCCharToChar,castCharToCChar)++type StringProp = String++withStringProp :: (MonadIO m) => StringProp -> Display -> (Window -> Atom -> m b) -> m b+withStringProp prop dpy f = do+    rootw <- io $ rootWindow dpy $ defaultScreen dpy+    a     <- io $ internAtom dpy prop False+    f rootw a++-- | Set the value of a string property.+setStringProp :: (MonadIO m) => Display -> StringProp -> [Char] -> m ()+setStringProp dpy prop string =+  withStringProp prop dpy $ \rootw a ->+    io $ changeProperty8 dpy rootw a a propModeReplace $ map castCharToCChar string++-- | Get the name of a string property and returns it as a 'Maybe'.+getStringProp :: (MonadIO m) => Display -> StringProp -> m (Maybe [Char])+getStringProp dpy prop =+  withStringProp prop dpy $ \rootw a -> do+    p <- io $ getWindowProperty8 dpy a rootw+    return $ map castCCharToChar <$> p++-- | Given a property name, returns its contents as a list. It uses the empty+-- list as default value.+getStringListProp :: (MonadIO m) => Display -> StringProp -> m [String]+getStringListProp dpy prop = maybe [] words `liftM` getStringProp dpy prop++-- | Given a property name and a list, sets the value of this property with+-- the list given as argument.+setStringListProp :: (MonadIO m) => Display -> StringProp -> [String] -> m ()+setStringListProp dpy prop str = setStringProp dpy prop (unwords str)
XMonad/Util/Themes.hs view
@@ -24,6 +24,14 @@     , oxymor00nTheme     , donaldTheme     , wfarrTheme+    , kavonForestTheme+    , kavonLakeTheme+    , kavonPeacockTheme+    , kavonVioGreenTheme+    , kavonBluesTheme+    , kavonAutumnTheme+    , kavonFireTheme+    , kavonChristmasTheme     , ThemeInfo (..)     ) where @@ -88,6 +96,14 @@                , robertTheme                , donaldTheme                , wfarrTheme+               , kavonForestTheme+               , kavonLakeTheme+               , kavonPeacockTheme+               , kavonVioGreenTheme+               , kavonBluesTheme+               , kavonAutumnTheme+               , kavonFireTheme+               , kavonChristmasTheme                ]  -- | The default xmonad theme, by David Roundy.@@ -201,3 +217,124 @@                                                , decoHeight          = 12                                                }              }++-- | Forest colours, by Kathryn Andersen+kavonForestTheme :: ThemeInfo+kavonForestTheme =+    newTheme { themeName        = "kavonForestTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Forest colours"+             , theme            = defaultTheme { activeColor         = "#115422"+                                               , activeBorderColor   = "#1a8033"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#543211"+                                               , inactiveBorderColor = "#804c19"+                                               , inactiveTextColor   = "#ffcc33"+                                               }+             }++-- | Lake (blue/green) colours, by Kathryn Andersen+kavonLakeTheme :: ThemeInfo+kavonLakeTheme =+    newTheme { themeName        = "kavonLakeTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Lake (blue/green) colours"+             , theme            = defaultTheme { activeColor         = "#001166"+                                               , activeBorderColor   = "#1f3999"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#09592a"+                                               , inactiveBorderColor = "#198044"+                                               , inactiveTextColor   = "#73e6a3"+                                               }+             }++-- | Peacock colours, by Kathryn Andersen+kavonPeacockTheme :: ThemeInfo+kavonPeacockTheme =+    newTheme { themeName        = "kavonPeacockTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Peacock colours"+             , theme            = defaultTheme { activeColor         = "#190f4c"+                                               , activeBorderColor   = "#2b1980"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#225173"+                                               , inactiveBorderColor = "#2a638c"+                                               , inactiveTextColor   = "#8fb2cc"+                                               }+             }++-- | Violet-Green colours, by Kathryn Andersen+kavonVioGreenTheme :: ThemeInfo+kavonVioGreenTheme =+    newTheme { themeName        = "kavonVioGreenTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Violet-Green colours"+             , theme            = defaultTheme { activeColor         = "#37174c"+                                               , activeBorderColor   = "#333399"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#174c17"+                                               , inactiveBorderColor = "#336633"+                                               , inactiveTextColor   = "#aaccaa"+                                               }+             }++-- | Blue colours, by Kathryn Andersen+kavonBluesTheme :: ThemeInfo+kavonBluesTheme =+    newTheme { themeName        = "kavonBluesTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Blue colours"+             , theme            = defaultTheme { activeColor         = "#000066"+                                               , activeBorderColor   = "#111199"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#9999ee"+                                               , inactiveBorderColor = "#6666cc"+                                               , inactiveTextColor   = "black"+                                               }+             }++-- | Christmas colours, by Kathryn Andersen+kavonChristmasTheme :: ThemeInfo+kavonChristmasTheme =+    newTheme { themeName        = "kavonChristmasTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Christmas (green + red) colours"+             , theme            = defaultTheme { activeColor         = "#660000"+                                               , activeBorderColor   = "#990000"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#006600"+                                               , inactiveBorderColor = "#003300"+                                               , inactiveTextColor   = "#99bb99"+                                               }+             }++-- | Autumn colours, by Kathryn Andersen+kavonAutumnTheme :: ThemeInfo+kavonAutumnTheme =+    newTheme { themeName        = "kavonAutumnTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Autumn (brown + red) colours"+             , theme            = defaultTheme { activeColor         = "#660000"+                                               , activeBorderColor   = "#990000"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#542d11"+                                               , inactiveBorderColor = "#804d1A"+                                               , inactiveTextColor   = "#ffcc33"+                                               }+             }++-- | Fire colours, by Kathryn Andersen+kavonFireTheme :: ThemeInfo+kavonFireTheme =+    newTheme { themeName        = "kavonFireTheme"+             , themeAuthor      = "Kathryn Andersen"+             , themeDescription = "Fire (orange + red) colours"+             , theme            = defaultTheme { activeColor         = "#660000"+                                               , activeBorderColor   = "#990000"+                                               , activeTextColor     = "white"+                                               , inactiveColor       = "#ff8000"+                                               , inactiveBorderColor = "#d9b162"+                                               , inactiveTextColor   = "black"+                                               }+             }+
XMonad/Util/Timer.hs view
@@ -23,6 +23,7 @@ import Control.Applicative import Control.Concurrent import Data.Unique+import System.Posix.Process (forkProcess)  -- $usage -- This module can be used to setup a timer to handle deferred events.@@ -35,7 +36,7 @@ startTimer :: Rational -> X TimerId startTimer s = io $ do   u   <- hashUnique <$> newUnique-  doubleFork $ do+  forkProcess $ do     d   <- openDisplay ""     rw  <- rootWindow d $ defaultScreen d     threadDelay (fromEnum $ s * 1000000)
+ XMonad/Util/Types.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.Types+-- Copyright   :  (c) Daniel Schoepe (2009)+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Daniel Schoepe <daniel.schoepe@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- Miscellaneous commonly used types.+--+-----------------------------------------------------------------------------++module XMonad.Util.Types (Direction1D(..)+                         ,Direction2D(..)+                         ) where++import Data.Typeable (Typeable)++-- | One-dimensional directions:+data Direction1D = Next | Prev deriving (Eq,Read,Show,Typeable)++-- | Two-dimensional directions:+data Direction2D = U -- ^ Up+                 | D -- ^ Down+                 | R -- ^ Right+                 | L -- ^ Left+                   deriving (Eq,Read,Show,Ord,Enum,Bounded,Typeable)
XMonad/Util/WindowProperties.hs view
@@ -8,19 +8,26 @@ -- Stability   :  unstable -- Portability :  unportable ----- EDSL for specifying window properties, such as title, classname or resource.+-- EDSL for specifying window properties; various utilities related to window+-- properties. -- ----------------------------------------------------------------------------- module XMonad.Util.WindowProperties (-    -- * Usage-    -- $usage-    Property(..), hasProperty, focusedHasProperty)+    -- * EDSL for window properties+    -- $edsl+    Property(..), hasProperty, focusedHasProperty, allWithProperty,+    propertyToQuery,+    -- * Helper functions+    -- $helpers+    getProp32, getProp32s) where import XMonad import qualified XMonad.StackSet as W+import Foreign.C.Types (CLong)+import Control.Monad --- $usage--- This module allows to specify window properties, such as title, classname or+-- $edsl+-- Allows to specify window properties, such as title, classname or -- resource, and to check them. -- -- In contrast to ManageHook properties, these are instances of Show and Read,@@ -31,7 +38,8 @@               | ClassName String               | Resource String               | Role String -- ^ WM_WINDOW_ROLE property-              | And Property Property  +              | Machine String -- ^ WM_CLIENT_MACHINE property+              | And Property Property               | Or  Property Property               | Not Property               | Const Bool@@ -44,7 +52,8 @@ hasProperty (Title s)     w = withDisplay $ \d -> fmap (Just s ==) $ io $ fetchName d w hasProperty (Resource s)  w = withDisplay $ \d -> fmap ((==) s . resName ) $ io $ getClassHint d w hasProperty (ClassName s) w = withDisplay $ \d -> fmap ((==) s . resClass) $ io $ getClassHint d w-hasProperty (Role s) w = withDisplay $ \d -> fmap ((==) (Just s)) $ getStringProperty d w "WM_WINDOW_ROLE"+hasProperty (Role s)      w = withDisplay $ \d -> fmap ((==) (Just s)) $ getStringProperty d w "WM_WINDOW_ROLE"+hasProperty (Machine s)   w = withDisplay $ \d -> fmap ((==) (Just s)) $ getStringProperty d w "WM_CLIENT_MACHINE" hasProperty (And p1 p2)   w = do { r1 <- hasProperty p1 w; r2 <- hasProperty p2 w; return $ r1 && r2 } hasProperty (Or p1 p2)    w = do { r1 <- hasProperty p1 w; r2 <- hasProperty p2 w; return $ r1 || r2 } hasProperty (Not p1)      w = do { r1 <- hasProperty p1 w; return $ not r1 }@@ -59,3 +68,31 @@         Just s  -> hasProperty p $ W.focus s         Nothing -> return False +-- | Find all existing windows with specified property+allWithProperty :: Property -> X [Window]+allWithProperty prop = withDisplay $ \dpy -> do+    rootw <- asks theRoot+    (_,_,wins) <- io $ queryTree dpy rootw+    hasProperty prop `filterM` wins++-- | Convert property to 'Query' 'Bool' (see "XMonad.ManageHook")+propertyToQuery :: Property -> Query Bool+propertyToQuery (Title s) = title =? s+propertyToQuery (Resource s) = resource =? s+propertyToQuery (ClassName s) = className =? s+propertyToQuery (Role s) = stringProperty "WM_WINDOW_ROLE" =? s+propertyToQuery (Machine s) = stringProperty "WM_CLIENT_MACHINE" =? s+propertyToQuery (And p1 p2) = propertyToQuery p1 <&&> propertyToQuery p2+propertyToQuery (Or p1 p2) = propertyToQuery p1 <||> propertyToQuery p2+propertyToQuery (Not p) = not `fmap` propertyToQuery p+propertyToQuery (Const b) = return b++-- $helpers++-- | Get a window property from atom+getProp32 :: Atom -> Window -> X (Maybe [CLong])+getProp32 a w = withDisplay $ \dpy -> io $ getWindowProperty32 dpy a w++-- | Get a window property from string+getProp32s :: String -> Window -> X (Maybe [CLong])+getProp32s str w = do { a <- getAtom str; getProp32 a w }
XMonad/Util/XSelection.hs view
@@ -1,10 +1,10 @@+{-# LANGUAGE CPP #-} {- | Module      :  XMonad.Util.XSelection Copyright   :  (C) 2007 Andrea Rossato, Matthew Sackman License     :  BSD3 -Maintainer  :  Andrea Rossato <andrea.rossato@unibz.it>,-               Matthew Sackman <matthew@wellquite.org>+Maintainer  : Gwern Branwen <gwern0@gmail.com> Stability   :  unstable Portability :  unportable @@ -19,18 +19,20 @@                                  getSelection,                                  promptSelection,                                  safePromptSelection,+                                 transformPromptSelection,+                                 transformSafePromptSelection,                                  putSelection) where  import Control.Concurrent (forkIO) import Control.Exception as E (catch) import Control.Monad(Monad (return, (>>)), Functor(..), liftM, join)-import Data.Bits (shiftL, (.&.), (.|.))-import Data.Char (chr, ord)+import Data.Char (ord) import Data.Maybe (fromMaybe)-import Data.Word (Word8) import XMonad import XMonad.Util.Run (safeSpawn, unsafeSpawn) +import Codec.Binary.UTF8.String (decode)+ {- $usage    Add @import XMonad.Util.XSelection@ to the top of Config.hs    Then make use of getSelection or promptSelection as needed; if@@ -38,7 +40,7 @@    the selection string is an URL you just highlighted), then one could add    to the xmonad.hs a line like thus: -   > , ((modMask .|. shiftMask, xK_b), promptSelection "firefox")+   > , ((modm .|. shiftMask, xK_b), promptSelection "firefox")     There are a number of known problems with XSelection: @@ -127,42 +129,12 @@ details on the advantages and disadvantages of using safeSpawn. -} promptSelection, safePromptSelection, unsafePromptSelection :: String -> X () promptSelection = unsafePromptSelection-safePromptSelection app = join $ io $ liftM (safeSpawn app) (getSelection)+safePromptSelection app = join $ io $ liftM (safeSpawn app . return) getSelection unsafePromptSelection app = join $ io $ liftM unsafeSpawn $ fmap (\x -> app ++ " " ++ x) getSelection -{- | Decode a UTF8 string packed into a list of Word8 values, directly to-   String; does not deal with CChar, hence you will want the counter-intuitive @map fromIntegral@-   UTF-8 decoding for internal use in getSelection.--   This code is copied from Eric Mertens's "utf-string" library <http://code.haskell.org/utf8-string/>-   (as of version 0.1),\which is BSD-3 licensed like this module.-   It'd be better to just @import Codec.Binary.UTF8.String (decode)@, but then users of this would need to install it; XMonad has enough-   dependencies already. -}-decode :: [Word8] -> String-decode [    ] = ""-decode (c:cs)-  | c < 0x80  = chr (fromEnum c) : decode cs-  | c < 0xc0  = replacement_character : decode cs-  | c < 0xe0  = multi_byte 1 0x1f 0x80-  | c < 0xf0  = multi_byte 2 0xf  0x800-  | c < 0xf8  = multi_byte 3 0x7  0x10000-  | c < 0xfc  = multi_byte 4 0x3  0x200000-  | c < 0xfe  = multi_byte 5 0x1  0x4000000-  | otherwise = replacement_character : decode cs-  where--    replacement_character :: Char-    replacement_character = '\xfffd'--    multi_byte :: Int -> Word8 -> Int -> [Char]-    multi_byte i mask overlong = aux i cs (fromEnum (c .&. mask))-      where-        aux 0 rs acc-          | overlong <= acc && acc <= 0x10ffff &&-            (acc < 0xd800 || 0xdfff < acc)     &&-            (acc < 0xfffe || 0xffff < acc)      = chr acc : decode rs-          | otherwise = replacement_character : decode rs-        aux n (r:rs) acc-          | r .&. 0xc0 == 0x80 = aux (n-1) rs-                               $ shiftL acc 6 .|. fromEnum (r .&. 0x3f)-        aux _ rs     _ = replacement_character : decode rs+{- | A wrapper around 'promptSelection' and its safe variant. They take two parameters, the first is a function that transforms strings, and the second is the application to run. The transformer essentially transforms the selection in X.+One example is to wrap code, such as a command line action copied out of the browser to be run as @"sudo" ++ cmd@ or @"su - -c \""++ cmd ++"\""@.+-}+transformPromptSelection, transformSafePromptSelection :: (String -> String) -> String -> X ()+transformPromptSelection f app = join $ io $ liftM (safeSpawn app . return) (fmap f getSelection)+transformSafePromptSelection f app = join $ io $ liftM unsafeSpawn $ fmap (\x -> app ++ " " ++ x) (fmap f getSelection)
XMonad/Util/XUtils.hs view
@@ -137,7 +137,7 @@   io $ fillRectangle d p gc 0 0 wh ht   -- and now again   io $ setForeground d gc color'-  io $ fillRectangle d p gc (fi bw) (fi bw) ((wh - (bw * 2))) (ht - (bw * 2))+  io $ fillRectangle d p gc (fi bw) (fi bw) (wh - (bw * 2)) (ht - (bw * 2))   when (isJust str) $ do     let (xmf,fc,bc,s) = fromJust str     printStringXMF d p xmf gc fc bc x y s
xmonad-contrib.cabal view
@@ -1,5 +1,5 @@ name:               xmonad-contrib-version:            0.8.1+version:            0.9 homepage:           http://xmonad.org/ synopsis:           Third party extensions for xmonad description:@@ -34,9 +34,6 @@ flag use_xft   description: Use Xft to render text -flag with_utf8-  description: Enable Utf8 support- flag testing   description: Testing mode   default: False@@ -52,18 +49,14 @@         extensions: ForeignFunctionInterface         cpp-options: -DXFT -    if flag(with_utf8)-        build-depends: utf8-string-        extensions: ForeignFunctionInterface-        cpp-options: -DUTF8--    build-depends:      mtl, unix, X11>=1.4.3, xmonad>=0.8, xmonad<0.9-    ghc-options:        -Wall+    build-depends:      mtl, unix, X11>=1.4.6.1, xmonad>=0.9, xmonad<1, utf8-string+    ghc-options:        -fwarn-tabs -Wall+    extensions:         ForeignFunctionInterface      if flag(testing)-        ghc-options:    -Werror+        ghc-options:    -fwarn-tabs -Werror -    if impl (ghc >= 6.10.1) && arch (x86_64)+    if impl (ghc == 6.10.1) && arch (x86_64)         ghc-options:    -O0      exposed-modules:    XMonad.Doc@@ -75,6 +68,7 @@                         XMonad.Actions.CopyWindow                         XMonad.Actions.CycleRecentWS                         XMonad.Actions.CycleSelectedLayouts+                        XMonad.Actions.CycleWindows                         XMonad.Actions.CycleWS                         XMonad.Actions.DeManage                         XMonad.Actions.DwmPromote@@ -83,72 +77,106 @@                         XMonad.Actions.FlexibleManipulate                         XMonad.Actions.FlexibleResize                         XMonad.Actions.FloatKeys+                        XMonad.Actions.FloatSnap                         XMonad.Actions.FocusNth+                        XMonad.Actions.GridSelect+                        XMonad.Actions.MessageFeedback                         XMonad.Actions.MouseGestures                         XMonad.Actions.MouseResize                         XMonad.Actions.NoBorders+                        XMonad.Actions.OnScreen                         XMonad.Actions.PerWorkspaceKeys+                        XMonad.Actions.PhysicalScreens                         XMonad.Actions.Plane                         XMonad.Actions.Promote                         XMonad.Actions.RotSlaves+                        XMonad.Actions.RandomBackground                         XMonad.Actions.Search                         XMonad.Actions.SimpleDate                         XMonad.Actions.SinkAll+                        XMonad.Actions.SpawnOn                         XMonad.Actions.Submap                         XMonad.Actions.SwapWorkspaces                         XMonad.Actions.TagWindows+                        XMonad.Actions.TopicSpace                         XMonad.Actions.UpdatePointer+                        XMonad.Actions.UpdateFocus                         XMonad.Actions.Warp+                        XMonad.Actions.WindowMenu                         XMonad.Actions.WindowNavigation                         XMonad.Actions.WindowGo                         XMonad.Actions.WindowBringer+                        XMonad.Actions.WithAll+                        XMonad.Actions.WorkspaceCursors                         XMonad.Config.Arossato+                        XMonad.Config.Azerty                         XMonad.Config.Desktop                         XMonad.Config.Droundy                         XMonad.Config.Gnome                         XMonad.Config.Kde-                        XMonad.Config.PlainConfig                         XMonad.Config.Sjanssen                         XMonad.Config.Xfce                         XMonad.Hooks.DynamicHooks                         XMonad.Hooks.DynamicLog-                        XMonad.Hooks.EventHook                         XMonad.Hooks.EwmhDesktops                         XMonad.Hooks.FadeInactive+                        XMonad.Hooks.FloatNext+                        XMonad.Hooks.InsertPosition                         XMonad.Hooks.ManageDocks                         XMonad.Hooks.ManageHelpers+                        XMonad.Hooks.Place+                        XMonad.Hooks.RestoreMinimized                         XMonad.Hooks.Script                         XMonad.Hooks.SetWMName                         XMonad.Hooks.ServerMode                         XMonad.Hooks.UrgencyHook+                        XMonad.Hooks.WorkspaceByPos                         XMonad.Hooks.XPropManage                         XMonad.Layout.Accordion+                        XMonad.Layout.AutoMaster+                        XMonad.Layout.BorderResize                         XMonad.Layout.BoringWindows+                        XMonad.Layout.CenteredMaster                         XMonad.Layout.Circle+                        XMonad.Layout.Cross+                        XMonad.Layout.Column                         XMonad.Layout.Combo+                        XMonad.Layout.ComboP                         XMonad.Layout.Decoration                         XMonad.Layout.DecorationMadness                         XMonad.Layout.Dishes                         XMonad.Layout.DragPane                         XMonad.Layout.DwmStyle+                        XMonad.Layout.FixedColumn                         XMonad.Layout.Gaps                         XMonad.Layout.Grid+                        XMonad.Layout.GridVariants                         XMonad.Layout.HintedGrid                         XMonad.Layout.HintedTile                         XMonad.Layout.IM+                        XMonad.Layout.IndependentScreens+                        XMonad.Layout.LayoutBuilder                         XMonad.Layout.LayoutCombinators                         XMonad.Layout.LayoutHints                         XMonad.Layout.LayoutModifier                         XMonad.Layout.LayoutScreens+                        XMonad.Layout.LimitWindows                         XMonad.Layout.MagicFocus                         XMonad.Layout.Magnifier                         XMonad.Layout.Master                         XMonad.Layout.Maximize+                        XMonad.Layout.MessageControl+                        XMonad.Layout.Minimize+                        XMonad.Layout.Monitor+                        XMonad.Layout.Mosaic                         XMonad.Layout.MosaicAlt+                        XMonad.Layout.MouseResizableTile                         XMonad.Layout.MultiToggle                         XMonad.Layout.MultiToggle.Instances                         XMonad.Layout.Named                         XMonad.Layout.NoBorders+                        XMonad.Layout.NoFrillsDecoration+                        XMonad.Layout.OneBig                         XMonad.Layout.PerWorkspace                         XMonad.Layout.Reflect                         XMonad.Layout.ResizableTile@@ -157,10 +185,12 @@                         XMonad.Layout.Simplest                         XMonad.Layout.SimpleDecoration                         XMonad.Layout.SimpleFloat+                        XMonad.Layout.Spacing                         XMonad.Layout.Spiral                         XMonad.Layout.Square                         XMonad.Layout.ShowWName                         XMonad.Layout.StackTile+                        XMonad.Layout.SubLayouts                         XMonad.Layout.Tabbed                         XMonad.Layout.TabBarDecoration                         XMonad.Layout.ThreeColumns@@ -186,6 +216,7 @@                         XMonad.Prompt.Window                         XMonad.Prompt.Workspace                         XMonad.Prompt.XMonad+                        XMonad.Util.Cursor                         XMonad.Util.CustomKeys                         XMonad.Util.Dmenu                         XMonad.Util.Dzen@@ -193,12 +224,18 @@                         XMonad.Util.Font                         XMonad.Util.Invisible                         XMonad.Util.Loggers+                        XMonad.Util.NamedActions+                        XMonad.Util.NamedScratchpad                         XMonad.Util.NamedWindows+                        XMonad.Util.StringProp                         XMonad.Util.Run                         XMonad.Util.Scratchpad                         XMonad.Util.Themes                         XMonad.Util.Timer+                        XMonad.Util.Types                         XMonad.Util.WindowProperties                         XMonad.Util.WorkspaceCompare+                        XMonad.Util.Paste+                        XMonad.Util.Replace                         XMonad.Util.XSelection                         XMonad.Util.XUtils