packages feed

xmonad-contrib 0.12 → 0.13

raw patch · 65 files changed

+2787/−519 lines, 65 filesdep +bytestringdep ~X11dep ~basedep ~containersnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring

Dependency ranges changed: X11, base, containers, xmonad

API changes (from Hackage documentation)

- XMonad.Hooks.ManageDocks: instance GHC.Read.Read XMonad.Hooks.ManageDocks.ClearGapCache
- XMonad.Hooks.ManageDocks: instance GHC.Show.Show XMonad.Hooks.ManageDocks.ClearGapCache
- XMonad.Hooks.ManageDocks: instance XMonad.Core.Message XMonad.Hooks.ManageDocks.ClearGapCache
- XMonad.Layout.AvoidFloats: instance (GHC.Classes.Ord a, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.AvoidFloats.AvoidFloats a)
- XMonad.Layout.Combo: instance (GHC.Read.Read l, GHC.Read.Read a, GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.Combo.CombineTwo l l1 l2 a)
- XMonad.Layout.Combo: instance (GHC.Show.Show l, GHC.Show.Show a, GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.Combo.CombineTwo l l1 l2 a)
- XMonad.Layout.ComboP: instance (GHC.Read.Read l, GHC.Read.Read a, GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.ComboP.CombineTwoP l l1 l2 a)
- XMonad.Layout.ComboP: instance (GHC.Show.Show l, GHC.Show.Show a, GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.ComboP.CombineTwoP l l1 l2 a)
- XMonad.Layout.Decoration: instance (GHC.Read.Read s, GHC.Read.Read (ds a)) => GHC.Read.Read (XMonad.Layout.Decoration.Decoration ds s a)
- XMonad.Layout.Decoration: instance (GHC.Show.Show s, GHC.Show.Show (ds a)) => GHC.Show.Show (XMonad.Layout.Decoration.Decoration ds s a)
- XMonad.Layout.Fullscreen: instance (GHC.Classes.Ord a, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.Fullscreen.FullscreenFloat a)
- XMonad.Layout.Groups: instance (GHC.Read.Read a, GHC.Read.Read (l a)) => GHC.Read.Read (XMonad.Layout.Groups.Group l a)
- XMonad.Layout.Groups: instance (GHC.Show.Show a, GHC.Show.Show (l a)) => GHC.Show.Show (XMonad.Layout.Groups.Group l a)
- XMonad.Layout.Groups.Examples: instance (s ~ XMonad.Layout.Decoration.DefaultShrinker) => Data.Default.Class.Default (XMonad.Layout.Groups.Examples.TiledTabsConfig s)
- XMonad.Layout.IfMax: instance (GHC.Read.Read (l1 w), GHC.Read.Read (l2 w)) => GHC.Read.Read (XMonad.Layout.IfMax.IfMax l1 l2 w)
- XMonad.Layout.IfMax: instance (GHC.Show.Show (l1 w), GHC.Show.Show (l2 w)) => GHC.Show.Show (XMonad.Layout.IfMax.IfMax l1 l2 w)
- XMonad.Layout.IfMax: instance (XMonad.Core.LayoutClass l1 a, XMonad.Core.LayoutClass l2 a) => XMonad.Core.LayoutClass (XMonad.Layout.IfMax.IfMax l1 l2) a
- XMonad.Layout.LayoutBuilder: data LayoutN l1 l2 a
- XMonad.Layout.LayoutBuilder: instance (GHC.Read.Read a, GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.LayoutBuilder.LayoutN l1 l2 a)
- XMonad.Layout.LayoutBuilder: instance (GHC.Show.Show a, GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.LayoutBuilder.LayoutN l1 l2 a)
- XMonad.Layout.LayoutBuilder: instance (XMonad.Core.LayoutClass l1 a, XMonad.Core.LayoutClass l2 a, GHC.Read.Read a, GHC.Show.Show a, GHC.Classes.Eq a, Data.Typeable.Internal.Typeable a) => XMonad.Core.LayoutClass (XMonad.Layout.LayoutBuilder.LayoutN l1 l2) a
- XMonad.Layout.LayoutBuilderP: instance (GHC.Read.Read p, GHC.Read.Read a, GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.LayoutBuilderP.LayoutP p l1 l2 a)
- XMonad.Layout.LayoutBuilderP: instance (GHC.Show.Show p, GHC.Show.Show a, GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.LayoutBuilderP.LayoutP p l1 l2 a)
- XMonad.Layout.LayoutCombinators: instance (GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.LayoutCombinators.NewSelect l1 l2 a)
- XMonad.Layout.LayoutCombinators: instance (GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.LayoutCombinators.NewSelect l1 l2 a)
- XMonad.Layout.LayoutModifier: instance (GHC.Read.Read (m a), GHC.Read.Read (l a)) => GHC.Read.Read (XMonad.Layout.LayoutModifier.ModifiedLayout m l a)
- XMonad.Layout.LayoutModifier: instance (GHC.Show.Show (m a), GHC.Show.Show (l a)) => GHC.Show.Show (XMonad.Layout.LayoutModifier.ModifiedLayout m l a)
- XMonad.Layout.MultiToggle: instance (GHC.Read.Read a, GHC.Read.Read b) => GHC.Read.Read (XMonad.Layout.MultiToggle.HCons a b)
- XMonad.Layout.MultiToggle: instance (GHC.Read.Read ts, GHC.Read.Read (l a)) => GHC.Read.Read (XMonad.Layout.MultiToggle.MultiToggleS ts l a)
- XMonad.Layout.MultiToggle: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (XMonad.Layout.MultiToggle.HCons a b)
- XMonad.Layout.MultiToggle: instance (GHC.Show.Show ts, GHC.Show.Show (l a)) => GHC.Show.Show (XMonad.Layout.MultiToggle.MultiToggleS ts l a)
- XMonad.Layout.NoBorders: instance (GHC.Read.Read p, GHC.Read.Read w) => GHC.Read.Read (XMonad.Layout.NoBorders.ConfigurableBorder p w)
- XMonad.Layout.NoBorders: instance (GHC.Show.Show p, GHC.Show.Show w) => GHC.Show.Show (XMonad.Layout.NoBorders.ConfigurableBorder p w)
- XMonad.Layout.OnHost: instance (GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.OnHost.OnHost l1 l2 a)
- XMonad.Layout.OnHost: instance (GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.OnHost.OnHost l1 l2 a)
- XMonad.Layout.PerScreen: instance (GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.PerScreen.PerScreen l1 l2 a)
- XMonad.Layout.PerScreen: instance (GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.PerScreen.PerScreen l1 l2 a)
- XMonad.Layout.PerWorkspace: instance (GHC.Read.Read (l1 a), GHC.Read.Read (l2 a)) => GHC.Read.Read (XMonad.Layout.PerWorkspace.PerWorkspace l1 l2 a)
- XMonad.Layout.PerWorkspace: instance (GHC.Show.Show (l1 a), GHC.Show.Show (l2 a)) => GHC.Show.Show (XMonad.Layout.PerWorkspace.PerWorkspace l1 l2 a)
- XMonad.Layout.SubLayouts: instance (GHC.Read.Read a, GHC.Read.Read (l a)) => GHC.Read.Read (XMonad.Layout.SubLayouts.Sublayout l a)
- XMonad.Layout.SubLayouts: instance (GHC.Show.Show a, GHC.Show.Show (l a)) => GHC.Show.Show (XMonad.Layout.SubLayouts.Sublayout l a)
- XMonad.Layout.ToggleLayouts: instance (GHC.Read.Read (lt a), GHC.Read.Read (lf a)) => GHC.Read.Read (XMonad.Layout.ToggleLayouts.ToggleLayouts lt lf a)
- XMonad.Layout.ToggleLayouts: instance (GHC.Show.Show (lt a), GHC.Show.Show (lf a)) => GHC.Show.Show (XMonad.Layout.ToggleLayouts.ToggleLayouts lt lf a)
- XMonad.Layout.ZoomRow: instance (GHC.Classes.Eq a, GHC.Classes.Eq (f a)) => GHC.Classes.Eq (XMonad.Layout.ZoomRow.ZoomRow f a)
- XMonad.Layout.ZoomRow: instance (GHC.Read.Read a, GHC.Read.Read (f a)) => GHC.Read.Read (XMonad.Layout.ZoomRow.ZoomRow f a)
- XMonad.Layout.ZoomRow: instance (GHC.Show.Show a, GHC.Show.Show (f a)) => GHC.Show.Show (XMonad.Layout.ZoomRow.ZoomRow f a)
+ XMonad.Actions.CycleWS: HiddenEmptyWS :: WSType
+ XMonad.Actions.DynamicProjects: changeProjectDirPrompt :: XPConfig -> X ()
+ XMonad.Actions.DynamicProjects: instance XMonad.Prompt.XPrompt XMonad.Actions.DynamicProjects.ProjectPrompt
+ XMonad.Actions.DynamicWorkspaces: instance GHC.Read.Read XMonad.Actions.DynamicWorkspaces.DynamicWorkspaceState
+ XMonad.Actions.DynamicWorkspaces: instance GHC.Show.Show XMonad.Actions.DynamicWorkspaces.DynamicWorkspaceState
+ XMonad.Actions.DynamicWorkspaces: instance XMonad.Core.ExtensionClass XMonad.Actions.DynamicWorkspaces.DynamicWorkspaceState
+ XMonad.Actions.DynamicWorkspaces: removeEmptyWorkspaceByTag :: String -> X ()
+ XMonad.Actions.DynamicWorkspaces: setWorkspaceIndex :: WorkspaceIndex -> X ()
+ XMonad.Actions.DynamicWorkspaces: type WorkspaceIndex = Int
+ XMonad.Actions.DynamicWorkspaces: withWorkspaceIndex :: (String -> WindowSet -> WindowSet) -> WorkspaceIndex -> X ()
+ XMonad.Actions.FocusNth: swapNth :: Int -> X ()
+ XMonad.Actions.FocusNth: swapNth' :: Int -> Stack a -> Stack a
+ XMonad.Actions.Navigation2D: hybridNavigation :: Navigation2D
+ XMonad.Actions.Submap: submapDefaultWithKey :: ((KeyMask, KeySym) -> X ()) -> Map (KeyMask, KeySym) (X ()) -> X ()
+ XMonad.Actions.TopicSpace: infix 9 >*>
+ XMonad.Actions.TreeSelect: TSConfig :: Bool -> Pixel -> String -> (Pixel, Pixel) -> (Pixel, Pixel) -> (Pixel, Pixel) -> Pixel -> Int -> Int -> Int -> Int -> Int -> Map (KeyMask, KeySym) (TreeSelect a (Maybe a)) -> TSConfig a
+ XMonad.Actions.TreeSelect: TSNode :: String -> String -> a -> TSNode a
+ XMonad.Actions.TreeSelect: [ts_background] :: TSConfig a -> Pixel
+ XMonad.Actions.TreeSelect: [ts_extra] :: TSConfig a -> Pixel
+ XMonad.Actions.TreeSelect: [ts_font] :: TSConfig a -> String
+ XMonad.Actions.TreeSelect: [ts_hidechildren] :: TSConfig a -> Bool
+ XMonad.Actions.TreeSelect: [ts_highlight] :: TSConfig a -> (Pixel, Pixel)
+ XMonad.Actions.TreeSelect: [ts_indent] :: TSConfig a -> Int
+ XMonad.Actions.TreeSelect: [ts_navigate] :: TSConfig a -> Map (KeyMask, KeySym) (TreeSelect a (Maybe a))
+ XMonad.Actions.TreeSelect: [ts_node] :: TSConfig a -> (Pixel, Pixel)
+ XMonad.Actions.TreeSelect: [ts_node_height] :: TSConfig a -> Int
+ XMonad.Actions.TreeSelect: [ts_node_width] :: TSConfig a -> Int
+ XMonad.Actions.TreeSelect: [ts_nodealt] :: TSConfig a -> (Pixel, Pixel)
+ XMonad.Actions.TreeSelect: [ts_originX] :: TSConfig a -> Int
+ XMonad.Actions.TreeSelect: [ts_originY] :: TSConfig a -> Int
+ XMonad.Actions.TreeSelect: [tsn_extra] :: TSNode a -> String
+ XMonad.Actions.TreeSelect: [tsn_name] :: TSNode a -> String
+ XMonad.Actions.TreeSelect: [tsn_value] :: TSNode a -> a
+ XMonad.Actions.TreeSelect: cancel :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: data TSConfig a
+ XMonad.Actions.TreeSelect: data TSNode a
+ XMonad.Actions.TreeSelect: defaultNavigation :: Map (KeyMask, KeySym) (TreeSelect a (Maybe a))
+ XMonad.Actions.TreeSelect: instance Control.Monad.IO.Class.MonadIO (XMonad.Actions.TreeSelect.TreeSelect a)
+ XMonad.Actions.TreeSelect: instance Control.Monad.Reader.Class.MonadReader (XMonad.Actions.TreeSelect.TSConfig a) (XMonad.Actions.TreeSelect.TreeSelect a)
+ XMonad.Actions.TreeSelect: instance Control.Monad.State.Class.MonadState (XMonad.Actions.TreeSelect.TSState a) (XMonad.Actions.TreeSelect.TreeSelect a)
+ XMonad.Actions.TreeSelect: instance Data.Default.Class.Default (XMonad.Actions.TreeSelect.TSConfig a)
+ XMonad.Actions.TreeSelect: instance GHC.Base.Applicative (XMonad.Actions.TreeSelect.TreeSelect a)
+ XMonad.Actions.TreeSelect: instance GHC.Base.Functor (XMonad.Actions.TreeSelect.TreeSelect a)
+ XMonad.Actions.TreeSelect: instance GHC.Base.Monad (XMonad.Actions.TreeSelect.TreeSelect a)
+ XMonad.Actions.TreeSelect: moveChild :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: moveHistBack :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: moveHistForward :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: moveNext :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: moveParent :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: movePrev :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: moveTo :: [String] -> TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: select :: TreeSelect a (Maybe a)
+ XMonad.Actions.TreeSelect: toWorkspaces :: Forest String -> [WorkspaceId]
+ XMonad.Actions.TreeSelect: treeselect :: TSConfig a -> Forest (TSNode a) -> X (Maybe a)
+ XMonad.Actions.TreeSelect: treeselectAction :: TSConfig (X a) -> Forest (TSNode (X a)) -> X ()
+ XMonad.Actions.TreeSelect: treeselectAt :: TSConfig a -> TreeZipper (TSNode a) -> [[String]] -> X (Maybe a)
+ XMonad.Actions.TreeSelect: treeselectWorkspace :: TSConfig WorkspaceId -> Forest String -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
+ XMonad.Actions.TreeSelect: tsDefaultConfig :: TSConfig a
+ XMonad.Actions.TreeSelect: type Pixel = Word64
+ XMonad.Actions.WindowBringer: WindowBringerConfig :: String -> [String] -> (WindowSpace -> Window -> X String) -> WindowBringerConfig
+ XMonad.Actions.WindowBringer: [menuArgs] :: WindowBringerConfig -> [String]
+ XMonad.Actions.WindowBringer: [menuCommand] :: WindowBringerConfig -> String
+ XMonad.Actions.WindowBringer: [windowTitler] :: WindowBringerConfig -> WindowSpace -> Window -> X String
+ XMonad.Actions.WindowBringer: actionMenu :: WindowBringerConfig -> (Window -> WindowSet -> WindowSet) -> X ()
+ XMonad.Actions.WindowBringer: bringMenuConfig :: WindowBringerConfig -> X ()
+ XMonad.Actions.WindowBringer: data WindowBringerConfig
+ XMonad.Actions.WindowBringer: gotoMenuConfig :: WindowBringerConfig -> X ()
+ XMonad.Actions.WindowBringer: instance Data.Default.Class.Default XMonad.Actions.WindowBringer.WindowBringerConfig
+ XMonad.Actions.WindowBringer: windowMap' :: (WindowSpace -> Window -> X String) -> X (Map String Window)
+ XMonad.Actions.WindowGo: raiseNextMaybeCustomFocus :: (Window -> WindowSet -> WindowSet) -> X () -> Query Bool -> X ()
+ XMonad.Actions.Workscreen: type WorkscreenId = Int
+ XMonad.Actions.WorkspaceNames: getCurrentWorkspaceName :: X (Maybe String)
+ XMonad.Actions.WorkspaceNames: getWorkspaceName :: WorkspaceId -> X (Maybe String)
+ XMonad.Actions.WorkspaceNames: getWorkspaceNames' :: X (WorkspaceId -> Maybe String)
+ XMonad.Config.Gnome: desktopLayoutModifiers :: LayoutClass l a => l a -> ModifiedLayout AvoidStruts l a
+ XMonad.Config.Kde: desktopLayoutModifiers :: LayoutClass l a => l a -> ModifiedLayout AvoidStruts l a
+ XMonad.Config.Mate: desktopLayoutModifiers :: LayoutClass l a => l a -> ModifiedLayout AvoidStruts l a
+ XMonad.Config.Xfce: desktopLayoutModifiers :: LayoutClass l a => l a -> ModifiedLayout AvoidStruts l a
+ XMonad.Hooks.DynamicBars: dynStatusBarEventHook' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> Event -> X All
+ XMonad.Hooks.DynamicBars: dynStatusBarStartup' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> X ()
+ XMonad.Hooks.DynamicBars: multiPPFormat :: (PP -> X String) -> PP -> PP -> X ()
+ XMonad.Hooks.DynamicBars: type DynamicStatusBarPartialCleanup = ScreenId -> IO ()
+ XMonad.Hooks.ManageDocks: docks :: XConfig a -> XConfig a
+ XMonad.Hooks.ManageDocks: docksStartupHook :: X ()
+ XMonad.Hooks.ManageDocks: instance GHC.Classes.Eq XMonad.Hooks.ManageDocks.StrutCache
+ XMonad.Hooks.ManageDocks: instance XMonad.Core.ExtensionClass XMonad.Hooks.ManageDocks.StrutCache
+ XMonad.Hooks.ManageDocks: instance XMonad.Core.Message XMonad.Hooks.ManageDocks.UpdateDocks
+ XMonad.Hooks.ManageHelpers: infixr 0 -?>>
+ XMonad.Layout.AvoidFloats: instance (GHC.Read.Read a, GHC.Classes.Ord a) => GHC.Read.Read (XMonad.Layout.AvoidFloats.AvoidFloats a)
+ XMonad.Layout.Combo: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a), GHC.Read.Read l, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.Combo.CombineTwo l l1 l2 a)
+ XMonad.Layout.Combo: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a), GHC.Show.Show l, GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.Combo.CombineTwo l l1 l2 a)
+ XMonad.Layout.ComboP: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a), GHC.Read.Read l, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.ComboP.CombineTwoP l l1 l2 a)
+ XMonad.Layout.ComboP: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a), GHC.Show.Show l, GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.ComboP.CombineTwoP l l1 l2 a)
+ XMonad.Layout.Decoration: instance (GHC.Read.Read (ds a), GHC.Read.Read s) => GHC.Read.Read (XMonad.Layout.Decoration.Decoration ds s a)
+ XMonad.Layout.Decoration: instance (GHC.Show.Show (ds a), GHC.Show.Show s) => GHC.Show.Show (XMonad.Layout.Decoration.Decoration ds s a)
+ XMonad.Layout.Fullscreen: instance (GHC.Read.Read a, GHC.Classes.Ord a) => GHC.Read.Read (XMonad.Layout.Fullscreen.FullscreenFloat a)
+ XMonad.Layout.Groups: instance (GHC.Read.Read (l a), GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.Groups.Group l a)
+ XMonad.Layout.Groups: instance (GHC.Show.Show (l a), GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.Groups.Group l a)
+ XMonad.Layout.Groups.Examples: instance s ~ XMonad.Layout.Decoration.DefaultShrinker => Data.Default.Class.Default (XMonad.Layout.Groups.Examples.TiledTabsConfig s)
+ XMonad.Layout.IfMax: instance (GHC.Read.Read (l2 w), GHC.Read.Read (l1 w)) => GHC.Read.Read (XMonad.Layout.IfMax.IfMax l1 l2 w)
+ XMonad.Layout.IfMax: instance (GHC.Show.Show (l2 w), GHC.Show.Show (l1 w)) => GHC.Show.Show (XMonad.Layout.IfMax.IfMax l1 l2 w)
+ XMonad.Layout.IfMax: instance (XMonad.Core.LayoutClass l1 Graphics.X11.Types.Window, XMonad.Core.LayoutClass l2 Graphics.X11.Types.Window) => XMonad.Core.LayoutClass (XMonad.Layout.IfMax.IfMax l1 l2) Graphics.X11.Types.Window
+ XMonad.Layout.LayoutBuilder: Proxy :: Proxy a
+ XMonad.Layout.LayoutBuilder: alwaysTrue :: Predicate p w => Proxy w -> p
+ XMonad.Layout.LayoutBuilder: checkPredicate :: Predicate p w => p -> w -> X Bool
+ XMonad.Layout.LayoutBuilder: class Predicate p w
+ XMonad.Layout.LayoutBuilder: data LayoutB l1 l2 p a
+ XMonad.Layout.LayoutBuilder: data Proxy a
+ XMonad.Layout.LayoutBuilder: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a), GHC.Read.Read p, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.LayoutBuilder.LayoutB l1 l2 p a)
+ XMonad.Layout.LayoutBuilder: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a), GHC.Show.Show p, GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.LayoutBuilder.LayoutB l1 l2 p a)
+ XMonad.Layout.LayoutBuilder: instance (XMonad.Core.LayoutClass l1 a, XMonad.Core.LayoutClass l2 a, GHC.Read.Read a, GHC.Show.Show a, GHC.Show.Show p, GHC.Classes.Eq a, Data.Typeable.Internal.Typeable a, XMonad.Layout.LayoutBuilder.Predicate p a) => XMonad.Core.LayoutClass (XMonad.Layout.LayoutBuilder.LayoutB l1 l2 p) a
+ XMonad.Layout.LayoutBuilder: instance GHC.Read.Read p => GHC.Read.Read (XMonad.Layout.LayoutBuilder.Limit p)
+ XMonad.Layout.LayoutBuilder: instance GHC.Show.Show p => GHC.Show.Show (XMonad.Layout.LayoutBuilder.Limit p)
+ XMonad.Layout.LayoutBuilder: instance XMonad.Layout.LayoutBuilder.Predicate () a
+ XMonad.Layout.LayoutBuilder: instance XMonad.Layout.LayoutBuilder.Predicate XMonad.Util.WindowProperties.Property Graphics.X11.Types.Window
+ XMonad.Layout.LayoutBuilder: layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a, Predicate p a, Predicate p' a) => p -> SubBox -> Maybe SubBox -> l1 a -> LayoutB l2 l3 p' a -> LayoutB l1 (LayoutB l2 l3 p') p a
+ XMonad.Layout.LayoutBuilder: type LayoutN l1 l2 a = LayoutB l1 l2 () a
+ XMonad.Layout.LayoutBuilderP: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a), GHC.Read.Read p, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.LayoutBuilderP.LayoutP p l1 l2 a)
+ XMonad.Layout.LayoutBuilderP: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a), GHC.Show.Show p, GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.LayoutBuilderP.LayoutP p l1 l2 a)
+ XMonad.Layout.LayoutCombinators: infixr 5 |||
+ XMonad.Layout.LayoutCombinators: infixr 6 */**
+ XMonad.Layout.LayoutCombinators: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a)) => GHC.Read.Read (XMonad.Layout.LayoutCombinators.NewSelect l1 l2 a)
+ XMonad.Layout.LayoutCombinators: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a)) => GHC.Show.Show (XMonad.Layout.LayoutCombinators.NewSelect l1 l2 a)
+ XMonad.Layout.LayoutModifier: instance (GHC.Read.Read (l a), GHC.Read.Read (m a)) => GHC.Read.Read (XMonad.Layout.LayoutModifier.ModifiedLayout m l a)
+ XMonad.Layout.LayoutModifier: instance (GHC.Show.Show (l a), GHC.Show.Show (m a)) => GHC.Show.Show (XMonad.Layout.LayoutModifier.ModifiedLayout m l a)
+ XMonad.Layout.MultiToggle: infixr 0 ??
+ XMonad.Layout.MultiToggle: instance (GHC.Read.Read (l a), GHC.Read.Read ts) => GHC.Read.Read (XMonad.Layout.MultiToggle.MultiToggleS ts l a)
+ XMonad.Layout.MultiToggle: instance (GHC.Read.Read b, GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.MultiToggle.HCons a b)
+ XMonad.Layout.MultiToggle: instance (GHC.Show.Show (l a), GHC.Show.Show ts) => GHC.Show.Show (XMonad.Layout.MultiToggle.MultiToggleS ts l a)
+ XMonad.Layout.MultiToggle: instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.MultiToggle.HCons a b)
+ XMonad.Layout.NoBorders: instance (GHC.Read.Read w, GHC.Read.Read p) => GHC.Read.Read (XMonad.Layout.NoBorders.ConfigurableBorder p w)
+ XMonad.Layout.NoBorders: instance (GHC.Show.Show w, GHC.Show.Show p) => GHC.Show.Show (XMonad.Layout.NoBorders.ConfigurableBorder p w)
+ XMonad.Layout.OnHost: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a)) => GHC.Read.Read (XMonad.Layout.OnHost.OnHost l1 l2 a)
+ XMonad.Layout.OnHost: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a)) => GHC.Show.Show (XMonad.Layout.OnHost.OnHost l1 l2 a)
+ XMonad.Layout.PerScreen: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a)) => GHC.Read.Read (XMonad.Layout.PerScreen.PerScreen l1 l2 a)
+ XMonad.Layout.PerScreen: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a)) => GHC.Show.Show (XMonad.Layout.PerScreen.PerScreen l1 l2 a)
+ XMonad.Layout.PerWorkspace: instance (GHC.Read.Read (l2 a), GHC.Read.Read (l1 a)) => GHC.Read.Read (XMonad.Layout.PerWorkspace.PerWorkspace l1 l2 a)
+ XMonad.Layout.PerWorkspace: instance (GHC.Show.Show (l2 a), GHC.Show.Show (l1 a)) => GHC.Show.Show (XMonad.Layout.PerWorkspace.PerWorkspace l1 l2 a)
+ XMonad.Layout.SortedLayout: And :: Property -> Property -> Property
+ XMonad.Layout.SortedLayout: ClassName :: String -> Property
+ XMonad.Layout.SortedLayout: Const :: Bool -> Property
+ XMonad.Layout.SortedLayout: Machine :: String -> Property
+ XMonad.Layout.SortedLayout: Not :: Property -> Property
+ XMonad.Layout.SortedLayout: Or :: Property -> Property -> Property
+ XMonad.Layout.SortedLayout: Resource :: String -> Property
+ XMonad.Layout.SortedLayout: Role :: String -> Property
+ XMonad.Layout.SortedLayout: Title :: String -> Property
+ XMonad.Layout.SortedLayout: data Property
+ XMonad.Layout.SortedLayout: instance GHC.Classes.Eq XMonad.Layout.SortedLayout.WindowDescriptor
+ XMonad.Layout.SortedLayout: instance GHC.Classes.Ord XMonad.Layout.SortedLayout.WindowDescriptor
+ XMonad.Layout.SortedLayout: instance GHC.Read.Read (XMonad.Layout.SortedLayout.SortedLayout a)
+ XMonad.Layout.SortedLayout: instance GHC.Read.Read XMonad.Layout.SortedLayout.WindowDescriptor
+ XMonad.Layout.SortedLayout: instance GHC.Show.Show (XMonad.Layout.SortedLayout.SortedLayout a)
+ XMonad.Layout.SortedLayout: instance GHC.Show.Show XMonad.Layout.SortedLayout.WindowDescriptor
+ XMonad.Layout.SortedLayout: instance XMonad.Layout.LayoutModifier.LayoutModifier XMonad.Layout.SortedLayout.SortedLayout Graphics.X11.Types.Window
+ XMonad.Layout.SortedLayout: sorted :: [Property] -> l a -> ModifiedLayout SortedLayout l a
+ XMonad.Layout.SubLayouts: instance (GHC.Read.Read (l a), GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.SubLayouts.Sublayout l a)
+ XMonad.Layout.SubLayouts: instance (GHC.Show.Show (l a), GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.SubLayouts.Sublayout l a)
+ XMonad.Layout.TabBarDecoration: CenteredAt :: Rational -> Rational -> XPPosition
+ XMonad.Layout.TabBarDecoration: [xpCenterY] :: XPPosition -> Rational
+ XMonad.Layout.TabBarDecoration: [xpWidth] :: XPPosition -> Rational
+ XMonad.Layout.ToggleLayouts: instance (GHC.Read.Read (lf a), GHC.Read.Read (lt a)) => GHC.Read.Read (XMonad.Layout.ToggleLayouts.ToggleLayouts lt lf a)
+ XMonad.Layout.ToggleLayouts: instance (GHC.Show.Show (lf a), GHC.Show.Show (lt a)) => GHC.Show.Show (XMonad.Layout.ToggleLayouts.ToggleLayouts lt lf a)
+ XMonad.Layout.ZoomRow: instance (GHC.Classes.Eq (f a), GHC.Classes.Eq a) => GHC.Classes.Eq (XMonad.Layout.ZoomRow.ZoomRow f a)
+ XMonad.Layout.ZoomRow: instance (GHC.Read.Read (f a), GHC.Read.Read a) => GHC.Read.Read (XMonad.Layout.ZoomRow.ZoomRow f a)
+ XMonad.Layout.ZoomRow: instance (GHC.Show.Show (f a), GHC.Show.Show a) => GHC.Show.Show (XMonad.Layout.ZoomRow.ZoomRow f a)
+ XMonad.Prompt: CenteredAt :: Rational -> Rational -> XPPosition
+ XMonad.Prompt: [xpCenterY] :: XPPosition -> Rational
+ XMonad.Prompt: [xpWidth] :: XPPosition -> Rational
+ XMonad.Prompt.Directory: directoryMultipleModes :: String -> (String -> X ()) -> XPType
+ XMonad.Prompt.Input: infixr 1 ?+
+ XMonad.Prompt.Unicode: instance XMonad.Prompt.XPrompt XMonad.Prompt.Unicode.Unicode
+ XMonad.Prompt.Unicode: unicodePrompt :: XPConfig -> X ()
+ XMonad.Prompt.Window: Bring :: WindowPrompt
+ XMonad.Prompt.Window: BringCopy :: WindowPrompt
+ XMonad.Prompt.Window: BringToMaster :: WindowPrompt
+ XMonad.Prompt.Window: Goto :: WindowPrompt
+ XMonad.Prompt.Window: allWindows :: XWindowMap
+ XMonad.Prompt.Window: type XWindowMap = X (Map String Window)
+ XMonad.Prompt.Window: windowPrompt :: XPConfig -> WindowPrompt -> XWindowMap -> X ()
+ XMonad.Prompt.Window: wsWindows :: XWindowMap
+ XMonad.Util.Dzen: infixr 1 >=>
+ XMonad.Util.ExtensibleState: modified :: (ExtensionClass a, Eq a) => (a -> a) -> X Bool
+ XMonad.Util.Font: pixelToString :: (MonadIO m) => Display -> Pixel -> m String
+ XMonad.Util.Loggers: infixl 4 <$>
+ XMonad.Util.Loggers.NamedScratchpad: instance XMonad.Core.ExtensionClass XMonad.Util.Loggers.NamedScratchpad.NSPTrack
+ XMonad.Util.Loggers.NamedScratchpad: nspActive :: [String] -> (String -> String) -> (String -> String) -> Logger
+ XMonad.Util.Loggers.NamedScratchpad: nspActive' :: [NamedScratchpad] -> (String -> String) -> (String -> String) -> Logger
+ XMonad.Util.Loggers.NamedScratchpad: nspActiveIcon :: [Char] -> (String -> String) -> (String -> String) -> Logger
+ XMonad.Util.Loggers.NamedScratchpad: nspTrackHook :: [NamedScratchpad] -> Event -> X All
+ XMonad.Util.Loggers.NamedScratchpad: nspTrackStartup :: [NamedScratchpad] -> X ()
+ XMonad.Util.NoTaskbar: markNoTaskbar :: Window -> X ()
+ XMonad.Util.NoTaskbar: noTaskbar :: ManageHook
+ XMonad.Util.TreeZipper: TreeZipper :: Tree a -> Forest a -> Forest a -> [(Forest a, a, Forest a)] -> TreeZipper a
+ XMonad.Util.TreeZipper: [tz_after] :: TreeZipper a -> Forest a
+ XMonad.Util.TreeZipper: [tz_before] :: TreeZipper a -> Forest a
+ XMonad.Util.TreeZipper: [tz_current] :: TreeZipper a -> Tree a
+ XMonad.Util.TreeZipper: [tz_parents] :: TreeZipper a -> [(Forest a, a, Forest a)]
+ XMonad.Util.TreeZipper: children :: TreeZipper a -> Maybe (TreeZipper a)
+ XMonad.Util.TreeZipper: cursor :: TreeZipper a -> a
+ XMonad.Util.TreeZipper: data TreeZipper a
+ XMonad.Util.TreeZipper: findChild :: (a -> Bool) -> TreeZipper a -> Maybe (TreeZipper a)
+ XMonad.Util.TreeZipper: followPath :: Eq b => (a -> b) -> [b] -> TreeZipper a -> Maybe (TreeZipper a)
+ XMonad.Util.TreeZipper: fromForest :: Forest a -> TreeZipper a
+ XMonad.Util.TreeZipper: getSubForest :: TreeZipper a -> Forest a
+ XMonad.Util.TreeZipper: isFirst :: TreeZipper a -> Bool
+ XMonad.Util.TreeZipper: isLast :: TreeZipper a -> Bool
+ XMonad.Util.TreeZipper: isLeaf :: TreeZipper a -> Bool
+ XMonad.Util.TreeZipper: isRoot :: TreeZipper a -> Bool
+ XMonad.Util.TreeZipper: nextChild :: TreeZipper a -> Maybe (TreeZipper a)
+ XMonad.Util.TreeZipper: nodeDepth :: TreeZipper a -> Int
+ XMonad.Util.TreeZipper: nodeIndex :: TreeZipper a -> Int
+ XMonad.Util.TreeZipper: parent :: TreeZipper a -> Maybe (TreeZipper a)
+ XMonad.Util.TreeZipper: previousChild :: TreeZipper a -> Maybe (TreeZipper a)
+ XMonad.Util.TreeZipper: rootNode :: TreeZipper a -> TreeZipper a
+ XMonad.Util.TreeZipper: toForest :: TreeZipper a -> Forest a
+ XMonad.Util.Ungrab: unGrab :: X ()
+ XMonad.Util.XUtils: pixelToString :: (MonadIO m) => Display -> Pixel -> m String
- XMonad.Config.Dmwit: atSchool :: MonadIO m => r -> r -> m r
+ XMonad.Config.Dmwit: atSchool :: MonadIO m => b -> b -> m b
- XMonad.Config.Dmwit: parse :: (Floating a, Read a) => String -> a
+ XMonad.Config.Dmwit: parse :: (Read a, Floating a) => String -> a
- XMonad.Layout.Groups.Wmii: wmii :: Shrinker s => s -> Theme -> Groups (ModifiedLayout Rename (ModifiedLayout (Decoration TabbedDecoration s) (Ignore ChangeLayout (Ignore JumpToLayout (ModifiedLayout UnEscape (NewSelect (ModifiedLayout Rename Tall) (NewSelect (ModifiedLayout Rename Simplest) Full))))))) (ZoomRow GroupEQ) Window
+ XMonad.Layout.Groups.Wmii: wmii :: Shrinker t => t -> Theme -> Groups (ModifiedLayout Rename (ModifiedLayout (Decoration TabbedDecoration t) (Ignore ChangeLayout (Ignore JumpToLayout (ModifiedLayout UnEscape (NewSelect (ModifiedLayout Rename Tall) (NewSelect (ModifiedLayout Rename Simplest) Full))))))) (ZoomRow GroupEQ) Window
- XMonad.Layout.LayoutBuilder: layoutAll :: (Read a, Eq a, LayoutClass l1 a) => SubBox -> l1 a -> LayoutN l1 Full a
+ XMonad.Layout.LayoutBuilder: layoutAll :: (Read a, Eq a, LayoutClass l1 a) => SubBox -> l1 a -> LayoutB 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: layoutN :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) => Int -> SubBox -> Maybe SubBox -> l1 a -> LayoutB l2 l3 p a -> LayoutB l1 (LayoutB l2 l3 p) () 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: layoutR :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) => Rational -> Rational -> SubBox -> Maybe SubBox -> l1 a -> LayoutB l2 l3 p a -> LayoutB l1 (LayoutB l2 l3 p) p a
- XMonad.Layout.LayoutBuilderP: layoutAll :: (Read a, Eq a, LayoutClass l1 a, Predicate p a) => SubBox -> l1 a -> LayoutP p l1 Full a
+ XMonad.Layout.LayoutBuilderP: layoutAll :: forall l1 p a. (Read a, Eq a, LayoutClass l1 a, Predicate p a) => SubBox -> l1 a -> LayoutP p l1 Full a
- XMonad.Prompt: XPC :: String -> String -> String -> String -> String -> String -> !Dimension -> XPPosition -> !Bool -> !Dimension -> Maybe Dimension -> !Int -> ([String] -> [String]) -> Map (KeyMask, KeySym) (XP ()) -> KeySym -> KeySym -> String -> Maybe Int -> Bool -> (String -> String -> Bool) -> XPConfig
+ XMonad.Prompt: XPC :: String -> String -> String -> String -> String -> String -> !Dimension -> XPPosition -> !Bool -> !Dimension -> Maybe Dimension -> !Int -> ([String] -> [String]) -> Map (KeyMask, KeySym) (XP ()) -> (KeyMask, KeySym) -> KeySym -> String -> Maybe Int -> Bool -> (String -> String -> Bool) -> XPConfig
- XMonad.Prompt: [completionKey] :: XPConfig -> KeySym
+ XMonad.Prompt: [completionKey] :: XPConfig -> (KeyMask, KeySym)
- XMonad.Util.EZConfig: additionalKeys :: XConfig a -> [((ButtonMask, KeySym), X ())] -> XConfig a
+ XMonad.Util.EZConfig: additionalKeys :: XConfig a -> [((KeyMask, KeySym), X ())] -> XConfig a
- XMonad.Util.EZConfig: removeKeys :: XConfig a -> [(ButtonMask, KeySym)] -> XConfig a
+ XMonad.Util.EZConfig: removeKeys :: XConfig a -> [(KeyMask, KeySym)] -> XConfig a

Files

CHANGES.md view
@@ -1,5 +1,92 @@ # Change Log / Release Notes +## 0.13 (February 10, 2017)++### Breaking Changes++  * The type of `completionKey` (of `XPConfig` record) has been+    changed from `KeySym` to `(KeyMask, KeySym)`. The default value+    for this is still bound to the `Tab` key.++  * New constructor `CenteredAt Rational Rational` added for+    `XMonad.Prompt.XPPosition`.++  * `XMonad.Prompt` now stores its history file in the XMonad cache+    directory in a file named `prompt-history`.++### New Modules++  * `XMonad.Layout.SortedLayout`++    A new LayoutModifier that sorts a given layout by a list of+    properties. The order of properties in the list determines+    the order of windows in the final layout. Any unmatched windows+    go to the end of the order.++  * `XMonad.Prompt.Unicode`++    A prompt to search a unicode character by its name, and put it into the+    clipboard.++  * `XMonad.Util.Ungrab`++    Release xmonad's keyboard and pointer grabs immediately, so+    screen grabbers and lock utilities, etc. will work. Replaces+    the short sleep hackaround.++  * `XMonad.Util.Loggers.NamedScratchpad`++    A collection of Loggers (see `XMonad.Util.Loggers`) for NamedScratchpads+    (see `XMonad.Util.NamedScratchpad`).++  * `XMonad.Util.NoTaskbar`++    Utility function and `ManageHook` to mark a window to be ignored by+    EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since+    you will usually be taken to the `NSP` workspace by them.++### Bug Fixes and Minor Changes++  * `XMonad.Hooks.ManageDocks`,++    - Fix a very annoying bug where taskbars/docs would be+      covered by windows.++    - Also fix a bug that caused certain Gtk and Qt application to+      have issues displaying menus and popups.++  * `XMonad.Layout.LayoutBuilder`++    Merge all functionality from `XMonad.Layout.LayoutBuilderP` into+    `XMonad.Layout.LayoutBuilder`.++  * `XMonad.Actions.WindowGo`++    - Fix `raiseNextMaybe` cycling between 2 workspaces only.++  * `XMonad.Actions.UpdatePointer`++    - Fix bug when cursor gets stuck in one of the corners.++  * `XMonad.Actions.Submap`++    Establish pointer grab to avoid freezing X, when button press occurs after+    submap key press.  And terminate submap at button press in the same way,+    as we do for wrong key press.++  * `XMonad.Actions.DynamicProjects`++    - Switching away from a dynamic project that contains no windows+      automatically deletes that project's workspace.++      The project itself was already being deleted, this just deletes+      the workspace created for it as well.++    - Added function to change the working directory (`changeProjectDirPrompt`)++    - All of the prompts are now multiple mode prompts.  Try using the+      `changeModeKey` in a prompt and see what happens!+ ## 0.12 (December 14, 2015)  ### Breaking Changes@@ -12,7 +99,7 @@     | < 0.12                              |   >= 0.12                        |     |-------------------------------------|----------------------------------|     | `updatePointer Nearest`             | `updatePointer (0.5, 0.5) (1,1)` |-    | `updatePointer (Relative x y)`      | `updatePointer (x,y) (1,1)`      |+    | `updatePointer (Relative x y)`      | `updatePointer (x,y) (0,0)`      |     | `updatePointer (TowardsCentre x y)` | `updatePointer (0.5,0.5) (x,y)`  |  ### New Modules
README.md view
@@ -1,5 +1,7 @@ # xmonad-contrib: Third Party Extensions to the xmonad Window Manager +[![Build Status](https://travis-ci.org/xmonad/xmonad-contrib.svg?branch=master)](https://travis-ci.org/xmonad/xmonad-contrib)+ You need the ghc compiler and xmonad window manager installed in order to use these extensions. 
XMonad/Actions/CycleWS.hs view
@@ -239,6 +239,7 @@             | NonEmptyWS  -- ^ cycle through non-empty workspaces             | HiddenWS    -- ^ cycle through non-visible workspaces             | HiddenNonEmptyWS  -- ^ cycle through non-empty non-visible workspaces+            | HiddenEmptyWS  -- ^ cycle through empty non-visible workspaces             | AnyWS       -- ^ cycle through all workspaces             | WSTagGroup Char                           -- ^ cycle through workspaces in the same group, the@@ -257,6 +258,9 @@ wsTypeToPred HiddenNonEmptyWS  = do ne <- wsTypeToPred NonEmptyWS                                     hi <- wsTypeToPred HiddenWS                                     return (\w -> hi w && ne w)+wsTypeToPred HiddenEmptyWS  = do ne <- wsTypeToPred EmptyWS+                                 hi <- wsTypeToPred HiddenWS+                                 return (\w -> hi w && ne w) wsTypeToPred AnyWS      = return (const True) wsTypeToPred (WSTagGroup sep) = do cur <- (groupName.workspace.current) `fmap` gets windowset                                    return $ (cur ==).groupName
XMonad/Actions/DynamicProjects.hs view
@@ -31,6 +31,7 @@        , switchProjectPrompt        , shiftToProjectPrompt        , renameProjectPrompt+       , changeProjectDirPrompt           -- * Helper Functions        , switchProject@@ -43,6 +44,7 @@ -------------------------------------------------------------------------------- import Control.Applicative ((<|>)) import Control.Monad (when, unless)+import Data.Char (isSpace) import Data.List (sort, union, stripPrefix) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map@@ -52,8 +54,7 @@ import XMonad import XMonad.Actions.DynamicWorkspaces import XMonad.Prompt-import XMonad.Prompt.Directory (directoryPrompt)-import XMonad.Prompt.Workspace (Wor(..))+import XMonad.Prompt.Directory import qualified XMonad.StackSet as W import qualified XMonad.Util.ExtensibleState as XS @@ -143,24 +144,66 @@   initialValue = ProjectState Map.empty Nothing  --------------------------------------------------------------------------------+-- Internal types for working with XPrompt.+data ProjectPrompt = ProjectPrompt ProjectMode [ProjectName]+data ProjectMode = SwitchMode | ShiftMode | RenameMode | DirMode++instance XPrompt ProjectPrompt where+  showXPrompt (ProjectPrompt submode _) =+    case submode of+      SwitchMode -> "Switch or Create Project: "+      ShiftMode  -> "Send Window to Project: "+      RenameMode -> "New Project Name: "+      DirMode    -> "Change Project Directory: "++  completionFunction (ProjectPrompt RenameMode _) = return . (:[])+  completionFunction (ProjectPrompt DirMode _) =+    let xpt = directoryMultipleModes "" (const $ return ())+    in completionFunction xpt+  completionFunction (ProjectPrompt _ ns) = mkComplFunFromList' ns++  modeAction (ProjectPrompt SwitchMode _) buf auto = do+    let name = if null auto then buf else auto+    ps <- XS.gets projects++    case Map.lookup name ps of+      Just p              -> switchProject p+      Nothing | null name -> return ()+              | otherwise -> switchProject (defProject name)++  modeAction (ProjectPrompt ShiftMode _) buf auto = do+    let name = if null auto then buf else auto+    ps <- XS.gets projects+    shiftToProject . fromMaybe (defProject name) $ Map.lookup name ps++  modeAction (ProjectPrompt RenameMode _) name _ =+    when (not (null name) && not (all isSpace name)) $ do+      renameWorkspaceByName name+      modifyProject (\p -> p { projectName = name })++  modeAction (ProjectPrompt DirMode _) buf auto = do+    let dir = if null auto then buf else auto+    modifyProject (\p -> p { projectDirectory = dir })++-------------------------------------------------------------------------------- -- | Add dynamic projects support to the given config. dynamicProjects :: [Project] -> XConfig a -> XConfig a dynamicProjects ps c =-  c { startupHook     = startupHook c <> dynamicProjectsStartupHook ps-    , logHook         = logHook c     <> dynamicProjectsLogHook+  c { startupHook     = dynamicProjectsStartupHook ps <> startupHook c+    , logHook         = dynamicProjectsLogHook        <> logHook c     }  -------------------------------------------------------------------------------- -- | Log hook for tracking workspace changes. dynamicProjectsLogHook :: X () dynamicProjectsLogHook = do-  name  <- gets (W.tag . W.workspace . W.current . windowset)-  state <- XS.get+  name   <- gets (W.tag . W.workspace . W.current . windowset)+  xstate <- XS.get -  unless (Just name == previousProject state) $ do-    XS.put (state {previousProject = Just name})+  unless (Just name == previousProject xstate) $ do+    XS.put (xstate {previousProject = Just name})     activateProject . fromMaybe (defProject name) $-      Map.lookup name (projects state)+      Map.lookup name (projects xstate)  -------------------------------------------------------------------------------- -- | Start-up hook for recording configured projects.@@ -199,6 +242,21 @@   return $ fromMaybe (defProject name) proj  --------------------------------------------------------------------------------+-- | Modify the current project using a pure function.+modifyProject :: (Project -> Project) -> X ()+modifyProject f = do+  p  <- currentProject+  ps <- XS.gets projects++  -- If a project is renamed to match another project, the old project+  -- will be removed and replaced with this one.+  let new = f p+      ps' = Map.insert (projectName new) new $ Map.delete (projectName p) ps++  XS.modify $ \s -> s {projects = ps'}+  activateProject new++-------------------------------------------------------------------------------- -- | Switch to the given project. switchProject :: Project -> X () switchProject p = do@@ -210,7 +268,8 @@    -- If the project we are switching away from has no windows, and   -- it's a dynamic project, remove it from the configuration.-  when (null ws && isNothing (projectStartHook oldp)) $+  when (null ws && isNothing (projectStartHook oldp)) $ do+    removeWorkspaceByTag name -- also remove the old workspace     XS.modify (\s -> s {projects = Map.delete name $ projects s})    appendWorkspace (projectName p)@@ -219,22 +278,11 @@ -- | Prompt for a project name and then switch to it.  Automatically -- creates a project if a new name is returned from the prompt. switchProjectPrompt :: XPConfig -> X ()-switchProjectPrompt c = projectPrompt c switch-  where-    switch :: ProjectTable -> ProjectName -> X ()-    switch ps name = case Map.lookup name ps of-      Just p              -> switchProject p-      Nothing | null name -> return ()-              | otherwise -> directoryPrompt dirC "Project Dir: " (mkProject name)--    dirC :: XPConfig-    dirC = c { alwaysHighlight = False } -- Fix broken tab completion.--    mkProject :: ProjectName -> FilePath -> X ()-    mkProject name dir = do-      let p = Project name dir Nothing-      XS.modify $ \s -> s {projects = Map.insert name p $ projects s}-      switchProject p+switchProjectPrompt = projectPrompt [ SwitchMode+                                    , ShiftMode+                                    , RenameMode+                                    , DirMode+                                    ]  -------------------------------------------------------------------------------- -- | Shift the currently focused window to the given project.@@ -247,40 +295,44 @@ -- | Prompts for a project name and then shifts the currently focused -- window to that project. shiftToProjectPrompt :: XPConfig -> X ()-shiftToProjectPrompt c = projectPrompt c go-  where-    go :: ProjectTable -> ProjectName -> X ()-    go ps name = shiftToProject . fromMaybe (defProject name) $-                 Map.lookup name ps+shiftToProjectPrompt = projectPrompt [ ShiftMode+                                     , RenameMode+                                     , SwitchMode+                                     , DirMode+                                     ]  --------------------------------------------------------------------------------+-- | Rename the current project.+renameProjectPrompt :: XPConfig -> X ()+renameProjectPrompt = projectPrompt [ RenameMode+                                    , DirMode+                                    , SwitchMode+                                    , ShiftMode+                                    ]++--------------------------------------------------------------------------------+-- | Change the working directory used for the current project.+--+-- NOTE: This will only affect new processed started in this project.+-- Existing processes will maintain the previous working directory.+changeProjectDirPrompt :: XPConfig -> X ()+changeProjectDirPrompt = projectPrompt [ DirMode+                                       , SwitchMode+                                       , ShiftMode+                                       , RenameMode+                                       ]++-------------------------------------------------------------------------------- -- | Prompt for a project name.-projectPrompt :: XPConfig -> (ProjectTable -> ProjectName -> X ()) -> X ()-projectPrompt c f = do+projectPrompt :: [ProjectMode] -> XPConfig -> X ()+projectPrompt submodes c = do   ws <- map W.tag `fmap` gets (W.workspaces . windowset)   ps <- XS.gets projects    let names = sort (Map.keys ps `union` ws)-      label = "Switch or Create Project: "--  mkXPrompt (Wor label) c (mkComplFunFromList' names) (f ps)------------------------------------------------------------------------------------- | Rename the current project.-renameProjectPrompt :: XPConfig -> X ()-renameProjectPrompt c = mkXPrompt (Wor "New Project Name: ") c (return . (:[])) go-  where-    go :: String -> X ()-    go name = do-      p  <- currentProject-      ps <- XS.gets projects-      renameWorkspaceByName name--      let p'  = fromMaybe (p { projectName = name }) $ Map.lookup name ps-          ps' = Map.insert name p' $ Map.delete (projectName p) ps+      modes = map (\m -> XPT $ ProjectPrompt m names) submodes -      XS.modify $ \s -> s {projects = ps'}-      activateProject p'+  mkXPromptWithModes modes c  -------------------------------------------------------------------------------- -- | Activate a project by updating the working directory and
XMonad/Actions/DynamicWorkspaces.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveDataTypeable #-}+ ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Actions.DynamicWorkspaces@@ -21,13 +23,16 @@                                          removeWorkspace,                                          removeWorkspaceByTag,                                          removeEmptyWorkspace,+                                         removeEmptyWorkspaceByTag,                                          removeEmptyWorkspaceAfter,                                          removeEmptyWorkspaceAfterExcept,                                          addHiddenWorkspace, addHiddenWorkspaceAt,                                          withWorkspace,                                          selectWorkspace, renameWorkspace,                                          renameWorkspaceByName,-                                         toNthWorkspace, withNthWorkspace+                                         toNthWorkspace, withNthWorkspace,+                                         setWorkspaceIndex, withWorkspaceIndex,+                                         WorkspaceIndex                                        ) where  import XMonad hiding (workspaces)@@ -38,6 +43,8 @@ import Data.List (find) import Data.Maybe (isNothing) import Control.Monad (when)+import qualified Data.Map.Strict as Map+import qualified XMonad.Util.ExtensibleState as XS  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:@@ -53,19 +60,57 @@ -- >   , ((modm .|. shiftMask, xK_m      ), withWorkspace def (windows . copy)) -- >   , ((modm .|. shiftMask, xK_r      ), renameWorkspace def) ----- > -- mod-[1..9]       %! Switch to workspace N--- > -- mod-shift-[1..9] %! Move client to workspace N+-- > -- mod-[1..9]       %! Switch to workspace N in the list of workspaces+-- > -- mod-shift-[1..9] %! Move client to workspace N in the list of workspaces -- >    ++ -- >    zip (zip (repeat (modm)) [xK_1..xK_9]) (map (withNthWorkspace W.greedyView) [0..]) -- >    ++ -- >    zip (zip (repeat (modm .|. shiftMask)) [xK_1..xK_9]) (map (withNthWorkspace W.shift) [0..]) --+-- Alternatively, you can associate indexes (which don't depend of the+-- workspace list order) to workspaces by using following keybindings:+--+-- > -- mod-[1..9]         %! Switch to workspace of index N+-- > -- mod-control-[1..9] %! Set index N to the current workspace+-- >    +++-- >    zip (zip (repeat (modm)) [xK_1..xK_9]) (map (withWorkspaceIndex W.greedyView) [1..])+-- >    +++-- >    zip (zip (repeat (modm .|. controlMask)) [xK_1..xK_9]) (map (setWorkspaceIndex) [1..])+-- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". See also the documentation for -- "XMonad.Actions.CopyWindow", 'windows', 'shift', and 'XPConfig'. +type WorkspaceTag = String+-- | The workspace index is mapped to a workspace tag by the user and+-- can be updated.+type WorkspaceIndex  = Int +-- | Internal dynamic project state that stores a mapping between+--   workspace indexes and workspace tags.+data DynamicWorkspaceState = DynamicWorkspaceState {workspaceIndexMap :: Map.Map WorkspaceIndex WorkspaceTag}+  deriving (Typeable, Read, Show) +instance ExtensionClass DynamicWorkspaceState where+  initialValue = DynamicWorkspaceState Map.empty+  extensionType = PersistentExtension++-- | Set the index of the current workspace.+setWorkspaceIndex :: WorkspaceIndex -> X ()+setWorkspaceIndex widx = do+  wtag  <- gets (currentTag . windowset)+  wmap <- XS.gets workspaceIndexMap+  XS.modify $ \s -> s {workspaceIndexMap = Map.insert widx wtag wmap}++withWorkspaceIndex :: (String -> WindowSet -> WindowSet) -> WorkspaceIndex -> X ()+withWorkspaceIndex job widx = do+  wtag <- ilookup widx+  maybe (return ()) (windows . job) wtag+    where+      ilookup :: WorkspaceIndex -> X (Maybe WorkspaceTag)+      ilookup idx = Map.lookup idx `fmap` XS.gets workspaceIndexMap++ mkCompl :: [String] -> String -> IO [String] mkCompl l s = return $ filter (\x -> take (length s) x == s) l @@ -81,10 +126,15 @@ renameWorkspace conf = workspacePrompt conf renameWorkspaceByName  renameWorkspaceByName :: String -> X ()-renameWorkspaceByName w = windows $ \s -> let sett wk = wk { tag = w }-                                              setscr scr = scr { workspace = sett $ workspace scr }-                                              sets q = q { current = setscr $ current q }-                                          in sets $ removeWorkspace' w s+renameWorkspaceByName w = do old  <- gets (currentTag . windowset)+			     windows $ \s -> let sett wk = wk { tag = w }+						 setscr scr = scr { workspace = sett $ workspace scr }+						 sets q = q { current = setscr $ current q }+                                             in sets $ removeWorkspace' w s+			     updateIndexMap old w+  where updateIndexMap old new = do+          wmap <- XS.gets workspaceIndexMap+          XS.modify $ \s -> s {workspaceIndexMap = Map.map (\t -> if t == old then new else t) wmap}  toNthWorkspace :: (String -> X ()) -> Int -> X () toNthWorkspace job wnum = do sort <- getSortByIndex@@ -128,7 +178,7 @@ addWorkspacePrompt :: XPConfig -> X () addWorkspacePrompt conf = mkXPrompt (Wor "New workspace name: ") conf (const (return [])) addWorkspace --- | Prompt for the name of a new workspace, appending it to the end of the list of workspaces +-- | Prompt for the name of a new workspace, appending it to the end of the list of workspaces --   if it does not already exist, and switch to it. appendWorkspacePrompt :: XPConfig -> X () appendWorkspacePrompt conf = mkXPrompt (Wor "New workspace name: ") conf (const (return [])) appendWorkspace
XMonad/Actions/FocusNth.hs view
@@ -14,7 +14,8 @@ module XMonad.Actions.FocusNth (                  -- * Usage                  -- $usage-                 focusNth,focusNth') where+                 focusNth,focusNth',+                 swapNth,swapNth') where  import XMonad.StackSet import XMonad@@ -40,6 +41,17 @@ focusNth' :: Int -> Stack a -> Stack a focusNth' n s@(Stack _ ls rs) | (n < 0) || (n > length(ls) + length(rs)) = s                               | otherwise = listToStack n (integrate s)++-- | Swap current window with nth. Focus stays in the same position+swapNth :: Int -> X ()+swapNth = windows . modify' . swapNth'++swapNth' :: Int -> Stack a -> Stack a+swapNth' n s@(Stack c l r)+  | (n < 0) || (n > length l + length r) || (n == length l) = s+  | n < length l = let (nl, nc:nr) = splitAt (length l - n - 1) l in Stack nc (nl ++ c : nr) r+  | otherwise    = let (nl, nc:nr) = splitAt (n - length l - 1) r in Stack nc l (nl ++ c : nr)+                                                                            listToStack :: Int -> [a] -> Stack a listToStack n l = Stack t ls rs
XMonad/Actions/GridSelect.hs view
@@ -653,7 +653,7 @@     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+    io $ grabPointer dpy win True buttonReleaseMask grabModeAsync grabModeAsync none none currentTime     font <- initXMF (gs_font gsconfig)     let screenWidth = toInteger $ rect_width scr         screenHeight = toInteger $ rect_height scr@@ -682,6 +682,7 @@     liftIO $ do       unmapWindow dpy win       destroyWindow dpy win+      ungrabPointer dpy currentTime       sync dpy False     releaseXMF font     return selectedElement
XMonad/Actions/Navigation2D.hs view
@@ -43,6 +43,7 @@                                    , Navigation2D                                    , lineNavigation                                    , centerNavigation+                                   , hybridNavigation                                    , fullScreenRect                                    , singleWindowRect                                    , switchLayer@@ -74,10 +75,11 @@ -- natural but may make it impossible to navigate to a given window from the -- current window, particularly in the floating layer.  /Center navigation/ -- feels less natural in certain situations but ensures that all windows can be--- reached without the need to involve the mouse.  Navigation2D allows different--- navigation strategies to be used in the two layers and allows customization--- of the navigation strategy for the tiled layer based on the layout currently--- in effect.+-- reached without the need to involve the mouse. A third option is to use+-- /Hybrid navigation/, which automatically chooses between the two whenever+-- navigation is attempted.  Navigation2D allows different navigation strategies+-- to be used in the two layers and allows customization of the navigation strategy+-- for the tiled layer based on the layout currently in effect. -- -- You can use this module with (a subset of) the following in your @~\/.xmonad\/xmonad.hs@: --@@ -316,6 +318,13 @@ centerNavigation :: Navigation2D centerNavigation = N 2 doCenterNavigation +-- | Hybrid navigation. This attempts Line navigation, then falls back on Center+-- navigation if it does not find any suitable target windows. This is useful since+-- Line navigation tends to fail on gaps, but provides more intuitive motions+-- when it succeeds—provided there are no floating windows.+hybridNavigation :: Navigation2D+hybridNavigation = N 2 doHybridNavigation+ -- | Stores the configuration of directional navigation. The 'Default' instance -- uses line navigation for the tiled layer and for navigation between screens, -- and center navigation for the float layer.  No custom navigation strategies@@ -757,6 +766,13 @@       | otherwise                       = wp -- q is farther away from the bottom ray than p                                              -- or it has the same distance but comes later                                              -- in the window stack++-- | Implements Hybrid navigation. This attempts Line navigation first,+-- then falls back on Center navigation if it finds no suitable target window.+doHybridNavigation :: Eq a => Direction2D -> Rect a -> [Rect a] -> Maybe a+doHybridNavigation = applyToBoth (<|>) doLineNavigation doCenterNavigation+    where+        applyToBoth f g h a b c = f (g a b c) (h a b c)  -- | Swaps the current window with the window given as argument swap :: Window -> WindowSet -> WindowSet
XMonad/Actions/Search.hs view
@@ -284,7 +284,7 @@ amazon, alpha, codesearch, deb, debbts, debpts, dictionary, google, hackage, hoogle,   images, imdb, isohunt, lucky, maps, mathworld, openstreetmap, scholar, stackage, thesaurus, vocabulary, wayback, wikipedia, wiktionary,   youtube, duckduckgo :: SearchEngine-amazon        = searchEngine "amazon"        "http://www.amazon.com/exec/obidos/external-search?index=all&keyword="+amazon        = searchEngine "amazon"        "http://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=" alpha         = searchEngine "alpha"         "http://www.wolframalpha.com/input/?i=" codesearch    = searchEngine "codesearch"    "http://www.google.com/codesearch?q=" deb           = searchEngine "deb"           "http://packages.debian.org/"
XMonad/Actions/Submap.hs view
@@ -16,9 +16,11 @@                              -- * Usage                              -- $usage                              submap,-                             submapDefault+                             submapDefault,+                             submapDefaultWithKey                             ) where import Data.Bits+import Data.Maybe (fromMaybe) import XMonad hiding (keys) import qualified Data.Map as M import Control.Monad.Fix (fix)@@ -58,25 +60,38 @@ --   corresponding action, or does nothing if the key is not found in --   the map. submap :: M.Map (KeyMask, KeySym) (X ()) -> X ()-submap keys = submapDefault (return ()) keys+submap = submapDefault (return ())  -- | Like 'submap', but executes a default action if the key did not match. submapDefault :: X () -> M.Map (KeyMask, KeySym) (X ()) -> X ()-submapDefault defAction keys = do+submapDefault = submapDefaultWithKey . const++-- | Like 'submapDefault', but sends the unmatched key to the default+-- action as argument.+submapDefaultWithKey :: ((KeyMask, KeySym) -> X ())+                     -> M.Map (KeyMask, KeySym) (X ())+                     -> X ()+submapDefaultWithKey defAction keys = do     XConf { theRoot = root, display = d } <- ask      io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime+    io $ grabPointer d root False buttonPressMask grabModeAsync grabModeAsync+                     none none currentTime      (m, s) <- io $ allocaXEvent $ \p -> fix $ \nextkey -> do-        maskEvent d keyPressMask p-        KeyEvent { ev_keycode = code, ev_state = m } <- getEvent p-        keysym <- keycodeToKeysym d code 0-        if isModifierKey keysym-            then nextkey-            else return (m, keysym)+        maskEvent d (keyPressMask .|. buttonPressMask) p+        ev <- getEvent p+        case ev of+          KeyEvent { ev_keycode = code, ev_state = m } -> do+            keysym <- keycodeToKeysym d code 0+            if isModifierKey keysym+                then nextkey+                else return (m, keysym)+          _ -> return (0, 0)     -- Remove num lock mask and Xkb group state bits     m' <- cleanMask $ m .&. ((1 `shiftL` 12) - 1) +    io $ ungrabPointer d currentTime     io $ ungrabKeyboard d currentTime -    maybe defAction id (M.lookup (m', s) keys)+    fromMaybe (defAction (m', s)) (M.lookup (m', s) keys)
+ XMonad/Actions/TreeSelect.hs view
@@ -0,0 +1,657 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE RecordWildCards #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.TreeSelect+-- Copyright   :  (c) Tom Smeets <tom.tsmeets@gmail.com>+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Tom Smeets <tom.tsmeets@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+--+-- TreeSelect displays your workspaces or actions in a Tree-like format.+-- You can select the desired workspace/action with the cursor or hjkl keys.+--+-- This module is fully configurable and very useful if you like to have a+-- lot of workspaces.+--+-- Only the nodes up to the currently selected are displayed.+-- This will be configurable in the near future by changing 'ts_hidechildren' to @False@, this is not yet implemented.+--+-- <<https://wiki.haskell.org/wikiupload/thumb/0/0b/Treeselect-Workspace.png/800px-Treeselect-Workspace.png>>+--+-----------------------------------------------------------------------------+module XMonad.Actions.TreeSelect+    (+      -- * Usage+      -- $usage+      treeselectWorkspace+    , toWorkspaces+    , treeselectAction++      -- * Configuring+      -- $config+    , Pixel+      -- $pixel++    , TSConfig(..)+    , tsDefaultConfig++      -- * Navigation+      -- $navigation+    , defaultNavigation+    , select+    , cancel+    , moveParent+    , moveChild+    , moveNext+    , movePrev+    , moveHistBack+    , moveHistForward+    , moveTo++      -- * Advanced usage+      -- $advusage+    , TSNode(..)+    , treeselect+    , treeselectAt+    ) where++import Control.Applicative+import Control.Monad.Reader+import Control.Monad.State+import Data.List (find)+import Data.Maybe+import Data.Tree+import Foreign+import System.IO+import System.Posix.Process (forkProcess, executeFile)+import XMonad hiding (liftX)+import XMonad.StackSet as W+import XMonad.Util.Font+import XMonad.Util.NamedWindows+import XMonad.Util.TreeZipper+import XMonad.Hooks.WorkspaceHistory+import qualified Data.Map as M++#ifdef XFT+import Graphics.X11.Xft+import Graphics.X11.Xrender+#endif++-- $usage+--+-- These imports are used in the following example+--+-- > import Data.Tree+-- > import XMonad.Actions.TreeSelect+-- > import XMonad.Hooks.WorkspaceHistory+-- > import qualified XMonad.StackSet as W+--+-- For selecting Workspaces, you need to define them in a tree structure using 'Data.Tree.Node' instead of just a standard list+--+-- Here is an example workspace-tree+--+-- > myWorkspaces :: Forest String+-- > myWorkspaces = [ Node "Browser" [] -- a workspace for your browser+-- >                , Node "Home"       -- for everyday activity's+-- >                    [ Node "1" []   --  with 4 extra sub-workspaces, for even more activity's+-- >                    , Node "2" []+-- >                    , Node "3" []+-- >                    , Node "4" []+-- >                    ]+-- >                , Node "Programming" -- for all your programming needs+-- >                    [ Node "Haskell" []+-- >                    , Node "Docs"    [] -- documentation+-- >                    ]+-- >                ]+--+-- Then add it to your 'XMonad.Core.workspaces' using the 'toWorkspaces' function.+--+-- Optionally, if you add 'workspaceHistoryHook' to your 'logHook' you can use the \'o\' and \'i\' keys to select from previously-visited workspaces+--+-- > xmonad $ defaultConfig { ...+-- >                        , workspaces = toWorkspaces myWorkspaces+-- >                        , logHook = workspaceHistoryHook+-- >                        }+--+-- After that you still need to bind buttons to 'treeselectWorkspace' to start selecting a workspaces and moving windows+--+-- you could bind @Mod-f@ to switch workspace+--+-- >  , ((modMask, xK_f), treeselectWorkspace myTreeConf myWorkspaces W.greedyView)+--+-- and bind @Mod-Shift-f@ to moving the focused windows to a workspace+--+-- >  , ((modMask .|. shiftMask, xK_f), treeselectWorkspace myTreeConf myWorkspaces W.shift)++-- $config+-- The selection menu is very configurable, you can change the font, all colors and the sizes of the boxes.+--+-- The default config defined as 'tsDefaultConfig'+--+-- > tsDefaultConfig = TSConfig { ts_hidechildren = True+-- >                            , ts_background   = 0xc0c0c0c0+-- >                            , ts_font         = "xft:Sans-16"+-- >                            , ts_node         = (0xff000000, 0xff50d0db)+-- >                            , ts_nodealt      = (0xff000000, 0xff10b8d6)+-- >                            , ts_highlight    = (0xffffffff, 0xffff0000)+-- >                            , ts_extra        = 0xff000000+-- >                            , ts_node_width   = 200+-- >                            , ts_node_height  = 30+-- >                            , ts_originX      = 0+-- >                            , ts_originY      = 0+-- >                            , ts_indent       = 80+-- >                            , ts_navigate     = defaultNavigation+-- >                            }++-- $pixel+--+-- The 'Pixel' Color format is in the form of @0xaarrggbb@+--+-- Note that transparency is only supported if you have a window compositor running like <https://github.com/chjj/compton compton>+--+-- Some Examples:+--+-- @+-- white       = 0xffffffff+-- black       = 0xff000000+-- red         = 0xffff0000+-- blue        = 0xff00ff00+-- green       = 0xff0000ff+-- transparent = 0x00000000+-- @++-- $navigation+--+-- Keybindings for navigations can also be modified+--+-- This is the definition of 'defaultNavigation'+--+-- > defaultNavigation :: M.Map (KeyMask, KeySym) (TreeSelect a (Maybe a))+-- > defaultNavigation = M.fromList+-- >     [ ((0, xK_Escape), cancel)+-- >     , ((0, xK_Return), select)+-- >     , ((0, xK_space),  select)+-- >     , ((0, xK_Up),     movePrev)+-- >     , ((0, xK_Down),   moveNext)+-- >     , ((0, xK_Left),   moveParent)+-- >     , ((0, xK_Right),  moveChild)+-- >     , ((0, xK_k),      movePrev)+-- >     , ((0, xK_j),      moveNext)+-- >     , ((0, xK_h),      moveParent)+-- >     , ((0, xK_l),      moveChild)+-- >     , ((0, xK_o),      moveHistBack)+-- >     , ((0, xK_i),      moveHistForward)+-- >     ]++-- $advusage+-- This module can also be used to select any other action++-- | Extensive configuration for displaying the tree.+--+-- This class also has a 'Default' instance+data TSConfig a = TSConfig { ts_hidechildren :: Bool -- ^ when enabled, only the parents (and their first children) of the current node will be shown (This feature is not yet implemented!)+                           , ts_background :: Pixel -- ^ background color filling the entire screen.++                           , ts_font :: String -- ^ XMF font for drawing the node name extra text++                           , ts_node      :: (Pixel, Pixel) -- ^ node foreground (text) and background color when not selected+                           , ts_nodealt   :: (Pixel, Pixel) -- ^ every other node will use this color instead of 'ts_node'+                           , ts_highlight :: (Pixel, Pixel) -- ^ node foreground (text) and background color when selected++                           , ts_extra :: Pixel -- ^ extra text color++                           , ts_node_width   :: Int -- ^ node width in pixels+                           , ts_node_height  :: Int -- ^ node height in pixels+                           , ts_originX :: Int -- ^ tree X position on the screen in pixels+                           , ts_originY :: Int -- ^ tree Y position on the screen in pixels++                           , ts_indent :: Int -- ^ indentation amount for each level in pixels++                           , ts_navigate :: M.Map (KeyMask, KeySym) (TreeSelect a (Maybe a)) -- ^ key bindings for navigating the tree+                           }++instance Default (TSConfig a) where+    def = TSConfig { ts_hidechildren = True+                   , ts_background   = 0xc0c0c0c0+                   , ts_font         = "xft:Sans-16"+                   , ts_node         = (0xff000000, 0xff50d0db)+                   , ts_nodealt      = (0xff000000, 0xff10b8d6)+                   , ts_highlight    = (0xffffffff, 0xffff0000)+                   , ts_extra        = 0xff000000+                   , ts_node_width   = 200+                   , ts_node_height  = 30+                   , ts_originX      = 0+                   , ts_originY      = 0+                   , ts_indent       = 80+                   , ts_navigate     = defaultNavigation+                   }++-- | Default navigation+--+-- * navigation using either arrow key or vi style hjkl+-- * Return or Space to confirm+-- * Escape or Backspace to cancel to+defaultNavigation :: M.Map (KeyMask, KeySym) (TreeSelect a (Maybe a))+defaultNavigation = M.fromList+    [ ((0, xK_Escape), cancel)+    , ((0, xK_Return), select)+    , ((0, xK_space),  select)+    , ((0, xK_Up),     movePrev)+    , ((0, xK_Down),   moveNext)+    , ((0, xK_Left),   moveParent)+    , ((0, xK_Right),  moveChild)+    , ((0, xK_k),      movePrev)+    , ((0, xK_j),      moveNext)+    , ((0, xK_h),      moveParent)+    , ((0, xK_l),      moveChild)+    , ((0, xK_o),      moveHistBack)+    , ((0, xK_i),      moveHistForward)+    ]++-- | Default configuration.+--+-- Using nice alternating blue nodes+tsDefaultConfig :: TSConfig a+tsDefaultConfig = def++-- | Tree Node With a name and extra text+data TSNode a = TSNode { tsn_name  :: String+                       , tsn_extra :: String -- ^ extra text, displayed next to the node name+                       , tsn_value :: a      -- ^ value to return when this node is selected+                       }++-- | State used by TreeSelect.+--+-- Contains all needed information such as the window, font and a zipper over the tree.+data TSState a = TSState { tss_tree     :: TreeZipper (TSNode a)+                         , tss_window   :: Window+                         , tss_display  :: Display+                         , tss_size     :: (Int, Int) -- ^ size of 'tz_window'+                         , tss_xfont    :: XMonadFont+                         , tss_gc       :: GC+                         , tss_visual   :: Visual+                         , tss_colormap :: Colormap+                         , tss_history  :: ([[String]], [[String]]) -- ^ history zipper, navigated with 'moveHistBack' and 'moveHistForward'+                         }++-- | State monad transformer using 'TSState'+newtype TreeSelect a b = TreeSelect { runTreeSelect :: ReaderT (TSConfig a) (StateT (TSState a) X) b }+    deriving (Monad, Applicative, Functor, MonadState (TSState a),  MonadReader (TSConfig a), MonadIO)++-- | Lift the 'X' action into the 'XMonad.Actions.TreeSelect.TreeSelect' monad+liftX :: X a -> TreeSelect b a+liftX = TreeSelect . lift . lift++-- | Run Treeselect with a given config and tree.+-- This can be used for selectiong anything+--+-- * for switching workspaces and moving windows use 'treeselectWorkspace'+-- * for selecting actions use 'treeselectAction'+treeselect :: TSConfig a         -- ^ config file+           -> Forest (TSNode a)  -- ^ a list of 'Data.Tree.Tree's to select from.+           -> X (Maybe a)+treeselect c t = treeselectAt c (fromForest t) []++-- | Same as 'treeselect' but ad a specific starting position+treeselectAt :: TSConfig a         -- ^ config file+             -> TreeZipper (TSNode a)  -- ^ tree structure with a cursor position (starting node)+             -> [[String]] -- ^ list of paths that can be navigated with 'moveHistBack' and 'moveHistForward' (bound to the 'o' and 'i' keys)+             -> X (Maybe a)+treeselectAt conf@TSConfig{..} zipper hist = withDisplay $ \display -> do+    -- create a window on the currently focused screen+    rootw <- asks theRoot+    Rectangle{..} <- gets $ screenRect . W.screenDetail . W.current . windowset++    Just vinfo <- liftIO $ matchVisualInfo display (defaultScreen display) 32 4++    colormap <- liftIO $ createColormap display rootw (visualInfo_visual vinfo) allocNone++    win <- liftIO $ allocaSetWindowAttributes $ \attributes -> do+        set_override_redirect attributes True+        set_colormap attributes colormap+        set_background_pixel attributes ts_background+        set_border_pixel attributes 0+        createWindow display rootw rect_x rect_y rect_width rect_height 0 (visualInfo_depth vinfo) inputOutput (visualInfo_visual vinfo) (cWColormap .|. cWBorderPixel .|. cWBackPixel) attributes++    liftIO $ do+        -- TODO: move below?+        -- make the window visible+        mapWindow display win++        -- listen to key and mouse button events+        selectInput display win (exposureMask .|. keyPressMask .|. buttonReleaseMask)++        -- TODO: enable mouse select?+        -- and mouse button 1+        grabButton display button1 anyModifier win True buttonReleaseMask grabModeAsync grabModeAsync none none++    -- grab the keyboard+    status <- liftIO $ grabKeyboard display win True grabModeAsync grabModeAsync currentTime++    r <- if status == grabSuccess+        then do+            -- load the XMF font+            gc <- liftIO $ createGC display win+            xfont <- initXMF ts_font++            -- run the treeselect Monad+            ret <- evalStateT (runReaderT (runTreeSelect (redraw >> navigate)) conf)+                TSState{ tss_tree     = zipper+                       , tss_window   = win+                       , tss_display  = display+                       , tss_xfont    = xfont+                       , tss_size     = (fromIntegral rect_width, fromIntegral rect_height)+                       , tss_gc       = gc+                       , tss_visual   = visualInfo_visual vinfo+                       , tss_colormap = colormap+                       , tss_history = ([], hist)+                       }++            -- release the XMF font+            releaseXMF xfont+            liftIO $ freeGC display gc+            return ret++        else return Nothing++    -- destroy the window+    liftIO $ do+        unmapWindow display win+        destroyWindow display win+        freeColormap display colormap+        -- Flush the output buffer and wait for all the events to be processed+        -- TODO: is this needed?+        sync display False+    return r++-- | Select a workspace and execute a \"view\" function from "XMonad.StackSet" on it.+treeselectWorkspace :: TSConfig WorkspaceId+                    -> Forest String -- ^ your tree of workspace-names+                    -> (WorkspaceId -> WindowSet -> WindowSet) -- ^ the \"view\" function.+                                                               -- Instances can be 'W.greedyView' for switching to a workspace+                                                               -- and/or 'W.shift' for moving the focused window to a selected workspace.+                                                               --+                                                               -- These actions can also be combined by doing+                                                               --+                                                               -- > \i -> W.greedyView i . W.shift i+                    -> X ()+treeselectWorkspace c xs f = do+    -- get all defined workspaces+    -- They have to be set with 'toWorkspaces'!+    ws <- gets (W.workspaces . windowset)++    -- check the 'XConfig.workspaces'+    if all (`elem` map tag ws) (toWorkspaces xs)+      then do+        -- convert the 'Forest WorkspaceId' to 'Forest (TSNode WorkspaceId)'+        wsf <- forMForest (mkPaths xs) $ \(n, i) -> maybe (return (TSNode n "Does not exist!" "")) (mkNode n) (find (\w -> i == tag w) ws)++        -- get the current workspace path+        me <- gets (W.tag . W.workspace . W.current . windowset)+        hist <- workspaceHistory+        treeselectAt c (fromJust $ followPath tsn_name (splitPath me) $ fromForest wsf) (map splitPath hist) >>= maybe (return ()) (windows . f)++      else liftIO $ do+        -- error!+        let msg = unlines $ [ "Please add:"+                            , "    workspaces = toWorkspaces myWorkspaces"+                            , "to your XMonad config!"+                            , ""+                            , "XConfig.workspaces: "+                            ] ++ map tag ws+        hPutStrLn stderr msg+        _ <- forkProcess $ executeFile "xmessage" True [msg] Nothing+        return ()+  where+    mkNode n w = do+        -- find the focused window's name on this workspace+        name <- maybe (return "") (fmap show . getName . W.focus) $ stack w+        return $ TSNode n name (tag w)++-- | Convert the workspace-tree to a flat list of paths such that XMonad can use them+--+-- The Nodes will be separated by a dot (\'.\') character+toWorkspaces :: Forest String -> [WorkspaceId]+toWorkspaces = map snd . concatMap flatten . mkPaths++mkPaths :: Forest String -> Forest (String, WorkspaceId)+mkPaths = map (\(Node n ns) -> Node (n, n) (map (f n) ns))+  where+    f pth (Node x xs) = let pth' = pth ++ '.' : x+                         in Node (x, pth') (map (f pth') xs)++splitPath :: WorkspaceId -> [String]+splitPath i = case break (== '.') i of+    (x,   []) -> [x]+    (x, _:xs) -> x : splitPath xs++-- | Select from a Tree of 'X' actions+--+-- <<https://wiki.haskell.org/wikiupload/thumb/9/9b/Treeselect-Action.png/800px-Treeselect-Action.png>>+--+-- Each of these actions have to be specified inside a 'TSNode'+--+-- Example+--+-- > treeselectAction myTreeConf+-- >    [ Node (TSNode "Hello"    "displays hello"      (spawn "xmessage hello!")) []+-- >    , Node (TSNode "Shutdown" "Poweroff the system" (spawn "shutdown")) []+-- >    , Node (TSNode "Brightness" "Sets screen brightness using xbacklight" (return ()))+-- >        [ Node (TSNode "Bright" "FULL POWER!!"            (spawn "xbacklight -set 100")) []+-- >        , Node (TSNode "Normal" "Normal Brightness (50%)" (spawn "xbacklight -set 50"))  []+-- >        , Node (TSNode "Dim"    "Quite dark"              (spawn "xbacklight -set 10"))  []+-- >        ]+-- >    ]+treeselectAction :: TSConfig (X a) -> Forest (TSNode (X a)) -> X ()+treeselectAction c xs = treeselect c xs >>= \x -> case x of+    Just a  -> a >> return ()+    Nothing -> return ()++forMForest :: (Functor m, Applicative m, Monad m) => [Tree a] -> (a -> m b) -> m [Tree b]+forMForest x g = mapM (mapMTree g) x++mapMTree :: (Functor m, Applicative m, Monad m) => (a -> m b) -> Tree a -> m (Tree b)+mapMTree f (Node x xs) = Node <$> f x <*>  mapM (mapMTree f) xs+++-- | Quit returning the currently selected node+select :: TreeSelect a (Maybe a)+select = Just <$> gets (tsn_value . cursor . tss_tree)++-- | Quit without returning anything+cancel :: TreeSelect a (Maybe a)+cancel = return Nothing++-- TODO: redraw only what is necessary.+-- Examples: redrawAboveCursor, redrawBelowCursor and redrawCursor++-- | Move the cursor to its parent node+moveParent :: TreeSelect a (Maybe a)+moveParent = moveWith parent >> redraw >> navigate++-- | Move the cursor one level down, highlighting its first child-node+moveChild :: TreeSelect a (Maybe a)+moveChild = moveWith children >> redraw >> navigate++-- | Move the cursor to the next child-node+moveNext :: TreeSelect a (Maybe a)+moveNext = moveWith nextChild >> redraw >> navigate++-- | Move the cursor to the previous child-node+movePrev :: TreeSelect a (Maybe a)+movePrev = moveWith previousChild >> redraw >> navigate++-- | Move backwards in history+moveHistBack :: TreeSelect a (Maybe a)+moveHistBack = do+    s <- get+    case tss_history s of+        (xs, a:y:ys) -> do+            put s{tss_history = (a:xs, y:ys)}+            moveTo y+        _ -> navigate++-- | Move forward in history+moveHistForward :: TreeSelect a (Maybe a)+moveHistForward = do+    s <- get+    case tss_history s of+        (x:xs, ys) -> do+            put s{tss_history = (xs, x:ys)}+            moveTo x+        _ -> navigate++-- | Move to a specific node+moveTo :: [String] -- ^ path, always starting from the top+       -> TreeSelect a (Maybe a)+moveTo i = moveWith (followPath tsn_name i . rootNode) >> redraw >> navigate++-- | Apply a transformation on the internal 'XMonad.Util.TreeZipper.TreeZipper'.+moveWith :: (TreeZipper (TSNode a) -> Maybe (TreeZipper (TSNode a))) -> TreeSelect a ()+moveWith f = do+    s <- get+    case f (tss_tree s) of+        -- TODO: redraw cursor only?+        Just t -> put s{ tss_tree = t }+        Nothing -> return ()++-- | wait for keys and run navigation+navigate :: TreeSelect a (Maybe a)+navigate = gets tss_display >>= \d -> join . liftIO . allocaXEvent $ \e -> do+    maskEvent d (exposureMask .|. keyPressMask .|. buttonReleaseMask) e++    ev <- getEvent e++    if ev_event_type ev == keyPress+      then do+        (ks, _) <- lookupString $ asKeyEvent e+        return $ do+            mask <- liftX $ cleanMask (ev_state ev)+            f <- asks ts_navigate+            fromMaybe navigate $ M.lookup (mask, fromMaybe xK_VoidSymbol ks) f+      else return navigate++-- | Request a full redraw+redraw :: TreeSelect a ()+redraw = do+    win <- gets tss_window+    dpy <- gets tss_display++    -- clear window+    -- TODO: not always needed!+    liftIO $ clearWindow dpy win++    t <- gets tss_tree+    _ <- drawLayers 0 0 (reverse $ (tz_before t, cursor t, tz_after t) : tz_parents t)+    return ()++drawLayers :: Int -- ^ indentation level+           -> Int -- ^ height+           -> [(Forest (TSNode a), TSNode a, Forest (TSNode a))] -- ^ node layers (from top to bottom!)+           -> TreeSelect a Int+drawLayers _ yl [] = return yl+drawLayers xl yl ((bs, c, as):xs) = do+    TSConfig{..} <- ask++    let nodeColor y = if odd y then ts_node else ts_nodealt++    -- draw nodes above+    forM_ (zip [yl ..] (reverse bs)) $ \(y, Node n _) ->+        drawNode xl y n (nodeColor y)+        -- drawLayers (xl + 1) (y + 1) ns+        -- TODO: draw rest? if not ts_hidechildren+        -- drawLayers (xl + 1) (y + 1) ns++    -- draw the current / parent node+    -- if this is the last (currently focused) we use the 'ts_highlight' color+    let current_level = yl + length bs+    drawNode xl current_level c $+        if null xs then ts_highlight+                   else nodeColor current_level++    l2 <- drawLayers (xl + 1) (current_level + 1) xs++    -- draw nodes below+    forM_ (zip [l2 ..] as) $ \(y, Node n _) ->+        drawNode xl y n (nodeColor y)+        -- TODO: draw rest? if not ts_hidechildren+        -- drawLayers (xl + 1) (y + 1) ns+    return (l2 + length as)+++-- | Draw a node at a given indentation and height level+drawNode :: Int -- ^ indentation level (not in pixels)+         -> Int -- ^ height level (not in pixels)+         -> TSNode a -- ^ node to draw+         -> (Pixel, Pixel) -- ^ node foreground (font) and background color+         -> TreeSelect a ()+drawNode ix iy TSNode{..} col = do+    TSConfig{..} <- ask+    window       <- gets tss_window+    display      <- gets tss_display+    font         <- gets tss_xfont+    gc           <- gets tss_gc+    colormap <- gets tss_colormap+    visual   <- gets tss_visual+    liftIO $ drawWinBox window display visual colormap gc font col tsn_name ts_extra tsn_extra+        (ix * ts_indent) (iy * ts_node_height)+        ts_node_width ts_node_height++    -- TODO: draw extra text (transparent background? or ts_background)+    -- drawWinBox window fnt col2 nodeH (scW-x) (mes) (x+nodeW) y 8++-- | Draw a simple box with text+drawWinBox :: Window -> Display -> Visual -> Colormap -> GC -> XMonadFont -> (Pixel, Pixel) -> String -> Pixel -> String -> Int -> Int -> Int -> Int -> IO ()+drawWinBox win display visual colormap gc font (fg, bg) text fg2 text2 x y w h = do+    -- draw box+    setForeground display gc bg+    fillRectangle display win gc (fromIntegral x) (fromIntegral y) (fromIntegral w) (fromIntegral h)++    -- dreaw text+    drawStringXMF display win visual colormap gc font fg+        (fromIntegral $ x + 8)+        (fromIntegral $ y + h - 8)+        text++    -- dreaw extra text+    drawStringXMF display win visual colormap gc font fg2+        (fromIntegral $ x + w + 8)+        (fromIntegral $ y + h - 8)+        text2++-- | Modified version of 'XMonad.Util.Font.printStringXMF' that uses 'Pixel' as color format+drawStringXMF :: Display -> Drawable -> Visual -> Colormap -> GC+              -> XMonadFont -- ^ XMF Font+              -> Pixel -- ^ font color+              -> Position   -- ^ x-position+              -> Position   -- ^ y-position+              -> String -- ^ string text+              -> IO ()+drawStringXMF display window visual colormap gc font col x y text = case font of+    Core fnt -> do+        setForeground display gc col+        setFont display gc $ fontFromFontStruct fnt+        drawImageString display window gc x y text+    Utf8 fnt -> do+        setForeground display gc col+        wcDrawImageString display window fnt gc x y text+#ifdef XFT+    Xft fnt -> do+        withXftDraw display window visual colormap $+            \ft_draw -> withXftColorValue display visual colormap (fromARGB col) $+            \ft_color -> xftDrawString ft_draw ft_color fnt x y text++-- | Convert 'Pixel' to 'XRenderColor'+--+-- Note that it uses short to represent its components+fromARGB :: Pixel -> XRenderColor+fromARGB x = XRenderColor (fromIntegral $ 0xff00 .&. shiftR x 8)  -- red+                          (fromIntegral $ 0xff00 .&. x)           -- green+                          (fromIntegral $ 0xff00 .&. shiftL x 8)  -- blue+                          (fromIntegral $ 0xff00 .&. shiftR x 16) -- alpha+#endif
XMonad/Actions/UpdatePointer.hs view
@@ -1,7 +1,8 @@+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module      :  XMonadContrib.UpdatePointer--- Copyright   :  (c) Robert Marlow <robreim@bobturf.org>+-- Copyright   :  (c) Robert Marlow <robreim@bobturf.org>, 2015 Evgeny Kurnevsky -- License     :  BSD3-style (see LICENSE) -- -- Maintainer  :  Robert Marlow <robreim@bobturf.org>@@ -28,6 +29,7 @@ import Control.Monad import XMonad.StackSet (member, peek, screenDetail, current) import Data.Maybe+import Control.Exception  -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:@@ -63,9 +65,13 @@ updatePointer refPos ratio = do   ws <- gets windowset   dpy <- asks display+  let defaultRect = screenRect $ screenDetail $ current ws   rect <- case peek ws of-        Nothing -> return $ (screenRect . screenDetail .current) ws-        Just w  -> windowAttributesToRectangle `fmap` io (getWindowAttributes dpy w)+        Nothing -> return defaultRect+        Just w  -> do tryAttributes <- io $ try $ getWindowAttributes dpy w+                      return $ case tryAttributes of+                        Left (_ :: SomeException) -> defaultRect+                        Right attributes          -> windowAttributesToRectangle attributes   root <- asks theRoot   mouseIsMoving <- asks mouseFocused   (_sameRoot,_,currentWindow,rootX,rootY,_,_,_) <- io $ queryPointer dpy root
XMonad/Actions/WindowBringer.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TupleSections #-} ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Actions.WindowBringer@@ -17,13 +18,13 @@ module XMonad.Actions.WindowBringer (                     -- * Usage                     -- $usage-                    gotoMenu, gotoMenu', gotoMenuArgs, gotoMenuArgs',-                    bringMenu, bringMenu', bringMenuArgs, bringMenuArgs',-                    windowMap,-                    bringWindow+                    WindowBringerConfig(..),+                    gotoMenu, gotoMenuConfig, gotoMenu', gotoMenuArgs, gotoMenuArgs',+                    bringMenu, bringMenuConfig, bringMenu', bringMenuArgs, bringMenuArgs',+                    windowMap, windowMap', bringWindow, actionMenu                    ) where -import Data.Char (toLower)+import Control.Applicative((<$>)) import qualified Data.Map as M  import qualified XMonad.StackSet as W@@ -46,54 +47,74 @@ -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". --- | Default menu command-defaultCmd :: String-defaultCmd = "dmenu"+data WindowBringerConfig = WindowBringerConfig+    { menuCommand :: String -- ^ The shell command that will handle window selection+    , menuArgs :: [String] -- ^ Arguments to be passed to menuCommand+    , windowTitler :: X.WindowSpace -> Window -> X String -- ^ A function that produces window titles given a workspace and a window+    } +instance Default WindowBringerConfig where+    def = WindowBringerConfig{ menuCommand = "dmenu"+                             , menuArgs = ["-i"]+                             , windowTitler = decorateName+                             }+ -- | Pops open a dmenu with window titles. Choose one, and you will be --   taken to the corresponding workspace. gotoMenu :: X ()-gotoMenu = gotoMenuArgs []+gotoMenu = gotoMenuConfig def  -- | Pops open a dmenu with window titles. Choose one, and you will be+--   taken to the corresponding workspace. This version accepts a configuration+--   object.+gotoMenuConfig :: WindowBringerConfig -> X ()+gotoMenuConfig wbConfig = actionMenu wbConfig W.focusWindow++-- | Pops open a dmenu with window titles. Choose one, and you will be --   taken to the corresponding workspace. This version takes a list of --   arguments to pass to dmenu. gotoMenuArgs :: [String] -> X ()-gotoMenuArgs menuArgs = gotoMenuArgs' defaultCmd menuArgs+gotoMenuArgs args = gotoMenuConfig def { menuArgs = args }  -- | Pops open an application with window titles given over stdin. Choose one, --   and you will be taken to the corresponding workspace. gotoMenu' :: String -> X ()-gotoMenu' menuCmd = gotoMenuArgs' menuCmd []+gotoMenu' cmd = gotoMenuConfig def { menuArgs = [], menuCommand = cmd }  -- | Pops open an application with window titles given over stdin. Choose one, --   and you will be taken to the corresponding workspace. This version takes a --   list of arguments to pass to dmenu. gotoMenuArgs' :: String -> [String] -> X ()-gotoMenuArgs' menuCmd menuArgs = actionMenu menuCmd menuArgs W.focusWindow+gotoMenuArgs' cmd args = gotoMenuConfig def { menuCommand = cmd, menuArgs = args }  -- | Pops open a dmenu with window titles. Choose one, and it will be --   dragged, kicking and screaming, into your current workspace. bringMenu :: X ()-bringMenu = bringMenuArgs []+bringMenu = bringMenuArgs def  -- | Pops open a dmenu with window titles. Choose one, and it will be --   dragged, kicking and screaming, into your current workspace. This version+--   accepts a configuration object.+bringMenuConfig :: WindowBringerConfig -> X ()+bringMenuConfig wbConfig = actionMenu wbConfig bringWindow++-- | Pops open a dmenu with window titles. Choose one, and it will be+--   dragged, kicking and screaming, into your current workspace. This version --   takes a list of arguments to pass to dmenu. bringMenuArgs :: [String] -> X ()-bringMenuArgs menuArgs = bringMenuArgs' defaultCmd menuArgs+bringMenuArgs args = bringMenuConfig def { menuArgs = args }  -- | Pops open an application with window titles given over stdin. Choose one, --   and it will be dragged, kicking and screaming, into your current --   workspace. bringMenu' :: String -> X ()-bringMenu' menuCmd = bringMenuArgs' menuCmd []+bringMenu' cmd = bringMenuConfig def { menuArgs = [], menuCommand = cmd }  -- | Pops open an application with window titles given over stdin. Choose one, --   and it will be dragged, kicking and screaming, into your current --   workspace. This version allows arguments to the chooser to be specified. bringMenuArgs' :: String -> [String] -> X ()-bringMenuArgs' menuCmd menuArgs = actionMenu menuCmd menuArgs bringWindow+bringMenuArgs' cmd args = bringMenuConfig def { menuArgs = args, menuCommand = cmd }  -- | Brings the specified window into the current workspace. bringWindow :: Window -> X.WindowSet -> X.WindowSet@@ -101,25 +122,33 @@  -- | Calls dmenuMap to grab the appropriate Window, and hands it off to action --   if found.-actionMenu :: String -> [String] -> (Window -> X.WindowSet -> X.WindowSet) -> X ()-actionMenu menuCmd menuArgs action = windowMap >>= menuMapFunction >>= flip X.whenJust (windows . action)+actionMenu :: WindowBringerConfig -> (Window -> X.WindowSet -> X.WindowSet) -> X ()+actionMenu WindowBringerConfig{ menuCommand = cmd+                              , menuArgs = args+                              , windowTitler = titler+                              } action+    = windowMap' titler >>= menuMapFunction >>= flip X.whenJust (windows . action)     where       menuMapFunction :: M.Map String a -> X (Maybe a)-      menuMapFunction selectionMap = menuMapArgs menuCmd menuArgs selectionMap+      menuMapFunction = menuMapArgs cmd args + -- | A map from window names to Windows. windowMap :: X (M.Map String Window)-windowMap = do+windowMap = windowMap' decorateName++-- | A map from window names to Windows, given a windowTitler function.+windowMap' :: (X.WindowSpace -> Window -> X String) -> X (M.Map String Window)+windowMap' titler = do   ws <- gets X.windowset-  M.fromList `fmap` concat `fmap` mapM keyValuePairs (W.workspaces ws)+  M.fromList . concat <$> mapM keyValuePairs (W.workspaces ws)  where keyValuePairs ws = mapM (keyValuePair ws) $ W.integrate' (W.stack ws)-       keyValuePair ws w = flip (,) w `fmap` decorateName ws w+       keyValuePair ws w = flip (,) w <$> titler ws w  -- | Returns the window name as will be listed in dmenu.---   Lowercased, for your convenience (since dmenu is case-sensitive). --   Tagged with the workspace ID, to guarantee uniqueness, and to let the user --   know where he's going. decorateName :: X.WindowSpace -> Window -> X String decorateName ws w = do-  name <- fmap (map toLower . show) $ getName w+  name <- show <$> getName w   return $ name ++ " [" ++ W.tag ws ++ "]"
XMonad/Actions/WindowGo.hs view
@@ -21,6 +21,7 @@                  runOrRaiseNext,                  raiseMaybe,                  raiseNextMaybe,+                 raiseNextMaybeCustomFocus,                   raiseBrowser,                  raiseEditor,@@ -37,13 +38,14 @@  import Control.Monad import Data.Char (toLower)+import qualified Data.List as L (nub,sortBy) import Data.Monoid-import XMonad (Query(), X(), ManageHook, withWindowSet, runQuery, liftIO, ask)+import XMonad (Query(), X(), ManageHook, WindowSet, 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, swapMaster, focusWindow)+import qualified XMonad.StackSet as W (peek, swapMaster, focusWindow, workspaces, StackSet, Workspace, integrate', tag, stack) import XMonad.Util.Run (safeSpawnProg) {- $usage @@ -65,12 +67,20 @@ For detailed instructions on editing your key bindings, see "XMonad.Doc.Extending#Editing_key_bindings". -} +-- | Get the list of workspaces sorted by their tag+workspacesSorted :: Ord i => W.StackSet i l a s sd -> [W.Workspace i l a]+workspacesSorted s = L.sortBy (\u t -> W.tag u `compare` W.tag t) $ W.workspaces s++-- | Get a list of all windows in the 'StackSet' with an absolute ordering of workspaces+allWindowsSorted :: Ord i => Eq a => W.StackSet i l a s sd -> [a]+allWindowsSorted = L.nub . concatMap (W.integrate' . W.stack) . workspacesSorted+ -- | 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+  matches <- filterM (runQuery qry) $ allWindowsSorted wins   case matches of     [] -> el     ws -> f ws@@ -137,16 +147,21 @@      'raiseNextMaybe' is an alternative version that allows cycling      through the matching windows. If the focused window matches the      query the next matching window is raised. If no matches are found-     the function f is executed.--}-+     the function f is executed. -} raiseNextMaybe :: X () -> Query Bool -> X ()-raiseNextMaybe f qry = flip (ifWindows qry) f $ \ws -> do+raiseNextMaybe = raiseNextMaybeCustomFocus W.focusWindow++{- | See 'raiseMaybe' and 'raiseNextMaybe'.+     In addition to all of the options offered by 'raiseNextMaybe'+     'raiseNextMaybeCustomFocus' allows the user to supply the function that+     should be used to shift the focus to any window that is found. -}+raiseNextMaybeCustomFocus :: (Window -> WindowSet -> WindowSet) -> X() -> Query Bool -> X()+raiseNextMaybeCustomFocus focusFn 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+                            in windows $ focusFn y+    _ -> windows . focusFn . 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.@@ -167,7 +182,8 @@ raiseAndDo f qry after = ifWindow qry (afterRaise `mappend` raiseHook) f     where afterRaise = ask >>= (>> idHook) . liftX . after -{- | If a window matching the second argument is found, the window is focused and the third argument is called;+{- | If a window matching the second argument 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@@ -182,7 +198,6 @@ {- |  If the window is found the window is focused and set to master       otherwise, action is run. -      > runOrRaiseMaster "firefox" (className =? "Firefox"))-  -}+      > runOrRaiseMaster "firefox" (className =? "Firefox")) -} runOrRaiseMaster :: String -> Query Bool -> X () runOrRaiseMaster run query = runOrRaiseAndDo run query (\_ -> windows W.swapMaster)
XMonad/Actions/Workscreen.hs view
@@ -31,6 +31,7 @@   ,shiftToWorkscreen   ,fromWorkspace   ,expandWorkspace+  ,WorkscreenId   ) where  import XMonad hiding (workspaces)
XMonad/Actions/WorkspaceNames.hs view
@@ -24,7 +24,10 @@     -- * Workspace naming     renameWorkspace,     workspaceNamesPP,+    getWorkspaceNames',     getWorkspaceNames,+    getWorkspaceName,+    getCurrentWorkspaceName,     setWorkspaceName,     setCurrentWorkspaceName, @@ -88,14 +91,27 @@     initialValue = WorkspaceNames M.empty     extensionType = PersistentExtension +-- | Returns a lookup function that maps workspace tags to workspace names.+getWorkspaceNames' :: X (WorkspaceId -> Maybe String)+getWorkspaceNames' = do+    WorkspaceNames m <- XS.get+    return (`M.lookup` m)+ -- | Returns a function that maps workspace tag @\"t\"@ to @\"t:name\"@ for -- workspaces with a name, and to @\"t\"@ otherwise. getWorkspaceNames :: X (WorkspaceId -> String) getWorkspaceNames = do-    WorkspaceNames m <- XS.get-    return $ \wks -> case M.lookup wks m of-        Nothing -> wks-        Just s  -> wks ++ ":" ++ s+    lookup <- getWorkspaceNames'+    return $ \wks -> wks ++ maybe "" (':' :) (lookup wks)++-- | Gets the name of a workspace, if set, otherwise returns nothing.+getWorkspaceName :: WorkspaceId -> X (Maybe String)+getWorkspaceName w = ($ w) `fmap` getWorkspaceNames'++-- | Gets the name of the current workspace. See 'getWorkspaceName'+getCurrentWorkspaceName :: X (Maybe String)+getCurrentWorkspaceName = do+    getWorkspaceName =<< gets (W.currentTag . windowset)  -- | Sets the name of a workspace. Empty string makes the workspace unnamed -- again.
XMonad/Config/Azerty.hs view
@@ -36,7 +36,7 @@ -- 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 }+-- > main = xmonad someConfig { keys = \c -> azertyKeys c <+> keys someConfig c }  azertyConfig = def { keys = azertyKeys <+> keys def } @@ -46,3 +46,9 @@     [((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)]]+    +++    -- mod-{z,e,r} %! Switch to physical/Xinerama screens 1, 2, or 3+    -- mod-shift-{z,e,r} %! Move client to screen 1, 2, or 3+    [((m .|. modm, key), screenWorkspace sc >>= flip whenJust (windows . f))+        | (key, sc) <- zip [xK_z, xK_e, xK_r] [0..],+          (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
XMonad/Config/Bluetile.hs view
@@ -180,8 +180,7 @@ bluetileManageHook = composeAll                [ workspaceByPos, positionStoreManageHook (Just defaultThemeWithButtons)                 , className =? "MPlayer" --> doFloat-                , isFullscreen --> doFullFloat-                , manageDocks]+                , isFullscreen --> doFullFloat]  bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $ (                         named "Floating" floating |||@@ -199,6 +198,7 @@             floatingDeco l = buttonDeco shrinkText defaultThemeWithButtons l  bluetileConfig =+    docks $     def         { modMask = mod4Mask,   -- logo key           manageHook = bluetileManageHook,
XMonad/Config/Desktop.hs view
@@ -164,10 +164,9 @@ -- >        adjustEventInput -- -desktopConfig = ewmh def-    { startupHook     = setDefaultCursor xC_left_ptr+desktopConfig = docks $ ewmh def+    { startupHook     = setDefaultCursor xC_left_ptr <+> startupHook def     , layoutHook      = desktopLayoutModifiers $ layoutHook def-    , manageHook      = manageHook def <+> manageDocks     , keys            = desktopKeys <+> keys def }  desktopKeys (XConfig {modMask = modm}) = M.fromList $
XMonad/Config/Dmwit.hs view
@@ -205,7 +205,7 @@ instance (Show a, Show b) => PPrint (Map a b) -- }}} -- main {{{-dmwitConfig nScreens = def {+dmwitConfig nScreens = docks $ def {     borderWidth             = 2,     workspaces              = withScreens nScreens (map show [1..5]),     terminal                = "urxvt",@@ -221,7 +221,6 @@                               <+> (appName =? "huludesktop" --> doRectFloat fullscreen43on169)                               <+> fullscreenMPlayer                               <+> floatAll ["Gimp", "Wine"]-                              <+> manageDocks                               <+> manageSpawn,     logHook                 = allPPs nScreens,     startupHook             = refresh
XMonad/Config/Droundy.hs view
@@ -42,7 +42,7 @@ import XMonad.Actions.CycleWS ( moveTo, WSType( HiddenNonEmptyWS ),                                 Direction1D( Prev, Next) ) -import XMonad.Hooks.ManageDocks ( avoidStruts, manageDocks )+import XMonad.Hooks.ManageDocks ( avoidStruts, docks ) import XMonad.Hooks.EwmhDesktops ( ewmh )  myXPConfig :: XPConfig@@ -117,7 +117,7 @@     ++     zip (zip (repeat (modMask x .|. shiftMask)) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..]) -config = ewmh def+config = docks $ ewmh def          { borderWidth = 1 -- Width of the window border in pixels.          , XMonad.workspaces = ["mutt","iceweasel"]          , layoutHook = showWName $ workspaceDir "~" $@@ -129,7 +129,6 @@                         named "widescreen" ((mytab *||* mytab)                                                 ****//* combineTwo Square mytab mytab) --   |||                         --mosaic 0.25 0.5-         , manageHook = manageHook def <+> manageDocks -- add panel-handling          , terminal = "xterm" -- The preferred terminal program.          , normalBorderColor = "#222222" -- Border color for unfocused windows.          , focusedBorderColor = "#00ff00" -- Border color for focused windows.
XMonad/Config/Gnome.hs view
@@ -18,7 +18,8 @@     -- $usage     gnomeConfig,     gnomeRun,-    gnomeRegister+    gnomeRegister,+    desktopLayoutModifiers     ) where  import XMonad
XMonad/Config/Kde.hs view
@@ -17,7 +17,8 @@     -- * Usage     -- $usage     kdeConfig,-    kde4Config+    kde4Config,+    desktopLayoutModifiers     ) where  import XMonad
XMonad/Config/Mate.hs view
@@ -20,7 +20,8 @@     -- $usage     mateConfig,     mateRun,-    mateRegister+    mateRegister,+    desktopLayoutModifiers     ) where  import XMonad
XMonad/Config/Sjanssen.hs view
@@ -21,7 +21,7 @@ import qualified Data.Map as M  sjanssenConfig =-    ewmh $ def+    docks $ ewmh $ def         { terminal = "exec urxvt"         , workspaces = ["irc", "web"] ++ map show [3 .. 9 :: Int]         , mouseBindings = \(XConfig {modMask = modm}) -> M.fromList $@@ -35,7 +35,7 @@                                     | (x, w) <- [ ("Firefox", "web")                                                 , ("Ktorrent", "7")                                                 , ("Amarokapp", "7")]]-                        <+> manageHook def <+> manageDocks <+> manageSpawn+                        <+> manageHook def <+> manageSpawn                         <+> (isFullscreen --> doFullFloat)         , startupHook = mapM_ spawnOnce spawns         }
XMonad/Config/Xfce.hs view
@@ -16,7 +16,8 @@ module XMonad.Config.Xfce (     -- * Usage     -- $usage-    xfceConfig+    xfceConfig,+    desktopLayoutModifiers     ) where  import XMonad
XMonad/Doc/Extending.hs view
@@ -116,6 +116,13 @@ See "XMonad.Doc.Extending#Editing_key_bindings" for instructions on how to edit your key bindings. +* "XMonad.Actions.AfterDrag":+    Allows you to add actions dependent on the current mouse drag.++* "XMonad.Actions.BluetileCommands":+    External commands for interfacing the [Bluetile](https://hackage.haskell.org/package/bluetile)+    tiling window manager with Xmonad.+ * "XMonad.Actions.Commands":     Allows you to run internal xmonad commands (X () actions) using     a dmenu menu in addition to key bindings.  Requires dmenu and@@ -159,6 +166,20 @@     master, swap it with the next window in the stack. Focus stays in the     master. +* "XMonad.Actions.DynamicProjects":+    Imbues workspaces with additional features so they can be treated as+    individual project areas.++* "XMonad.Actions.DynamicWorkspaceGroups":+    Dynamically manage "workspace groups", sets of workspaces being used+    together for some common task or purpose, to allow switching between+    workspace groups in a single action. Note that this only makes sense for+    multi-head setups.++* "XMonad.Actions.DynamicWorkspaceOrder":+    Remember a dynamically updateable ordering on workspaces, together with+    tools for using this ordering with "XMonad.Actions.CycleWS" and "XMonad.Hooks.DynamicLog".+ * "XMonad.Actions.DynamicWorkspaces":     Provides bindings to add and delete workspaces.  Note that you may only     delete a workspace that is already empty.@@ -186,6 +207,24 @@     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.GroupNavigation":+    Provides methods for cycling through groups of windows across workspaces,+    ignoring windows that do not belong to this group. A group consists of all+    windows matching a user-provided boolean query. Also provides a method for+    jumping back to the most recently used window in any given group.++* "XMonad.Actions.KeyRemap":+    Remap Keybinding on the fly, e.g having Dvorak char,+    but everything with Control/Shift is left US Layout.++* "XMonad.Actions.Launcher":+    A set of prompts for XMonad.++* "XMonad.Actions.LinkWorkspaces":+    Provides bindings to add and delete links between workspaces. It is aimed at+    providing useful links between workspaces in a multihead setup.+    Linked workspaces are view at the same time.+ * "XMonad.Actions.MessageFeedback":     Alternative to 'XMonad.Operations.sendMessage' that provides knowledge     of whether the message was handled, and utility functions based on@@ -198,6 +237,10 @@     A layout modifier to resize windows with the mouse by grabbing the     window's lower right corner. +* "XMonad.Actions.Navigation2D":+    Navigation2D is an xmonad extension that allows easy directional navigation+    of windows and screens (in a multi-monitor setup).+ * "XMonad.Actions.NoBorders":     This module provides helper functions for dealing with window borders. @@ -228,6 +271,10 @@     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.ShowText":+    ShowText displays text for sometime on the screen similar to+    "XMonad.Util.Dzen" which offers more features (currently).+ * "XMonad.Actions.SimpleDate":     An example external contrib module for XMonad.     Provides a simple binding to dzen2 to print the date as a popup menu.@@ -254,6 +301,12 @@ * "XMonad.Actions.TopicSpace":     Turns your workspaces into a more topic oriented system. +* "XMonad.Actions.TreeSelect":+    TreeSelect displays your workspaces or actions in a Tree-like format.+    You can select the desired workspace/action with the cursor or hjkl keys.+    This module is fully configurable and very useful if you like to have a+    lot of workspaces.+ * "XMonad.Actions.UpdateFocus":     Updates the focus on mouse move in unfocused windows. @@ -283,9 +336,23 @@     Provides functions for performing a given action on all windows of     the current workspace. +* "XMonad.Actions.Workscreen":+    A workscreen permits to display a set of workspaces on several screens. In+    xinerama mode, when a workscreen is viewed, workspaces associated to all+    screens are visible. The first workspace of a workscreen is displayed on+    first screen, second on second screen, etc. Workspace position can be easily+    changed. If the current workscreen is called again, workspaces are shifted.+    This also permits to see all workspaces of a workscreen even if just one screen+    is present, and to move windows from workspace to workscreen.+ * "XMonad.Actions.WorkspaceCursors":     Like "XMonad.Actions.Plane" for an arbitrary number of dimensions. +* "XMonad.Actions.WorkspaceNames":+    Provides bindings to rename workspaces, show these names in DynamicLog and+    swap workspaces along with their names. These names survive restart. Together+    with "XMonad.Layout.WorkspaceDir" this provides for a fully dynamic topic+    space workflow. -}  {- $configs@@ -297,26 +364,57 @@ own configuration, possibly with some modifications.  -* "XMonad.Config.Arossato"+* "XMonad.Config.Arossato":     This module specifies my xmonad defaults. -* "XMonad.Config.Azerty"+* "XMonad.Config.Azerty":     Fixes some keybindings for users of French keyboard layouts. -* "XMonad.Config.Desktop"+* "XMonad.Config.Bepo":+    This module fixes some of the keybindings for the francophone among you who+    use a BEPO keyboard layout. Based on "XMonad.Config.Azerty".++* "XMonad.Config.Bluetile":+    This is the default configuration of [Bluetile](http://projects.haskell.org/bluetile/).+    If you are migrating from Bluetile to xmonad or want to create a similar setup,+    then this will give you pretty much the same thing, except for Bluetile's+    helper applications such as the dock.++* "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.Dmwit":+    [dmwit](https://github.com/dmwit)'s xmonad configs and helpers. -* "XMonad.Config.Kde"+* "XMonad.Config.Droundy":+    Droundy's xmonad config. -* "XMonad.Config.Sjanssen"+* "XMonad.Config.Gnome":+    This module provides a config suitable for use with the GNOME desktop environment. -* "XMonad.Config.Xfce"+* "XMonad.Config.Kde":+    This module provides a config suitable for use with the KDE desktop environment. +* "XMonad.Config.Mate":+    This module provides a config suitable for use with the MATE desktop environment.++* "XMonad.Config.Prime":+    This is a draft of a brand new config syntax for xmonad. It aims to be+    1) easier to copy/paste snippets from the docs 2) easier to get the gist+    for what's going on, for you imperative programmers. It's brand new, so it's+    pretty much guaranteed to break or change syntax. But what's the worst that+    could happen? Xmonad crashes and logs you out? It probably won't do that.+    Give it a try.++* "XMonad.Config.Sjanssen":+    [spencerjanssen](https://github.com/spencerjanssen)'s xmonad configs.++* "XMonad.Config.Xfce":+    This module provides a config suitable for use with the Xfce desktop environment.+ -}  {- $hooks@@ -349,6 +447,29 @@  Here is a list of the modules found in @XMonad.Hooks@: +* "XMonad.Hooks.CurrentWorkspaceOnTop":+    Ensures that the windows of the current workspace are always in front of+    windows that are located on other visible screens. This becomes important if+    you use decoration and drag windows from one screen to another.+    Using this module, the dragged window will always be in front of other windows.++* "XMonad.Hooks.DebugEvents":+    Module to dump diagnostic information about X11 events received by xmonad.+    This is incomplete due to "Event" being incomplete and not providing+    information about a number of events, and enforcing artificial constraints+    on others (for example ClientMessage); the X11 package will require a number+    of changes to fix these problems.++* "XMonad.Hooks.DebugKeyEvents":+    A debugging module to track key events, useful when you can't tell whether+    xmonad is processing some or all key events.++* "XMonad.Hooks.DebugStack":+    Dump the state of the StackSet. A logHook and handleEventHook are also provided.++* "Xmonad.Hooks.DynamicBars":+    Manage per-screen status bars.+ * "XMonad.Hooks.DynamicHooks":     One-shot and permanent ManageHooks that can be updated at runtime. @@ -367,14 +488,28 @@     which causes those windows to become slightly translucent if something     like xcompmgr is running +* "XMonad.Hooks.FadeWindows":+    A more flexible and general compositing interface than FadeInactive. Windows+    can be selected and opacity specified by means of FadeHooks, which are very+    similar to ManageHooks and use the same machinery.+ * "XMonad.Hooks.FloatNext":     Hook and keybindings for automatically sending the next     spawned window(s) to the floating layer. +* "XMonad.Hooks.ICCCMFocus":+    Deprecated.+ * "XMonad.Hooks.InsertPosition":     Configure where new windows should be added and which window should be     focused. +* "XMonad.Hooks.ManageDebug":+    A manageHook and associated logHook for debugging "ManageHooks". Simplest+    usage: wrap your xmonad config in the debugManageHook combinator. Or use+    debugManageHookOn for a triggerable version, specifying the triggering key+    sequence in "EZConfig" syntax. Or use the individual hooks in whatever way you see fit.+ * "XMonad.Hooks.ManageDocks":     This module provides tools to automatically manage 'dock' type programs,     such as gnome-panel, kicker, dzen, and xmobar.@@ -389,35 +524,54 @@ * "XMonad.Hooks.Place":     Automatic placement of floating windows. +* "XMonad.Hooks.PositionStoreHooks":+    This module contains two hooks for the PositionStore (see XMonad.Util.PositionStore) -+    a ManageHook and an EventHook. The ManageHook can be used to fill the+    PositionStore with position and size information about new windows. The advantage+    of using this hook is, that the information is recorded independent of the+    currently active layout. So the floating shape of the window can later be restored+    even if it was opened in a tiled layout initially. The EventHook makes sure+    that windows are deleted from the PositionStore when they are closed.+ * "XMonad.Hooks.RestoreMinimized":     (Deprecated: Use XMonad.Hooks.Minimize) 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.ScreenCorners":+    Run X () actions by touching the edge of your screen with your mouse.+ * "XMonad.Hooks.Script":     Provides a simple interface for running a ~\/.xmonad\/hooks script with the     name of a hook. -* "XMonad.Hooks.ServerMode": Allows sending commands to a running xmonad process.--* "XMonad.Hooks.SetCursor":-    Set a default mouse cursor on startup.+* "XMonad.Hooks.ServerMode":+    Allows sending commands to a running xmonad process.  * "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.ToggleHook":+    Hook and keybindings for toggling hook behavior.+ * "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.WallpaperSetter":+    Log hook which changes the wallpapers depending on visible workspaces.+ * "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.WorkspaceHistory":+    Keeps track of workspace viewing order.+ * "XMonad.Hooks.XPropManage":     A ManageHook matching on XProperties. @@ -450,6 +604,13 @@     master and slave. Size of slave area automatically changes depending on     number of slave windows. +* "XMonad.Layout.AvoidFloats":+    Find a maximum empty rectangle around floating windows and use that area to+    display non-floating windows.++* "XMonad.Layout.BinarySpacePartition":+    Layout where new windows will split the focused window in half, based off of BSPWM.+ * "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@@ -460,6 +621,11 @@ * "XMonad.Layout.BoringWindows":     BoringWindows is an extension to allow windows to be marked boring +* "XMonad.Layout.ButtonDecoration":+    A decoration that includes small buttons on both ends which invoke various+    actions when clicked on: Show a window menu (see "XMonad.Actions.WindowMenu"),+    minimize, maximize or close the window.+ * "XMonad.Layout.CenteredMaster":     Two layout modifiers. centerMaster places master window at center,     on top of all other windows, which are managed by base layout.@@ -488,6 +654,11 @@     A layout modifier and a class for easily creating decorated     layouts. +* "XMonad.Layout.DecorationAddons":+    Various stuff that can be added to the decoration. Most of it is intended to+    be used by other modules. See "XMonad.Layout.ButtonDecoration" for a module+    that makes use of this.+ * "XMonad.Layout.DecorationMadness":     A collection of decorated layouts: some of them may be nice, some     usable, others just funny.@@ -502,6 +673,24 @@     the other is either the currently focused window or the second window in     layout order. See also "XMonad.Layout.MouseResizableTall" +* "XMonad.Layout.DraggingVisualizer":+    A helper module to visualize the process of dragging a window by making it+    follow the mouse cursor. See "XMonad.Layout.WindowSwitcherDecoration" for a+    module that makes use of this.++* "XMonad.Layout.Drawer":+    A layout modifier that puts some windows in a "drawer" which retracts and+    expands depending on whether any window in it has focus. Useful for music+    players, tool palettes, etc.++* "XMonad.Layout.Dwindle":+    Three layouts: The first, Spiral, is a reimplementation of spiral with, at+    least to me, more intuitive semantics. The second, Dwindle, is inspired by+    a similar layout in awesome and produces the same sequence of decreasing+    window sizes as Spiral but pushes the smallest windows into a screen corner+    rather than the centre. The third, Squeeze arranges all windows in one row+    or in one column, with geometrically decreasing sizes.+ * "XMonad.Layout.DwmStyle":     A layout modifier for decorating windows in a dwm like style. @@ -511,6 +700,10 @@     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.Fullscreen":+    Hooks for sending messages about fullscreen windows to layouts, and a few+    example layout modifier that implement fullscreen windows.+ * "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@@ -526,6 +719,25 @@     master area and uses an aspect-ratio-specified layout for the     slaves. +* "XMonad.Layout.Groups":+    Two-level layout with windows split in individual layout groups, themselves+    managed by a user-provided layout.++*   * "XMonad.Layout.Groups.Examples":+        Example layouts for "XMonad.Layout.Groups".++*   * "XMonad.Layout.Groups.Helpers":+        Utility functions for "XMonad.Layout.Groups".++*   * "XMonad.Layout.Groups.Wmii":+        A wmii-like layout algorithm.++* "XMonad.Layout.Hidden":+    Similar to XMonad.Layout.Minimize but completely removes windows from the+    window set so XMonad.Layout.BoringWindows isn't necessary. Perfect companion+    to XMonad.Layout.BinarySpacePartition since it can be used to move windows+    to another part of the BSP tree.+ * "XMonad.Layout.HintedGrid":     A not so simple layout that attempts to put all windows in a square grid     while obeying their size hints.@@ -538,6 +750,16 @@     Layout modfier suitable for workspace with multi-windowed instant messenger     (like Psi or Tkabber). +* "XMonad.Layout.IfMax":+    Provides IfMax layout, which will run one layout if there are maximum N+    windows on workspace, and another layout, when number of windows is greater+    than N.++* "XMonad.Layout.ImageButtonDecoration":+    A decoration that includes small image buttons on both ends which invoke+    various actions when clicked on: Show a window menu (see "XMonad.Actions.WindowMenu"),+    minimize, maximize or close the window.+ * "XMonad.Layout.IndependentScreens":     Utility functions for simulating independent sets of workspaces on     each screen (like dwm's workspace model), using internal tags to@@ -613,12 +835,19 @@     A layout in the spirit of "XMonad.Layout.ResizableTile", but with the option     to use the mouse to adjust the layout. +* "XMonad.Layout.MultiColumns":+    This layout tiles windows in a growing number of columns. The number of+    windows in each column can be controlled by messages.+ * "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.MultiToggle.Instances":+        Some convenient common instances of the Transformer class, for use with "XMonad.Layout.MultiToggle".+ * "XMonad.Layout.Named":     A module for assigning a name to a given layout. @@ -634,17 +863,38 @@     result in title bars that span the entire window instead of being only the     length of the window title. +* "XMonad.Layout.OnHost":+    Configure layouts on a per-host basis: use layouts and apply layout modifiers+    selectively, depending on the host. Heavily based on "XMonad.Layout.PerWorkspace"+    by Brent Yorgey.+ * "XMonad.Layout.OneBig":     Places one (master) window at top left corner of screen, and other (slave)     windows at the top. +* "XMonad.Layout.PerScreen":+    Configure layouts based on the width of your screen; use your favorite+    multi-column layout for wide screens and a full-screen layout for small ones.+ * "XMonad.Layout.PerWorkspace":     Configure layouts on a per-workspace basis: use layouts and apply     layout modifiers selectively, depending on the workspace. +* "XMonad.Layout.PositionStoreFloat":+    A floating layout which has been designed with a dual-head setup in mind.+    It makes use of "XMonad.Util.PositionStore" as well as "XMonad.Hooks.PositionStoreHooks".+    Since there is currently no way to move or resize windows with the keyboard+    alone in this layout, it is adviced to use it in combination with a decoration+    such as "XMonad.Layout.NoFrillsDecoration" (to move windows) and the layout+    modifier "XMonad.Layout.BorderResize" (to resize windows).+ * "XMonad.Layout.Reflect":     Reflect a layout horizontally or vertically. +* "XMonad.Layout.Renamed":+    Layout modifier that can modify the description of its underlying layout on+    a (hopefully) flexible way.+ * "XMonad.Layout.ResizableTile":     More useful tiled layout that allows you to change a width\/height of window.     See also "XMonad.Layout.MouseResizableTile".@@ -676,6 +926,12 @@ * "XMonad.Layout.SimplestFloat":     A basic floating layout like SimpleFloat but without the decoration. +* "XMonad.Layout.SortedLayout":+    A new LayoutModifier that sorts a given layout by a list of+    properties. The order of properties in the list determines+    the order of windows in the final layout. Any unmatched windows+    go to the end of the order.+ * "XMonad.Layout.Spacing":     Add a configurable amount of space around windows. @@ -694,6 +950,13 @@     A stacking layout, like dishes but with the ability to resize master pane.     Mostly useful on small screens. +* "XMonad.Layout.Stoppable":+    This module implements a special kind of layout modifier, which when applied+    to a layout, causes xmonad to stop all non-visible processes. In a way,+    this is a sledge-hammer for applications that drain power. For example, given+    a web browser on a stoppable workspace, once the workspace is hidden the web+    browser will be stopped.+ * "XMonad.Layout.SubLayouts":     A layout combinator that allows layouts to be nested. @@ -724,6 +987,10 @@     WindowNavigation is an extension to allow easy navigation of a workspace.     See also "XMonad.Actions.WindowNavigation". +* "XMonad.Layout.WindowSwitcherDecoration":+    A decoration that allows to switch the position of windows by dragging them+    onto each other.+ * "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@@ -757,6 +1024,9 @@     you're doing.     Who knows, it might be useful for other purposes as well! +* "XMonad.Prompt.ConfirmPrompt":+    A module for setting up simple confirmation prompts for keybindings.+ * "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@@ -786,6 +1056,13 @@     * narrow completions by section number, if the one is specified     (like @\/etc\/bash_completion@ does) +* "XMonad.Prompt.Pass":+    This module provides 3 combinators for ease passwords manipulation (generate, read, remove):+    1) one to lookup passwords in the password-storage.+    2) one to generate a password for a given password label that the user inputs.+    3) one to delete a stored password for a given password label that the user inputs.++ * "XMonad.Prompt.RunOrRaise":     A prompt for XMonad which will run a program, open a file,     or raise an already running program, depending on context.@@ -830,6 +1107,10 @@ * "XMonad.Util.CustomKeys": configure key bindings (see   "XMonad.Doc.Extending#Editing_key_bindings"). +* "XMonad.Util.DebugWindow":+    Module to dump window information for diagnostic/debugging purposes. See+    "XMonad.Hooks.DebugEvents" and "XMonad.Hooks.DebugStack" for practical uses.+ * "XMonad.Util.Dmenu":     A convenient binding to dmenu.     Requires the process-1.0 package@@ -837,12 +1118,20 @@ * "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.+* "XMonad.Util.EZConfig":+    Configure key bindings easily, including a+    parser for writing key bindings in "M-C-x" style. -* "XMonad.Util.Font": A module for abstracting a font facility over-  Core fonts and Xft+* "XMonad.Util.ExtensibleState":+    Module for storing custom mutable state in xmonad. +* "XMonad.Util.Font":+    A module for abstracting a font facility over+    Core fonts and Xft.++* "XMonad.Util.Image":+    Utilities for manipulating [[Bool]] as images.+ * "XMonad.Util.Invisible":     A data type to store the layout state @@ -852,6 +1141,10 @@     a pretty-printing status logger format. See "XMonad.Hooks.DynamicLog"     for more information. +*   * "XMonad.Util.Loggers.NamedScratchpad":+        A collection of Loggers (see "XMonad.Util.Loggers") for NamedScratchpads+        (see "XMonad.Util.NamedScratchpad").+ * "XMonad.Util.NamedActions":     A wrapper for keybinding configuration that can list the available     keybindings.@@ -864,10 +1157,22 @@     This module allows you to associate the X titles of windows with     them. +* "XMonad.Util.NoTaskbar":+    Utility function and 'ManageHook` to mark a window to be ignored by+    EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since+    you will usually be taken to the `NSP` workspace by them.+ * "XMonad.Util.Paste":     A module for sending key presses to windows. This modules provides generalized     and specialized functions for this task. +* "XMonad.Util.PositionStore":+    A utility module to store information about position and size of a window.+    See "XMonad.Layout.PositionStoreFloat" for a layout that makes use of this.++* "XMonad.Util.RemoteWindows":+    This module implements a proper way of finding out whether the window is remote or local.+ * "XMonad.Util.Replace":     Implements a @--replace@ flag outside of core. @@ -880,6 +1185,16 @@ * "XMonad.Util.Scratchpad":     Very handy hotkey-launched toggleable floating terminal window. +* "XMonad.Util.SpawnNamedPipe":+    A module for spawning a pipe whose Handle lives in the Xmonad state.++* "XMonad.Util.SpawnOnce":+    A module for spawning a command once, and only once. Useful to start status+    bars and make session settings inside startupHook.++* "XMonad.Util.Stack":+    Utility functions for manipulating Maybe Stacks.+ * "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,@@ -894,9 +1209,20 @@ * "XMonad.Util.Types":     Miscellaneous commonly used types. +* "XMonad.Util.Ungrab":+    Release xmonad's keyboard and pointer grabs immediately, so+    screen grabbers and lock utilities, etc. will work. Replaces+    the short sleep hackaround.+ * "XMonad.Util.WindowProperties":     EDSL for specifying window properties; various utilities related to window     properties.++* "XMonad.Util.WindowState":+    Functions for saving per-window data.++* "XMonad.Util.WorkspaceCompare":+    Functions for examining, comparing, and sorting workspaces.  * "XMonad.Util.XSelection":     A module for accessing and manipulating X Window's mouse selection (the buffer used in copy and pasting).
XMonad/Hooks/DynamicBars.hs view
@@ -18,9 +18,13 @@   -- $usage     DynamicStatusBar   , DynamicStatusBarCleanup+  , DynamicStatusBarPartialCleanup   , dynStatusBarStartup+  , dynStatusBarStartup'   , dynStatusBarEventHook+  , dynStatusBarEventHook'   , multiPP+  , multiPPFormat   ) where  import Prelude@@ -29,9 +33,10 @@ import Control.Monad.Trans (lift) import Control.Monad.Writer (WriterT, execWriterT, tell) +import Data.List import Data.Maybe import Data.Monoid-import Data.Traversable (traverse)+import Data.Foldable (traverse_)  import Graphics.X11.Xinerama import Graphics.X11.Xlib@@ -50,14 +55,29 @@ -- dynamically responding to screen changes. A startup action, event hook, and -- a way to separate PP styles based on the screen's focus are provided: ----- * The 'dynStatusBarStartup' hook which initializes the status bars.+-- * The 'dynStatusBarStartup' hook which initializes the status bars. The+-- first argument is an `ScreenId -> IO Handle` which spawns a status bar on the+-- given screen and returns the pipe which the string should be written to.+-- The second argument is a `IO ()` to shut down all status bars. This should+-- be placed in your `startupHook`. -- -- * The 'dynStatusBarEventHook' hook which respawns status bars when the--- number of screens changes.+-- number of screens changes. The arguments are the same as for the+-- `dynStatusBarStartup` function. This should be placed in your+-- `handleEventHook`. --+-- * Each of the above functions have an alternate form+-- (`dynStatusBarStartup'` and `dynStatusBarEventHook'`) which use a cleanup+-- function which takes an additional `ScreenId` argument which allows for+-- more fine-grained control for shutting down a specific screen's status bar.+-- -- * The 'multiPP' function which allows for different output based on whether--- the screen for the status bar has focus.+-- the screen for the status bar has focus (the first argument) or not (the+-- second argument). This is for use in your `logHook`. --+-- * The 'multiPPFormat' function is the same as the 'multiPP' function, but it+-- also takes in a function that can customize the output to status bars.+-- -- The hooks take a 'DynamicStatusBar' function which is given the id of the -- screen to start up and returns the 'Handle' to the pipe to write to. The -- 'DynamicStatusBarCleanup' argument should tear down previous instances. It@@ -65,38 +85,68 @@ --  data DynStatusBarInfo = DynStatusBarInfo-  { dsbInfoScreens :: [ScreenId]-  , dsbInfoHandles :: [Handle]+  { dsbInfo :: [(ScreenId, Handle)]   } deriving (Typeable)  instance ExtensionClass DynStatusBarInfo where-  initialValue = DynStatusBarInfo [] []+  initialValue = DynStatusBarInfo []  type DynamicStatusBar = ScreenId -> IO Handle type DynamicStatusBarCleanup = IO ()+type DynamicStatusBarPartialCleanup = ScreenId -> IO () -dynStatusBarStartup :: DynamicStatusBar -> DynamicStatusBarCleanup -> X ()-dynStatusBarStartup sb cleanup = do+dynStatusBarSetup :: X ()+dynStatusBarSetup = do   dpy <- asks display   root <- asks theRoot   io $ xrrSelectInput dpy root rrScreenChangeNotifyMask++dynStatusBarStartup :: DynamicStatusBar -> DynamicStatusBarCleanup -> X ()+dynStatusBarStartup sb cleanup = do+  dynStatusBarSetup   updateStatusBars sb cleanup +dynStatusBarStartup' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> X ()+dynStatusBarStartup' sb cleanup = do+  dynStatusBarSetup+  updateStatusBars' sb cleanup+ dynStatusBarEventHook :: DynamicStatusBar -> DynamicStatusBarCleanup -> Event -> X All-dynStatusBarEventHook sb cleanup (RRScreenChangeNotifyEvent {}) = updateStatusBars sb cleanup >> return (All True)-dynStatusBarEventHook _  _       _                              = return (All True)+dynStatusBarEventHook sb cleanup = dynStatusBarRun (updateStatusBars sb cleanup) +dynStatusBarEventHook' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> Event -> X All+dynStatusBarEventHook' sb cleanup = dynStatusBarRun (updateStatusBars' sb cleanup)++dynStatusBarRun :: X () -> Event -> X All+dynStatusBarRun action (RRScreenChangeNotifyEvent {}) = action >> return (All True)+dynStatusBarRun _      _                              = return (All True)+ updateStatusBars :: DynamicStatusBar -> DynamicStatusBarCleanup -> X () updateStatusBars sb cleanup = do-  dsbInfo <- XS.get+  (dsbInfoScreens, dsbInfoHandles) <- XS.get >>= return . unzip . dsbInfo   screens <- getScreens-  when (screens /= dsbInfoScreens dsbInfo) $ do+  when (screens /= dsbInfoScreens) $ do       newHandles <- liftIO $ do-          hClose `mapM_` dsbInfoHandles dsbInfo+          hClose `mapM_` dsbInfoHandles           cleanup           mapM sb screens-      XS.put $ DynStatusBarInfo screens newHandles+      XS.put $ DynStatusBarInfo (zip screens newHandles) +updateStatusBars' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> X ()+updateStatusBars' sb cleanup = do+  (dsbInfoScreens, dsbInfoHandles) <- XS.get >>= return . unzip . dsbInfo+  screens <- getScreens+  when (screens /= dsbInfoScreens) $ do+      let oldInfo = zip dsbInfoScreens dsbInfoHandles+      let (infoToKeep, infoToClose) = partition (flip elem screens . fst) oldInfo+      newInfo <- liftIO $ do+          mapM_ hClose $ map snd infoToClose+          mapM_ cleanup $ map fst infoToClose+          let newScreens = screens \\ dsbInfoScreens+          newHandles <- mapM sb newScreens+          return $ zip newScreens newHandles+      XS.put . DynStatusBarInfo $ infoToKeep ++ newInfo+ ----------------------------------------------------------------------------- -- The following code is from adamvo's xmonad.hs file. -- http://www.haskell.org/haskellwiki/Xmonad/Config_archive/adamvo%27s_xmonad.hs@@ -104,10 +154,13 @@ multiPP :: PP -- ^ The PP to use if the screen is focused         -> PP -- ^ The PP to use otherwise         -> X ()-multiPP focusPP unfocusPP = do-  dsbInfo <- XS.get-  multiPP' dynamicLogString focusPP unfocusPP (dsbInfoHandles dsbInfo)+multiPP = multiPPFormat dynamicLogString +multiPPFormat :: (PP -> X String) -> PP -> PP -> X ()+multiPPFormat dynlStr focusPP unfocusPP = do+  (_, dsbInfoHandles) <- XS.get >>= return . unzip . dsbInfo+  multiPP' dynlStr focusPP unfocusPP dsbInfoHandles+ multiPP' :: (PP -> X String) -> PP -> PP -> [Handle] -> X () multiPP' dynlStr focusPP unfocusPP handles = do   st <- get@@ -118,10 +171,9 @@         out <- lift $ dynlStr $ if isFoc then focusPP else unfocusPP         when isFoc $ get >>= tell . Last . Just         return out-  traverse put . getLast+  traverse_ put . getLast     =<< execWriterT . (io . zipWithM_ hPutStrLn handles <=< mapM pickPP) . catMaybes     =<< mapM screenWorkspace (zipWith const [0 .. ] handles)-  return ()  getScreens :: MonadIO m => m [ScreenId] getScreens = liftIO $ do
XMonad/Hooks/DynamicLog.hs view
@@ -199,12 +199,11 @@           -> IO (XConfig (ModifiedLayout AvoidStruts l)) statusBar cmd pp k conf = do     h <- spawnPipe cmd-    return $ conf+    return $ docks $ 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
XMonad/Hooks/DynamicProperty.hs view
@@ -58,8 +58,8 @@   when (ps == propertyNewValue && a == pa) $ do     g <- appEndo <$> userCodeDef (Endo id) (runQuery hook w)     windows g-  return (All False) -- so anything else also processes it-dynamicPropertyChange _ _ _ = return (All False)+  return mempty -- so anything else also processes it+dynamicPropertyChange _ _ _ = return mempty  -- | A shorthand for the most common case, dynamic titles dynamicTitle :: ManageHook -> Event -> X All
XMonad/Hooks/EwmhDesktops.hs view
@@ -47,7 +47,7 @@ -- > main = xmonad $ ewmh def{ handleEventHook = -- >            handleEventHook def <+> fullscreenEventHook } ----- You may also be interested in 'avoidStruts' from "XMonad.Hooks.ManageDocks".+-- You may also be interested in 'docks' from "XMonad.Hooks.ManageDocks".   -- | Add EWMH functionality to the given config.  See above for an example.
XMonad/Hooks/ManageDocks.hs view
@@ -15,8 +15,8 @@ module XMonad.Hooks.ManageDocks (     -- * Usage     -- $usage-    manageDocks, checkDock, AvoidStruts, avoidStruts, avoidStrutsOn,-    docksEventHook,+    docks, manageDocks, checkDock, AvoidStruts, avoidStruts, avoidStrutsOn,+    docksEventHook, docksStartupHook,     ToggleStruts(..),     SetStruts(..),     module XMonad.Util.Types,@@ -39,34 +39,29 @@ import XMonad.Util.Types import XMonad.Util.WindowProperties (getProp32s) import XMonad.Util.XUtils (fi)+import qualified XMonad.Util.ExtensibleState as XS import Data.Monoid (All(..), mempty)+import Data.Functor((<$>))  import qualified Data.Set as S+import qualified Data.Map as M+import Control.Monad (when, forM_, filterM)  -- $usage -- To use this module, add the following import to @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Hooks.ManageDocks ----- The first component is a 'ManageHook' which recognizes these--- windows and de-manages them, so that xmonad does not try to tile--- them.  To enable it:+-- Wrap your xmonad config with a call to 'docks', like so: ----- > manageHook = ... <+> manageDocks+-- > main = xmonad $ docks def ----- The second component is a layout modifier that prevents windows--- from overlapping these dock windows.  It is intended to replace--- xmonad's so-called \"gap\" support.  First, you must add it to your--- list of layouts:+-- Then add 'avoidStruts' or 'avoidStrutsOn' layout modifier to your layout+-- to prevent windows from overlapping these windows. -- -- > layoutHook = avoidStruts (tall ||| mirror tall ||| ...) -- >                   where  tall = Tall 1 (3/100) (1/2) ----- The third component is an event hook that causes new docks to appear--- immediately, instead of waiting for the next focus change.------ > handleEventHook = ... <+> docksEventHook--- -- 'AvoidStruts' also supports toggling the dock gaps; add a keybinding -- similar to: --@@ -86,23 +81,43 @@ -- -- > layoutHook = avoidStrutsOn [U,L] (tall ||| mirror tall ||| ...) ----- /Important note/: if you are switching from manual gaps--- (defaultGaps in your config) to avoidStruts (recommended, since--- manual gaps will probably be phased out soon), be sure to switch--- off all your gaps (with mod-b) /before/ reloading your config with--- avoidStruts!  Toggling struts with a 'ToggleStruts' message will--- not work unless your gaps are set to zero.--- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". -- +-- | Add docks functionality to the given config.  See above for an example.+docks :: XConfig a -> XConfig a+docks c = c { startupHook     = docksStartupHook <+> startupHook c+            , handleEventHook = docksEventHook <+> handleEventHook c+            , manageHook      = manageDocks <+> manageHook c }++newtype StrutCache = StrutCache { fromStrutCache :: M.Map Window [Strut] }+    deriving (Eq, Typeable)++data UpdateDocks = UpdateDocks deriving Typeable+instance Message UpdateDocks++refreshDocks :: X ()+refreshDocks = sendMessage UpdateDocks++instance ExtensionClass StrutCache where+  initialValue = StrutCache M.empty++updateStrutCache :: Window -> [Strut] -> X Bool+updateStrutCache w strut = do+  XS.modified $ StrutCache . M.insert w strut . fromStrutCache++deleteFromStructCache :: Window -> X Bool+deleteFromStructCache w = do+  XS.modified $ StrutCache . M.delete w . fromStrutCache+ -- | Detects if the given window is of type DOCK and if so, reveals --   it, but does not manage it. manageDocks :: ManageHook-manageDocks = checkDock --> (doIgnore <+> clearGapCache)-    where clearGapCache = do-            liftX (broadcastMessage ClearGapCache)+manageDocks = checkDock --> (doIgnore <+> setDocksMask)+    where setDocksMask = do+            ask >>= \win -> liftX $ withDisplay $ \dpy -> do+                io $ selectInput dpy win (propertyChangeMask .|. structureNotifyMask)             mempty  -- | Checks if a window is a DOCK or DESKTOP window@@ -118,13 +133,34 @@ -- | Whenever a new dock appears, refresh the layout immediately to avoid the -- new dock. docksEventHook :: Event -> X All-docksEventHook (MapNotifyEvent {ev_window = w}) = do-    whenX ((not `fmap` (isClient w)) <&&> runQuery checkDock w) $ do-        broadcastMessage ClearGapCache-        refresh+docksEventHook (MapNotifyEvent { ev_window = w }) = do+    whenX (runQuery checkDock w <&&> (not <$> isClient w)) $ do+        strut <- getStrut w+        whenX (updateStrutCache w strut) refreshDocks     return (All True)+docksEventHook (PropertyEvent { ev_window = w+                              , ev_atom = a }) = do+    nws <- getAtom "_NET_WM_STRUT"+    nwsp <- getAtom "_NET_WM_STRUT_PARTIAL"+    when (a == nws || a == nwsp) $ do+        strut <- getStrut w+        whenX (updateStrutCache w strut) refreshDocks+    return (All True)+docksEventHook (DestroyWindowEvent {ev_window = w}) = do+    whenX (deleteFromStructCache w) refreshDocks+    return (All True) docksEventHook _ = return (All True) +docksStartupHook :: X ()+docksStartupHook = withDisplay $ \dpy -> do+    rootw <- asks theRoot+    (_,_,wins) <- io $ queryTree dpy rootw+    docks <- filterM (runQuery checkDock) wins+    forM_ docks $ \win -> do+        strut <- getStrut win+        updateStrutCache win strut+    refreshDocks+ -- | Gets the STRUT config, if present, in xmonad gap order getStrut :: Window -> X [Strut] getStrut w = do@@ -146,9 +182,7 @@ 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-    (_,_,wins) <- io $ queryTree dpy rootw-    struts <- (filter careAbout . concat) `fmap` mapM getStrut wins+    struts <- (filter careAbout . concat) `fmap` XS.gets (M.elems . fromStrutCache)      -- we grab the window attributes of the root window rather than checking     -- the width of the screen because xlib caches this info and it tends to@@ -170,12 +204,9 @@                  [Direction2D]               -> l a               -> ModifiedLayout AvoidStruts l a-avoidStrutsOn ss = ModifiedLayout $ AvoidStruts (S.fromList ss) Nothing+avoidStrutsOn ss = ModifiedLayout $ AvoidStruts (S.fromList ss) -data AvoidStruts a = AvoidStruts {-    avoidStrutsDirection :: S.Set Direction2D,-    avoidStrutsRectCache :: Maybe (S.Set Direction2D, Rectangle, Rectangle )-}  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.@@ -185,13 +216,6 @@  instance Message ToggleStruts ---- | message sent to ensure that caching the gaps won't give a wrong result--- because a new dock has been added-data ClearGapCache = ClearGapCache-  deriving (Read,Show,Typeable)-instance Message ClearGapCache- -- | 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:@@ -219,39 +243,31 @@ instance Message SetStruts  instance LayoutModifier AvoidStruts a where-    modifyLayoutWithUpdate as@(AvoidStruts ss cache) w r = do-        nr <- case cache of-            Just (ss', r', nr) | ss' == ss, r' == r -> return nr-            _ -> do-                nr <- fmap ($ r) (calcGap ss)-                setWorkarea nr-                return nr-        arranged <- runLayout w nr-        let newCache = Just (ss, r, nr)-        return (arranged, if newCache == cache-                    then Nothing-                    else Just as{ avoidStrutsRectCache = newCache } )+    modifyLayout (AvoidStruts ss) w r = do+        srect <- fmap ($ r) (calcGap ss)+        -- Ensure _NET_WORKAREA is not set.+        -- See: https://github.com/xmonad/xmonad-contrib/pull/79+        rmWorkarea+        runLayout w srect -    pureMess as@(AvoidStruts { avoidStrutsDirection = ss }) m-        | Just ToggleStruts    <- fromMessage m = Just $ as { avoidStrutsDirection = toggleAll ss }-        | Just (ToggleStrut s) <- fromMessage m = Just $ as { avoidStrutsDirection = toggleOne s ss }+    pureMess as@(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 $ as { avoidStrutsDirection = newSS }-        | Just ClearGapCache <- fromMessage m = Just $ as { avoidStrutsRectCache = Nothing }+        , newSS /= ss = Just $ AvoidStruts newSS+        | Just UpdateDocks <- fromMessage m = Just as         | 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 -setWorkarea :: Rectangle -> X ()-setWorkarea (Rectangle x y w h) = withDisplay $ \dpy -> do+rmWorkarea :: X ()+rmWorkarea = withDisplay $ \dpy -> do     a <- getAtom "_NET_WORKAREA"-    c <- getAtom "CARDINAL"     r <- asks theRoot-    io $ changeProperty32 dpy r a c propModeReplace [fi x, fi y, fi w, fi h]-+    io (deleteProperty dpy r a)  -- | (Direction, height\/width, initial pixel, final pixel). 
XMonad/Hooks/PositionStoreHooks.hs view
@@ -88,9 +88,9 @@             else do                 sc <- fromMaybe (W.current ws) <$> pointScreen (fi $ wa_x wa) (fi $ wa_y wa)                 let sr = screenRect . W.screenDetail $ sc-                sr' <- fmap ($ sr) (calcGap $ S.fromList [minBound .. maxBound])    -- take docks into account, accepting-                                                                                    -- a somewhat unfortunate inter-dependency-                                                                                    -- with 'XMonad.Hooks.ManageDocks'+                sr' <- fmap ($ sr) (calcGap $ S.fromList [minBound .. maxBound]) -- take docks into account, accepting+                                                                                       -- a somewhat unfortunate inter-dependency+                                                                                       -- with 'XMonad.Hooks.ManageDocks'                 modifyPosStore (\ps -> posStoreInsert ps w                                         (Rectangle (fi $ wa_x wa) (fi (wa_y wa) - fi decoH)                                             (fi $ wa_width wa) (decoH + fi (wa_height wa))) sr' )
XMonad/Hooks/ScreenCorners.hs view
@@ -185,6 +185,7 @@ -- >                      ] -- -- Then add layout hook:+-- -- > myLayout = screenCornerLayoutHook $ tiled ||| Mirror tiled ||| Full where -- >     tiled   = Tall nmaster delta ratio -- >     nmaster = 1
XMonad/Hooks/UrgencyHook.hs view
@@ -339,8 +339,8 @@ getNetWMState w = do     a_wmstate <- getAtom "_NET_WM_STATE"     fromMaybe [] `fmap` getProp32 a_wmstate w-    + -- 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:@@ -497,14 +497,14 @@  instance UrgencyHook BorderUrgencyHook where   urgencyHook BorderUrgencyHook { urgencyBorderColor = cs } w =-    withDisplay $ \dpy -> io $ do-      c' <- initColor dpy cs+    withDisplay $ \dpy -> do+      c' <- io (initColor dpy cs)       case c' of-        Just c -> setWindowBorder dpy w c-        _      -> hPutStrLn stderr $ concat ["Warning: bad urgentBorderColor "-                                            ,show cs-                                            ," in BorderUrgencyHook"-                                            ]+        Just c -> setWindowBorderWithFallback dpy w cs c+        _      -> io $ hPutStrLn stderr $ concat ["Warning: bad urgentBorderColor "+                                                 ,show cs+                                                 ," in BorderUrgencyHook"+                                                 ]  -- | Flashes when a window requests your attention and you can't see it. -- Defaults to a duration of five seconds, and no extra args to dzen.@@ -543,4 +543,3 @@         Just tag -> when (tag `elem` skips)                         $ adjustUrgents (delete w)         _ -> return ()-
XMonad/Layout/BinarySpacePartition.hs view
@@ -425,6 +425,7 @@  -- initially focused leaf, path from root to selected node, window ids of borders highlighting the selection data NodeRef = NodeRef { refLeaf :: Int, refPath :: [Direction2D], refWins :: [Window] } deriving (Show,Read,Eq)+noRef :: NodeRef noRef = NodeRef (-1) [] []  goToNode :: NodeRef -> Zipper a -> Maybe (Zipper a)
XMonad/Layout/Groups.hs view
@@ -274,7 +274,7 @@                results <- forM areas $ \(g, r') -> runLayout ws { W.layout = gLayout g                                                                 , W.stack = gZipper g } r' -               let hidden = map gLayout (W.integrate $ groups l) \\ map (gLayout . fst) areas+               let hidden = map gLayout (W.integrate $ groups _l) \\ map (gLayout . fst) areas                hidden' <- mapM (flip handleMessage $ SomeMessage Hide) hidden                 let placements = concatMap fst results
XMonad/Layout/Groups/Helpers.hs view
@@ -1,5 +1,5 @@ {-# OPTIONS_GHC -fno-warn-missing-signatures #-}-{-# LANGUAGE MultiParamTypeClasses, Rank2Types, ImpredicativeTypes #-}+{-# LANGUAGE MultiParamTypeClasses, Rank2Types #-}  ----------------------------------------------------------------------------- -- |@@ -178,7 +178,7 @@ -- ** Groups-specific actions  wrap :: G.ModifySpec -> X ()-wrap = sendMessage . G.Modify+wrap x = sendMessage (G.Modify x)  -- | Swap the focused group with the previous one swapGroupUp :: X ()
XMonad/Layout/Groups/Wmii.hs view
@@ -114,7 +114,7 @@ -- | Toggle whether the currently focused group should be maximized -- whenever it has focus. toggleGroupFull :: X ()-toggleGroupFull = toggleGroupFull+toggleGroupFull = toggleColumnFull  -- | Rotate the layouts in the focused group. groupToNextLayout :: X ()
XMonad/Layout/Hidden.hs view
@@ -110,7 +110,7 @@ -------------------------------------------------------------------------------- hideWindowMsg :: HiddenWindows a -> Window -> X (Maybe (HiddenWindows a)) hideWindowMsg (HiddenWindows hidden) win = do-  windows (W.delete' win)+  modify (\s -> s { windowset = W.delete' win $ windowset s })   return . Just . HiddenWindows $ hidden ++ [win]  --------------------------------------------------------------------------------@@ -130,4 +130,5 @@  -------------------------------------------------------------------------------- restoreWindow :: Window -> X ()-restoreWindow = windows . W.insertUp+restoreWindow win =+  modify (\s -> s { windowset = W.insertUp win $ windowset s })
XMonad/Layout/IfMax.hs view
@@ -14,7 +14,7 @@ -- ----------------------------------------------------------------------------- -{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, PatternGuards #-}  module XMonad.Layout.IfMax     ( -- * Usage@@ -23,6 +23,10 @@     , ifMax     ) where +import Control.Applicative((<$>))+import Control.Arrow+import qualified Data.List as L+import qualified Data.Map  as M import Data.Maybe  import XMonad@@ -47,21 +51,36 @@ data IfMax l1 l2 w = IfMax Int (l1 w) (l2 w)   deriving (Read, Show) -instance (LayoutClass l1 a, LayoutClass l2 a) => LayoutClass (IfMax l1 l2) a where+instance (LayoutClass l1 Window, LayoutClass l2 Window) => LayoutClass (IfMax l1 l2) Window where -  runLayout (W.Workspace _ (IfMax n l1 l2) s) rect = arrange (W.integrate' s)+  runLayout (W.Workspace wname (IfMax n l1 l2) s) rect = withWindowSet $ \ws -> arrange (W.integrate' s) (M.keys . W.floating $ ws)     where-      arrange [] = do l1' <- maybe l1 id `fmap` handleMessage l1 (SomeMessage ReleaseResources)-                      l2' <- maybe l2 id `fmap` handleMessage l2 (SomeMessage ReleaseResources)-                      return ([], Just $ IfMax n l1' l2')-      arrange ws | length ws <= n = do-                                    (wrs, ml1') <- runLayout (W.Workspace "" l1 s) rect+      arrange ws fw | length (ws L.\\ fw) <= n = do+                                    (wrs, ml1') <- runLayout (W.Workspace wname l1 s) rect                                     let l1' = fromMaybe l1 ml1'-                                    return (wrs, Just $ IfMax n l1' l2)-                 | otherwise      = do-                                    (wrs, ml2') <- runLayout (W.Workspace "" l2 s) rect+                                    l2' <- fromMaybe l2 <$> handleMessage l2 (SomeMessage Hide)+                                    return (wrs, Just $ IfMax n l1' l2')+                    | otherwise      = do+                                    (wrs, ml2') <- runLayout (W.Workspace wname l2 s) rect+                                    l1' <- fromMaybe l1 <$> handleMessage l1 (SomeMessage Hide)                                     let l2' = fromMaybe l2 ml2'-                                    return (wrs, Just $ IfMax n l1 l2')+                                    return (wrs, Just $ IfMax n l1' l2')++  handleMessage (IfMax n l1 l2) m | Just ReleaseResources <- fromMessage m = do+      l1' <- handleMessage l1 (SomeMessage ReleaseResources)+      l2' <- handleMessage l2 (SomeMessage ReleaseResources)+      if isNothing l1' && isNothing l2'+         then return Nothing+         else return $ Just $ IfMax n (fromMaybe l1 l1') (fromMaybe l2 l2')+  handleMessage (IfMax n l1 l2) m = do+      (allWindows, floatingWindows) <- gets ((W.integrate' . W.stack . W.workspace . W.current &&& M.keys . W.floating) . windowset)+      if length (allWindows L.\\ floatingWindows) <= n+        then do+          l1' <- handleMessage l1 m+          return $ flip (IfMax n) l2 <$> l1'+        else do+          l2' <- handleMessage l2 m+          return $ IfMax n l1 <$> l2'    description (IfMax n l1 l2) = "If number of windows is <= " ++ show n ++ ", then " ++                                 description l1 ++ ", else " ++ description l2
XMonad/Layout/LayoutBuilder.hs view
@@ -1,11 +1,26 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, PatternGuards, DeriveDataTypeable #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards         #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE ScopedTypeVariables   #-}+ ----------------------------------------------------------------------------- -- | -- Module      :  XMonad.Layout.LayoutBuilder--- Copyright   :  (c) 2009 Anders Engstrom <ankaan@gmail.com>+--+-- Copyright   :  (c) 2009 Anders Engstrom <ankaan@gmail.com>,+--                    2011 Ilya Portnov <portnov84@rambler.ru>,+--                    2015 Peter Jones <pjones@devalot.com>+-- -- License     :  BSD3-style (see LICENSE) ----- Maintainer  :  Anders Engstrom <ankaan@gmail.com>+-- Maintainer  :  Anders Engstrom <ankaan@gmail.com>,+--                Ilya Portnov <portnov84@rambler.ru>,+--                Peter Jones <pjones@devalot.com>+-- -- Stability   :  unstable -- Portability :  unportable --@@ -17,25 +32,40 @@ -- ("XMonad.Layout.LayoutHints", "XMonad.Layout.HintedGrid" etc.) -- ------------------------------------------------------------------------------ module XMonad.Layout.LayoutBuilder (   -- * Usage   -- $usage   layoutN,   layoutR,+  layoutP,   layoutAll,++  -- * Selecting Windows+  -- $selectWin+  Predicate (..),+  Proxy(..),++  -- * Messages   IncLayoutN (..),++  -- * Utilities   SubMeasure (..),   SubBox (..),   absBox,   relBox,+  LayoutB,   LayoutN, ) where +--------------------------------------------------------------------------------+import Control.Applicative ((<|>))+import Control.Monad (foldM)+import Data.Maybe import XMonad import qualified XMonad.StackSet as W-import Data.Maybe (isJust,isNothing,listToMaybe)+import XMonad.Util.WindowProperties +-------------------------------------------------------------------------------- -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: --@@ -89,56 +119,126 @@ -- -- "XMonad.Doc.Extending#Editing_key_bindings". -type WindowNum = Either Int (Rational,Rational)+--------------------------------------------------------------------------------+-- $selectWin+--+-- 'Predicate' exists because layouts are required to be serializable, and+-- "XMonad.Util.WindowProperties" is not sufficient (for example it does not+-- allow using regular expressions).+--+-- compare "XMonad.Util.Invisible" --- | 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)+-- | Type class for predicates. This enables us to manage not only Windows,+-- but any objects, for which instance Predicate is defined.+--+-- Another instance exists in XMonad.Util.WindowPropertiesRE in xmonad-extras+class Predicate p w where+  alwaysTrue     :: Proxy w -> p     -- ^ A predicate that is always True.+  checkPredicate :: p -> w -> X Bool -- ^ Check if given object (window or smth else) matches that predicate --- | 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.+instance Predicate () a where+  alwaysTrue _       = ()+  checkPredicate _ _ = return True++instance Predicate Property Window where+  alwaysTrue _   = Const True+  checkPredicate = hasProperty++--------------------------------------------------------------------------------+-- | Contains no actual data, but is needed to help select the correct instance+-- of 'Predicate'+data Proxy a = Proxy++--------------------------------------------------------------------------------+-- | Information about how to split windows between layouts.+data Limit p = LimitN Int                  -- ^ See: 'layoutN'.+             | LimitR (Rational, Rational) -- ^ See: 'layoutR'.+             | LimitP p                    -- ^ See: 'layoutP'.+             deriving (Show, Read)++--------------------------------------------------------------------------------+-- | Use one layout in the specified area for a number of windows and+-- possibly let another layout handle the rest.+data LayoutB l1 l2 p a = LayoutB+    { subFocus  :: Maybe a      -- ^ The focused window in this layout.+    , nextFocus :: Maybe a      -- ^ The focused window in the next layout.+    , limit     :: Limit p      -- ^ How to split windows between layouts.+    , box       :: SubBox       -- ^ Normal size of layout.+    , mbox      :: Maybe SubBox -- ^ Size of layout when handling all windows.+    , sub       :: l1 a         -- ^ The layout to use in this box.+    , next      :: Maybe (l2 a) -- ^ The next layout in the chain.+    } deriving (Show, Read)++--------------------------------------------------------------------------------+-- | A variant of 'LayoutB' that can't use 'layoutP'.  For backwards+-- compatibility with previous versions of LayoutBuilder.+type LayoutN l1 l2 a = LayoutB l1 l2 () a++--------------------------------------------------------------------------------+-- | 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)+       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+    -> LayoutB l2 l3 p a                 -- ^ Where to send the remaining windows+    -> LayoutB l1 (LayoutB l2 l3 p) () a -- ^ The resulting layout+layoutN num box mbox sub next = LayoutB Nothing Nothing (LimitN 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)+       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+    -> LayoutB l2 l3 p a                -- ^ Where to send the remaining windows+    -> LayoutB l1 (LayoutB l2 l3 p) p a -- ^ The resulting layout+layoutR numdiff num box mbox sub next = LayoutB Nothing Nothing (LimitR (numdiff,num)) box mbox sub (Just next) +--------------------------------------------------------------------------------+-- | Use the specified layout in the described area windows that match+-- given predicate 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.+layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a, Predicate p a, Predicate p' a) =>+       p                                 -- ^ The predicate to use+    -> 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+    -> LayoutB l2 l3 p' a                -- ^ Where to send the remaining windows+    -> LayoutB l1 (LayoutB l2 l3 p') p a -- ^ The resulting layout+layoutP prop box mbox sub next = LayoutB Nothing Nothing (LimitP prop) 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+       SubBox                -- ^ The box to place the windows in+    -> l1 a                  -- ^ The layout to use in the specified area+    -> LayoutB l1 Full () a  -- ^ The resulting layout+layoutAll box sub = LayoutB Nothing Nothing (LimitR (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@@ -148,7 +248,7 @@        -> 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@@ -157,138 +257,209 @@        -> 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, Show p, Eq a, Typeable a, Predicate p a+         ) => LayoutClass (LayoutB l1 l2 p) a where -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 _ LayoutB {..} s) rect = do+        (subs, nexts, subFocus', nextFocus') <- splitStack s limit subFocus nextFocus -        -- | 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+        let selBox = if isJust nextFocus' then box else fromMaybe box mbox -                 (sublist,sub',schange) <- handle sub subs $ calcArea selBox rect+        (sublist, sub', schange) <- handle sub subs (calcArea selBox rect) -                 (nextlist,next',nchange) <- case next of Nothing -> return ([], Nothing, False)-                                                          Just n -> do (res, l, ch) <- handle n nexts rect-                                                                       return (res, Just l, ch)+        (nextlist, next', nchange) <- case next of+          Nothing -> return ([], Nothing, False)+          Just n  -> do (res, l, ch) <- handle n nexts rect+                        return (res, Just l, ch) -                 let newlist =  if (length $ maybe [] W.up s) < (length $ W.integrate' subs)-                                then sublist++nextlist-                                else nextlist++sublist-                     newstate = if subf' /= subf || nextf' /= nextf || schange || nchange-                                then Just $ LayoutN subf' nextf' num box mbox sub' next'-                                else Nothing+        let newlist =  if length (maybe [] W.up s) < length (W.integrate' subs)+                         then sublist++nextlist+                         else nextlist++sublist -                 return (newlist, newstate)-              where-                  handle l s' r = do (res,ml) <- runLayout (W.Workspace "" l s') r-                                     l' <- return $ maybe l id ml-                                     return (res, l', isNothing ml)+            newstate = if subFocus' /= subFocus || nextFocus' /= nextFocus || schange || nchange+                         then Just $ LayoutB subFocus' nextFocus' limit box mbox sub' next'+                         else Nothing -        -- |  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+        return (newlist, newstate)+      where+          handle l s' r = do (res,ml) <- runLayout (W.Workspace "" l s') r+                             return (res, fromMaybe l ml, isNothing ml) -        -- |  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+    -- |  Propagate messages.+    handleMessage l m+        | Just (IncLayoutN n) <- fromMessage m = incLayoutN l m n+        | 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 layout = case layout of+        (LayoutB _ _ _ _ _ sub Nothing) ->+          "layoutAll " ++ description sub -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+        (LayoutB _ _ (LimitN _) _ _ sub (Just next)) ->+          "layoutN " ++ description sub ++ " " ++ description next -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 =+        (LayoutB _ _ (LimitR _) _ _ sub (Just next)) ->+          "layoutR " ++ description sub ++ " " ++ description next++        (LayoutB _ _ (LimitP _) _ _ sub (Just next)) ->+          "layoutP " ++ description sub ++ " " ++ description next++--------------------------------------------------------------------------------+-- | Increase the number of windows allowed in the focused layout.+incLayoutN :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a)+           => LayoutB l1 l2 p a+           -> SomeMessage+           -> Int+           -> X (Maybe (LayoutB l1 l2 p a))+incLayoutN layout@LayoutB {..} message n = do+    incThis <- isFocus subFocus++    if incThis+       then return $ Just layout { limit = newLimit }+       else sendNext layout message++  where+    newLimit = case limit of+      LimitN oldnum         -> LimitN (max 1 $ oldnum + n)+      LimitR (diff, oldnum) -> LimitR (diff, min 1 $ max 0 $ oldnum + fromIntegral n * diff)+      LimitP _              -> limit++--------------------------------------------------------------------------------+sendSub :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))+sendSub (LayoutB subFocus nextFocus 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+                then Just $ LayoutB subFocus nextFocus num box mbox (fromMaybe sub 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 =+--------------------------------------------------------------------------------+sendBoth :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))+sendBoth l@(LayoutB _ _ _ _ _ _ Nothing) m = sendSub l m+sendBoth (LayoutB subFocus nextFocus 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')+                then Just $ LayoutB subFocus nextFocus num box mbox (fromMaybe sub sub') (next' <|> Just 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 =+--------------------------------------------------------------------------------+sendNext :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))+sendNext (LayoutB _ _ _ _ _ _ Nothing) _ = return Nothing+sendNext (LayoutB subFocus nextFocus 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'+                then Just $ LayoutB subFocus nextFocus 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+--------------------------------------------------------------------------------+sendFocus :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))+sendFocus l@(LayoutB subFocus _ _ _ _ _ _) m = do+  foc <- isFocus subFocus +  if foc+    then sendSub  l m+    else sendNext l m++--------------------------------------------------------------------------------+-- | Check to see if the given window is currently focused. 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+                      return $ maybe False (\s -> show w == show (W.focus s)) ms +--------------------------------------------------------------------------------+calcNum :: Int -> Limit p -> Int+calcNum tot num = max 1 $ case num of LimitN i     -> i+                                      LimitR (_,r) -> ceiling $ r * fromIntegral tot+                                      LimitP _     -> 1 -calcNum :: Int -> WindowNum -> Int-calcNum tot num = max 1 $ case num of Left i -> i-                                      Right (_,r) -> ceiling $ r * fromIntegral tot+--------------------------------------------------------------------------------+-- | Split given list of objects (i.e. windows) using predicate.+splitBy :: (Predicate p a) => p -> [a] -> X ([a], [a])+splitBy prop = foldM step ([], [])+  where+    step (good, bad) w = do+      ok <- checkPredicate prop w+      return $ if ok+                then (w:good, bad)+                else (good,   w:bad) -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 | W.focus s `elem` l = Just $ W.focus s-                | maybe False (`elem` l) f = f-                | otherwise = listToMaybe l+--------------------------------------------------------------------------------+splitStack :: forall a p. (Eq a, Predicate p a)+           => Maybe (W.Stack a) -- ^ Window set.+           -> Limit p           -- ^ How to split the stack.+           -> Maybe a           -- ^ The window that was focused in this layout.+           -> Maybe a           -- ^ The window that was focused in the next layout.+           -> X (Maybe (W.Stack a), Maybe (W.Stack a), Maybe a, Maybe a)+splitStack Nothing _ _ _ = return (Nothing, Nothing, Nothing, Nothing)+splitStack (Just s) limit subFocus nextFocus =+  case limit of+    LimitN _    -> splitN+    LimitR _    -> splitN+    LimitP prop -> splitP prop +  where+    ws        = W.integrate s+    n         = calcNum (length ws) limit+    subl      = take n ws+    nextl     = drop n ws+    subFocus' xs  = foc xs subFocus+    nextFocus' xs = foc xs nextFocus++    -- Pick a new focused window if necessary.+    foc :: [a] -> Maybe a -> Maybe a+    foc [] _                           = Nothing+    foc l f | W.focus s `elem` l       = Just (W.focus s)+            | maybe False (`elem` l) f = f+            | otherwise                = listToMaybe l++    -- Split based on max number of windows.+    splitN = return ( differentiate' (subFocus' subl)   subl+                    , differentiate' (nextFocus' nextl) nextl+                    , subFocus'  subl+                    , nextFocus' nextl+                    )++    -- Split based on a predicate.+    splitP prop = do+      (this, other) <- splitBy prop ws+      return ( differentiate' (subFocus' this)   this+             , differentiate' (nextFocus' other) other+             , subFocus' this+             , nextFocus' other+             )++-------------------------------------------------------------------------------- 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'+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+    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-                                  }+    | 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/LayoutBuilderP.hs view
@@ -9,12 +9,11 @@ -- Stability   :  unstable -- Portability :  unportable ----- A layout combinator that sends windows matching given predicate to one rectangle--- and the rest to another.+-- DEPRECATED.  Use 'XMonad.Layout.LayoutBuilder' instead. -- ----------------------------------------------------------------------------- -module XMonad.Layout.LayoutBuilderP (+module XMonad.Layout.LayoutBuilderP {-# DEPRECATED "Use XMonad.Layout.LayoutBuilder instead" #-} (   LayoutP (..),   layoutP, layoutAll,   B.relBox, B.absBox,@@ -59,6 +58,7 @@  -- | Use the specified layout in the described area windows that match given predicate 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.+{-# DEPRECATED layoutP "Use XMonad.Layout.LayoutBuilder.layoutP instead." #-} layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a, Predicate p a) =>        p     -> B.SubBox                       -- ^ The box to place the windows in@@ -69,6 +69,7 @@ layoutP prop box mbox sub next = LayoutP Nothing Nothing prop box mbox sub (Just next)  -- | Use the specified layout in the described area for all remaining windows.+{-# DEPRECATED layoutAll "Use XMonad.Layout.LayoutBuilder.layoutAll instead." #-} layoutAll :: forall l1 p a. (Read a, Eq a, LayoutClass l1 a, Predicate p a) =>        B.SubBox             -- ^ The box to place the windows in     -> l1 a               -- ^ The layout to use in the specified area@@ -207,4 +208,3 @@ instance Predicate Property Window where   alwaysTrue _ = Const True   checkPredicate = hasProperty-
XMonad/Layout/Renamed.hs view
@@ -50,7 +50,7 @@                                    -- if necessary               | PrependWords String -- ^ Add a string to the left, appending a space to it if                                     -- necessary-              | Replace String -- ^ Repace with another wtring+              | Replace String -- ^ Replace with another string               | Chain [Rename a] -- ^ Apply a list of modifications in left-to-right order   deriving (Show, Read, Eq) 
+ XMonad/Layout/SortedLayout.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeSynonymInstances  #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Layout.SortedLayout+-- Copyright   :  (c) 2016 Kurt Dietrich+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  kurto@mac.com+-- Stability   :  unstable+-- Portability :  unportable+--+-- A 'LayoutModifier' that sorts the windows in another layout, given a+-- list of properties. The order of properties in the list determines+-- the order of windows in the final layout. Any unmatched windows+-- go to the end of the order.+-----------------------------------------------------------------------------++module XMonad.Layout.SortedLayout+  ( -- *Usage:+    -- $usage+  sorted+  , Property(..)+  ) where++import           Control.Monad+import           Data.Functor                 ((<$>))+import           Data.List++import           XMonad+import           XMonad.Layout.LayoutModifier+import           XMonad.StackSet              as W+import           XMonad.Util.WindowProperties++-- $usage+-- You can use this module with the following in your+-- @~\/.xmonad\/xmonad.hs@:+--+-- > import XMonad.Layout.SortedLayout+--+-- Then edit your @layoutHook@ to sort another layout (in this case, 'XMonad.Layout.Grid.Grid'):+--+-- > myLayout = sorted [ClassName "Firefox", ClassName "URxvt"] Grid+-- > main = xmonad def { layoutHook = myLayout }+--+-- For more detailed instructions on editing the layoutHook see:+--+-- "XMonad.Doc.Extending#Editing_the_layout_hook"+++-- | Modify a layout using a list of properties to sort its windows.+sorted :: [Property]+       -> l a+       -> ModifiedLayout SortedLayout l a+sorted props = ModifiedLayout . SortedLayout $ props ++ [Const True]++data WindowDescriptor = WindowDescriptor { wdSeqn :: !Integer+                                         , wdProp :: !Property+                                         , wdId   :: !Window+                                         } deriving (Show, Read)++instance Eq WindowDescriptor where+  (==) a b = wdId a == wdId b++instance Ord WindowDescriptor where+  compare a b = compare (wdSeqn a) (wdSeqn b)++data SortedLayout a = SortedLayout [Property] deriving (Show, Read)++instance LayoutModifier SortedLayout Window where+    modifyLayout (SortedLayout props) = sortLayout props+    modifierDescription _             = "Sorted"++findMatchingWindows :: Integer -> Property -> [Window] -> X [WindowDescriptor]+findMatchingWindows seqn prop wids =  fmap (fmap (WindowDescriptor seqn prop)) matching  where+  matching = filterM (hasProperty prop) wids++sortLayout :: (LayoutClass l Window)+           => [Property]+           -> W.Workspace WorkspaceId (l Window) Window+           -> Rectangle+           -> X ([(Window, Rectangle)], Maybe (l Window))+sortLayout props (W.Workspace w l r) rect = do+  let wids = W.integrate' r+  sortedWids <- map wdId . nub . sort . concat <$> zipWithM (\s p -> findMatchingWindows s p wids) [0..] props+  let sr = W.differentiate sortedWids+  runLayout (W.Workspace w l sr) rect
XMonad/Layout/Spacing.hs view
@@ -93,7 +93,7 @@     modifierDescription (SpacingWithEdge p) = "SpacingWithEdge " ++ 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)+shrinkRect p (Rectangle x y w h) = Rectangle (x+fi p) (y+fi p) (fi $ max 1 $ fi w-2*p) (fi $ max 1 $ fi h-2*p)  -- | Surrounds all windows with blank space, except when the window is the only -- visible window on the current workspace.
XMonad/Layout/Stoppable.hs view
@@ -35,6 +35,9 @@ -- (Linux-centric) approach may be used. See -- <https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt> --+-- * Note+-- This module doesn't work on programs that do fancy things with processes+-- (such as Chromium) and programs that do not set _NET_WM_PID. -----------------------------------------------------------------------------  module XMonad.Layout.Stoppable
XMonad/Layout/WindowNavigation.hs view
@@ -195,7 +195,9 @@ navigable d pt = sortby d . filter (inr d pt . snd)  sc :: Pixel -> Window -> X ()-sc c win = withDisplay $ \dpy -> io $ setWindowBorder dpy win c+sc c win = withDisplay $ \dpy -> do+    colorName <- io (pixelToString dpy c)+    setWindowBorderWithFallback dpy win colorName c  center :: Rectangle -> Point center (Rectangle x y w h) = P (fromIntegral x + fromIntegral w/2)  (fromIntegral y + fromIntegral h/2)
XMonad/Prompt.hs view
@@ -4,6 +4,7 @@ -- | -- Module      :  XMonad.Prompt -- Copyright   :  (C) 2007 Andrea Rossato, 2015 Evgeny Kurnevsky+--                    2015 Sibi Prabakaran -- License     :  BSD3 -- -- Maintainer  :  Spencer Janssen <spencerjanssen@gmail.com>@@ -90,7 +91,6 @@ import qualified Data.Map                     as M import           Data.Maybe                   (fromMaybe) import           Data.Set                     (fromList, toList)-import           System.Directory             (getAppUserDataDirectory) import           System.IO import           System.Posix.Files @@ -126,14 +126,14 @@         }  data XPConfig =-    XPC { font              :: String     -- ^ Font+    XPC { font              :: String     -- ^ Font; use the prefix @"xft:"@ for TrueType fonts         , bgColor           :: String     -- ^ Background color         , fgColor           :: String     -- ^ Font color         , fgHLight          :: String     -- ^ Font color of a highlighted completion entry         , bgHLight          :: String     -- ^ Background color of a highlighted completion entry         , borderColor       :: String     -- ^ Border color         , promptBorderWidth :: !Dimension -- ^ Border width-        , position          :: XPPosition -- ^ Position: 'Top' or 'Bottom'+        , position          :: XPPosition -- ^ Position: 'Top', 'Bottom', or 'CenteredAt'         , alwaysHighlight   :: !Bool      -- ^ Always highlight an item, overriden to True with multiple modes. This implies having *one* column of autocompletions only.         , height            :: !Dimension -- ^ Window height         , maxComplRows      :: Maybe Dimension@@ -144,12 +144,12 @@                                          -- history entries to remember         , promptKeymap      :: M.Map (KeyMask,KeySym) (XP ())                                          -- ^ Mapping from key combinations to actions-        , completionKey     :: KeySym     -- ^ Key that should trigger completion+        , completionKey     :: (KeyMask, KeySym)     -- ^ Key that should trigger completion         , changeModeKey     :: KeySym     -- ^ Key to change mode (when the prompt has multiple modes)         , defaultText       :: String     -- ^ The text by default in the prompt line         , autoComplete      :: Maybe Int  -- ^ Just x: if only one completion remains, auto-select it,-        , showCompletionOnTab :: Bool     -- ^ Only show list of completions when Tab was pressed                                           --   and delay by x microseconds+        , showCompletionOnTab :: Bool     -- ^ Only show list of completions when Tab was pressed         , searchPredicate   :: String -> String -> Bool                                           -- ^ Given the typed string and a possible                                           --   completion, is the completion valid?@@ -228,6 +228,17 @@  data XPPosition = Top                 | Bottom+                -- | Prompt will be placed in the center horizontally and+                --   in the certain place of screen vertically. If it's in the upper+                --   part of the screen, completion window will be placed below(like+                --   in 'Top') and otherwise above(like in 'Bottom')+                | CenteredAt { xpCenterY :: Rational+                             -- ^ Rational between 0 and 1, giving+                             -- y coordinate of center of the prompt relative to the screen height.+                             , xpWidth  :: Rational+                             -- ^ Rational between 0 and 1, giving+                             -- width of the prompt relatave to the screen width.+                             }                   deriving (Show,Read)  amberXPConfig, defaultXPConfig, greenXPConfig :: XPConfig@@ -242,7 +253,7 @@         , borderColor       = "white"         , promptBorderWidth = 1         , promptKeymap      = defaultXPKeymap-        , completionKey     = xK_Tab+        , completionKey     = (0,xK_Tab)         , changeModeKey     = xK_grave         , position          = Bottom         , height            = 18@@ -488,14 +499,15 @@   complKey <- gets $ completionKey . config   chgModeKey <- gets $ changeModeKey . config   c <- getCompletions+  mCleaned <- cleanMask m   when (length c > 1) $ modify (\s -> s { showComplWin = True })-  if complKey == sym+  if complKey == (mCleaned,sym)      then completionHandle c ks e      else if (sym == chgModeKey) then            do              modify setNextMode              updateWindows-          else when (t == keyPress) $ keyPressHandle m ks+          else when (t == keyPress) $ keyPressHandle mCleaned ks handle _ (ExposeEvent {ev_window = w}) = do   st <- get   when (win st == w) updateWindows@@ -506,25 +518,61 @@ completionHandle c ks@(sym,_) (KeyEvent { ev_event_type = t, ev_state = m }) = do   complKey <- gets $ completionKey . config   alwaysHlight <- gets $ alwaysHighlight . config+  mCleaned <- cleanMask m   case () of-    () | t == keyPress && sym == complKey ->-          do-            st <- get-            let updateState l = case alwaysHlight of-                  -- modify the buffer's value-                  False -> let newCommand = nextCompletion (currentXPMode st) (command st) l-                           in modify $ \s -> setCommand newCommand $ s { offset = length newCommand, highlightedCompl = Just newCommand}-                  --TODO: Scroll or paginate results-                  True -> let complIndex' = nextComplIndex st (length l)-                              highlightedCompl' = highlightedItem st { complIndex = complIndex'} c-                          in modify $ \s -> setHighlightedCompl highlightedCompl' $ s { complIndex = complIndex' }-                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+    () | t == keyPress && (mCleaned,sym) == complKey -> do+           st <- get++           let updateWins  l = redrawWindows l >> eventLoop (completionHandle l)+               updateState l = case alwaysHlight of+                 False                                           -> simpleComplete l st+                 True | Just (command st) /= highlightedCompl st -> alwaysHighlightCurrent st+                      | otherwise                                -> alwaysHighlightNext l st++           case c of+             []  -> updateWindows   >> eventLoop handle+             [x] -> updateState [x] >> getCompletions >>= updateWins+             l   -> updateState l   >> updateWins l+      | t == keyRelease && (mCleaned,sym) == complKey -> eventLoop (completionHandle c)+      | otherwise -> keyPressHandle mCleaned ks -- some other key, handle it normally+  where+    -- When alwaysHighlight is off, just complete based on what the+    -- user has typed so far.+    simpleComplete :: [String] -> XPState -> XP ()+    simpleComplete l st = do+      let newCommand = nextCompletion (currentXPMode st) (command st) l+      modify $ \s -> setCommand newCommand $+                     s { offset = length newCommand+                       , highlightedCompl = Just newCommand+                       }++    -- If alwaysHighlight is on, and this is the first use of the+    -- completion key, update the buffer so that it contains the+    -- current completion item.+    alwaysHighlightCurrent :: XPState -> XP ()+    alwaysHighlightCurrent st = do+      let newCommand = fromMaybe (command st) $ highlightedItem st c+      modify $ \s -> setCommand newCommand $+                     setHighlightedCompl (Just newCommand) $+                     s { offset = length newCommand+                       }++    -- If alwaysHighlight is on, and the user wants the next+    -- completion, move to the next completion item and update the+    -- buffer to reflect that.+    --+    --TODO: Scroll or paginate results+    alwaysHighlightNext :: [String] -> XPState -> XP ()+    alwaysHighlightNext l st = do+      let complIndex' = nextComplIndex st (length l)+          highlightedCompl' = highlightedItem st { complIndex = complIndex'} c+          newCommand = fromMaybe (command st) $ highlightedCompl'+      modify $ \s -> setHighlightedCompl highlightedCompl' $+                     setCommand newCommand $+                     s { complIndex = complIndex'+                       , offset = length newCommand+                       }+ -- some other event: go back to main loop completionHandle _ k e = handle k e @@ -662,12 +710,11 @@ keyPressHandle :: KeyMask -> KeyStroke -> XP () keyPressHandle m (ks,str) = do   km <- gets (promptKeymap . config)-  kmask <- cleanMask m -- mask is defined in ghc7-  case M.lookup (kmask,ks) km of+  case M.lookup (m,ks) km of     Just action -> action >> updateWindows     Nothing -> case str of                  "" -> eventLoop handle-                 _ -> when (kmask .&. controlMask == 0) $ do+                 _ -> when (m .&. controlMask == 0) $ do                                  let str' = if isUTF8Encoded str                                                then decodeString str                                                else str@@ -842,8 +889,12 @@   let (x,y) = case position c of                 Top -> (0,0)                 Bottom -> (0, rect_height s - height c)+                CenteredAt py w -> (floor $ (fi $ rect_width s) * ((1 - w) / 2), floor $ py * fi (rect_height s) - (fi (height c) / 2))+      width = case position c of+                CenteredAt _ w -> floor $ fi (rect_width s) * w+                _              -> rect_width s   w <- mkUnmanagedWindow d (defaultScreenOfDisplay d) rw-                      (rect_x s + x) (rect_y s + fi y) (rect_width s) (height c)+                      (rect_x s + x) (rect_y s + fi y) width (height c)   mapWindow d w   return w @@ -852,7 +903,9 @@   st <- get   let (c,(d,(w,gc))) = (config &&& dpy &&& win &&& gcon) st       scr = defaultScreenOfDisplay d-      wh = widthOfScreen scr+      wh = case position c of+             CenteredAt _ wd -> floor $ wd * fi (widthOfScreen scr)+             _               -> widthOfScreen scr       ht = height c       bw = promptBorderWidth c   Just bgcolor <- io $ initColor d (bgColor c)@@ -935,8 +988,11 @@ getComplWinDim compl = do   st <- get   let (c,(scr,fs)) = (config &&& screen &&& fontS) st-      wh = rect_width scr+      wh = case position c of+             CenteredAt _ w -> floor $ fi (rect_width scr) * w+             _ -> rect_width scr       ht = height c+      bw = promptBorderWidth c    tws <- mapM (textWidthXMF (dpy st) fs) compl   let max_compl_len =  fromIntegral ((fi ht `div` 2) + maximum tws)@@ -951,8 +1007,11 @@       actual_rows = min actual_max_number_of_rows (fi needed_rows)       actual_height = actual_rows * ht       (x,y) = case position c of-                Top -> (0,ht)-                Bottom -> (0, (0 + rem_height - actual_height))+                Top -> (0,ht - bw)+                Bottom -> (0, (0 + rem_height - actual_height + bw))+                CenteredAt py w+                  | py <= 1/2 -> (floor $ fi (rect_width scr) * ((1 - w) / 2), floor (py * fi (rect_height scr) + (fi ht)/2) - bw)+                  | otherwise -> (floor $ fi (rect_width scr) * ((1 - w) / 2), floor (py * fi (rect_height scr) - (fi ht)/2) - actual_height + bw)   (asc,desc) <- io $ textExtentsXMF fs $ head compl   let yp = fi $ (ht + fi (asc - desc)) `div` 2       xp = (asc + desc) `div` 2@@ -1039,7 +1098,7 @@ emptyHistory = M.empty  getHistoryFile :: IO FilePath-getHistoryFile = fmap (++ "/history") $ getAppUserDataDirectory "xmonad"+getHistoryFile = fmap (++ "/prompt-history") getXMonadCacheDir  readHistory :: IO History readHistory = readHist `E.catch` \(SomeException _) -> return emptyHistory@@ -1145,7 +1204,7 @@  -- | '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.+--   from the query history stored in the XMonad cache directory. historyCompletion :: ComplFunction historyCompletion = historyCompletionP (const True) 
XMonad/Prompt/Directory.hs view
@@ -16,7 +16,8 @@                              -- * Usage                              -- $usage                              directoryPrompt,-                             Dir,+                             directoryMultipleModes,+                             Dir                               ) where  import XMonad@@ -26,13 +27,23 @@ -- $usage -- For an example usage see "XMonad.Layout.WorkspaceDir" -data Dir = Dir String+data Dir = Dir String (String -> X ())  instance XPrompt Dir where-    showXPrompt (Dir x) = x+    showXPrompt (Dir x _) = x+    completionFunction _ = getDirCompl+    modeAction (Dir _ f) buf auto =+      let dir = if null auto then buf else auto+      in f dir  directoryPrompt :: XPConfig -> String -> (String -> X ()) -> X ()-directoryPrompt c prom = mkXPrompt (Dir prom) c getDirCompl+directoryPrompt c prom f = mkXPrompt (Dir prom f) c getDirCompl f++-- | A @XPType@ entry suitable for using with @mkXPromptWithModes@.+directoryMultipleModes :: String            -- ^ Prompt.+                       -> (String -> X ())  -- ^ Action.+                       -> XPType+directoryMultipleModes p f = XPT (Dir p f)  getDirCompl :: String -> IO [String] getDirCompl s = (filter notboring . lines) `fmap`
XMonad/Prompt/Pass.hs view
@@ -48,7 +48,7 @@                      , getNextCompletion                      , XPConfig                      , mkXPrompt-                     , mkComplFunFromList)+                     , searchPredicate) import System.Directory (getHomeDirectory) import System.FilePath (takeExtension, dropExtension, combine) import System.Posix.Env (getEnv)@@ -72,6 +72,11 @@ -- - how to setup the password storage, see <http://git.zx2c4.com/password-store/about/> -- +type Predicate = String -> String -> Bool++getPassCompl :: [String] -> Predicate -> String -> IO [String]+getPassCompl compls p s = do return $ filter (p s) compls+ type PromptLabel = String  data Pass = Pass PromptLabel@@ -101,7 +106,7 @@ mkPassPrompt :: PromptLabel -> (String -> X ()) -> XPConfig -> X () mkPassPrompt promptLabel passwordFunction xpconfig = do   passwords <- io (passwordStoreFolder >>= getPasswords)-  mkXPrompt (Pass promptLabel) xpconfig (mkComplFunFromList passwords) passwordFunction+  mkXPrompt (Pass promptLabel) xpconfig (getPassCompl passwords $ searchPredicate xpconfig) passwordFunction  -- | A prompt to retrieve a password from a given entry. --
+ XMonad/Prompt/Unicode.hs view
@@ -0,0 +1,99 @@+{- |+Module      :  XMonad.Prompt.Unicode+Copyright   :  (c) 2016 Joachim Breitner+License     :  BSD-style (see LICENSE)++Maintainer  :  <mail@joachim-breitner.de>+Stability   :  stable++A prompt for searching unicode characters by name and inserting them into+the clipboard.++Requires the file @\/usr\/share\/unicode\/UnicodeData.txt@ (shipped in the package+@unicode-data@ on Debian) and the @xsel@ tool.+-}++module XMonad.Prompt.Unicode (+ -- * Usage+ -- $usage+ unicodePrompt+ ) where++import qualified Data.ByteString.Char8 as BS+import Data.Char+import Data.Maybe+import Data.Ord+import Numeric+import System.Environment+import System.IO+import System.IO.Unsafe+import System.IO.Error+import Control.Arrow+import Data.List+import Text.Printf++import XMonad+import XMonad.Util.Run+import XMonad.Prompt++{- $usage++You can use this module by importing it, along with+"XMonad.Prompt", into your ~\/.xmonad\/xmonad.hs file:++> import XMonad.Prompt+> import XMonad.Prompt.Unicode++and adding an appropriate keybinding, for example:++>  , ((modm .|. controlMask, xK_u), unicodePrompt def)++-}++unicodeDataFilename :: String+unicodeDataFilename =  "/usr/share/unicode/UnicodeData.txt"++entries :: [(Char, BS.ByteString)]+entries = unsafePerformIO $ do+    datE <- tryIOError $ BS.readFile unicodeDataFilename+    case datE of+        Left e -> do+            hPutStrLn stderr $ "Could not read file \"" ++ unicodeDataFilename ++ "\""+            hPutStrLn stderr $ show e+            hPutStrLn stderr $ "Do you have unicode-data installed?"+            return []+        Right dat -> return $ sortBy (comparing (BS.length . snd)) $ parseUnicodeData dat+{-# NOINLINE entries #-}++parseUnicodeData :: BS.ByteString -> [(Char, BS.ByteString)]+parseUnicodeData = mapMaybe parseLine . BS.lines+  where+    parseLine l = do+        field1 : field2 : _ <- return $ BS.split ';' l+        [(c,"")] <- return $ readHex (BS.unpack field1)+        return (chr c, field2)++searchUnicode :: String -> [(Char, String)]+searchUnicode s = map (second BS.unpack) $ filter go entries+  where w = map BS.pack $  filter (all isAscii) $ filter ((> 1) . length) $ words $ map toUpper s+        go (c,d) = all (`BS.isInfixOf` d) w++-- | Prompt the user for a unicode character to be inserted into the paste buffer of the X server.+unicodePrompt :: XPConfig -> X ()+unicodePrompt config = mkXPrompt Unicode config unicodeCompl paste+  where+    unicodeCompl [] = return []+    unicodeCompl s = do+        return $ map (\(c,d) -> printf "%s %s" [c] d) $ take 20 $ searchUnicode s++    paste [] = return ()+    paste (c:_) = do+        runProcessWithInput "xsel" ["-i"] [c]+        return ()++data Unicode = Unicode+instance XPrompt Unicode where+    showXPrompt Unicode = "Unicode: "+    commandToComplete Unicode s = s+    nextCompletion Unicode = getNextCompletion+
XMonad/Prompt/Window.hs view
@@ -18,10 +18,16 @@     (     -- * Usage     -- $usage+    WindowPrompt(..),+    windowPrompt,+    allWindows,+    wsWindows,+    XWindowMap,++    -- * Deprecated     windowPromptGoto,     windowPromptBring,     windowPromptBringCopy,-    WindowPrompt,     ) where  import qualified Data.Map as M@@ -31,11 +37,13 @@ import XMonad.Prompt import XMonad.Actions.CopyWindow import XMonad.Actions.WindowBringer+import XMonad.Util.NamedWindows  -- $usage--- WindowPrompt brings windows to you and you to windows.--- That is to say, it pops up a prompt with window names, in case you forgot--- where you left your XChat.+-- WindowPrompt brings windows to you and you to windows. That is to+-- say, it pops up a prompt with window names, in case you forgot+-- where you left your XChat. It also offers helpers to build the+-- subset of windows which is used for the prompt completion. -- -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: --@@ -44,13 +52,14 @@ -- -- and in the keys definition: ----- > , ((modm .|. shiftMask, xK_g     ), windowPromptGoto  def)--- > , ((modm .|. shiftMask, xK_b     ), windowPromptBring def)+-- > , ((modm .|. shiftMask, xK_g     ), windowPrompt def Goto wsWindows)+-- > , ((modm .|. shiftMask, xK_b     ), windowPrompt def Bring allWindows) -- -- The autoComplete option is a handy complement here: ----- > , ((modm .|. shiftMask, xK_g     ), windowPromptGoto--- >                                            def { autoComplete = Just 500000 } )+-- > , ((modm .|. shiftMask, xK_g     ), windowPrompt+-- >                                        def { autoComplete = Just 500000 }+-- >                                        Goto allWindows) -- -- The \'500000\' is the number of microseconds to pause before sending you to -- your new window. This is useful so that you don't accidentally send some@@ -59,28 +68,50 @@ -- For detailed instruction on editing the key binding see -- "XMonad.Doc.Extending#Editing_key_bindings". -data WindowPrompt = Goto | Bring | BringCopy+-- Describe actions that can applied  on the selected window+data WindowPrompt = Goto | Bring | BringCopy | BringToMaster instance XPrompt WindowPrompt where     showXPrompt Goto      = "Go to window: "     showXPrompt Bring     = "Bring window: "+    showXPrompt BringToMaster+                          = "Bring window to master: "     showXPrompt BringCopy = "Bring a copy: "     commandToComplete _ c = c     nextCompletion      _ = getNextCompletion +-- | Deprecated. Use windowPrompt instead. windowPromptGoto, windowPromptBring, windowPromptBringCopy :: XPConfig -> X ()-windowPromptGoto  = doPrompt Goto-windowPromptBring = doPrompt Bring-windowPromptBringCopy = doPrompt BringCopy+windowPromptGoto c = windowPrompt c Goto windowMap+windowPromptBring c = windowPrompt c Bring windowMap+windowPromptBringCopy c = windowPrompt c BringCopy windowMap --- | Pops open a prompt with window titles. Choose one, and you will be--- taken to the corresponding workspace.-doPrompt :: WindowPrompt -> XPConfig -> X ()-doPrompt t c = do+-- | A helper to get the map of all windows.+allWindows :: XWindowMap+allWindows = windowMap++-- | A helper to get the map of windows of the current workspace.+wsWindows :: XWindowMap+wsWindows = withWindowSet (return . W.index) >>= winmap+    where+      winmap = fmap M.fromList . mapM pair+      pair w = do name <- fmap show $ getName w+                  return (name, w)++-- | A Map where keys are pretty printable window names and values are+-- Xmonad windows identifier.+type XWindowMap = X (M.Map String Window)++-- | Pops open a prompt with window titles belonging to+-- winmap. Choose one, and an action is applied on the+-- selected window, according to WindowPrompt.+windowPrompt :: XPConfig -> WindowPrompt -> XWindowMap -> X ()+windowPrompt c t winmap = do   a <- case t of-         Goto  -> fmap gotoAction  windowMap-         Bring -> fmap bringAction windowMap-         BringCopy -> fmap bringCopyAction windowMap-  wm <- windowMap+         Goto  -> fmap gotoAction  winmap+         Bring -> fmap bringAction winmap+         BringCopy -> fmap bringCopyAction winmap+         BringToMaster -> fmap bringToMaster winmap+  wm <- winmap   mkXPrompt t c (compList wm) a      where@@ -88,9 +119,9 @@       gotoAction       = winAction W.focusWindow       bringAction      = winAction bringWindow       bringCopyAction  = winAction bringCopyWindow+      bringToMaster    = winAction (\w s -> W.shiftMaster . W.focusWindow w $ bringWindow w s)        compList m s = return . filter (searchPredicate c s) . map fst . M.toList $ m-  -- | Brings a copy of the specified window into the current workspace. bringCopyWindow :: Window -> WindowSet -> WindowSet
XMonad/Util/CustomKeys.hs view
@@ -4,11 +4,9 @@ -- Copyright  : (c) 2007 Valery V. Vorotyntsev -- License    : BSD3-style (see LICENSE) ----- Maintainer : Valery V. Vorotynsev <valery.vv@gmail.com>--- -- Customized key bindings. ----- (See also "XMonad.Util.EZConfig" in xmonad-contrib.)+-- See also "XMonad.Util.EZConfig" in xmonad-contrib. --------------------------------------------------------------------  module XMonad.Util.CustomKeys (@@ -25,38 +23,30 @@  -- $usage ----- 1. In @~\/.xmonad\/xmonad.hs@ add:+-- In @~\/.xmonad\/xmonad.hs@ add: -- -- > import XMonad.Util.CustomKeys ----- 2. Set key bindings with 'customKeys':+-- Set key bindings with 'customKeys': -- -- > main = xmonad def { keys = customKeys delkeys inskeys } -- >     where -- >       delkeys :: XConfig l -> [(KeyMask, KeySym)] -- >       delkeys XConfig {modMask = modm} =--- >           -- we're preferring Futurama to Xinerama here--- >           [ (modm .|. m, k) | (m, k) <- zip [0, shiftMask] [xK_w, xK_e, xK_r] ]+-- >           [ (modm .|. shiftMask, xK_Return) -- > terminal+-- >           , (modm .|. shiftMask, xK_c)      -- > close the focused window+-- >           ]+-- >           +++-- >           [ (modm .|. m, k) | m <- [0, shiftMask], k <- [xK_w, xK_e, xK_r] ] -- > -- >       inskeys :: XConfig l -> [((KeyMask, KeySym), X ())] -- >       inskeys conf@(XConfig {modMask = modm}) =--- >           [ ((mod1Mask,             xK_F2  ), spawn $ terminal conf)+-- >           [ ((mod1Mask,             xK_F2  ), spawn $ terminal conf) -- mod1-f2 %! Run a terminal emulator+-- >           , ((modm,                 xK_Delete), kill) -- %! Close the focused window -- >           , ((modm .|. controlMask, xK_F11 ), spawn "xscreensaver-command -lock") -- >           , ((mod1Mask,             xK_Down), spawn "amixer set Master 1-") -- >           , ((mod1Mask,             xK_Up  ), spawn "amixer set Master 1+") -- >           ]------ 0 (/hidden feature/). You can always replace bindings map---   entirely. No need to import "CustomKeys" this time:------ > import XMonad--- > import System.Exit--- > import qualified Data.Map as M--- >--- > main = xmonad def {--- >          keys = \_ -> M.fromList [--- >                  -- Let me out of here! I want my KDE back! Help! Help!--- >                  ( (0, xK_Escape), io (exitWith ExitSuccess) ) ] }  -- | Customize 'XMonad.Config.def' -- delete needless -- shortcuts and insert those you will use.
XMonad/Util/DebugWindow.hs view
@@ -41,7 +41,15 @@   case w' of     Nothing                                   ->       return $ "(deleted window " ++ wx ++ ")"-    Just (WindowAttributes x y wid ht bw m o) -> do+    Just (WindowAttributes+      { wa_x                 = x+      , wa_y                 = y+      , wa_width             = wid+      , wa_height            = ht+      , wa_border_width      = bw+      , wa_map_state         = m+      , wa_override_redirect = o+      }) -> do       c' <- withDisplay $ \d ->             io (getWindowProperty8 d wM_CLASS w)       let c = case c' of
XMonad/Util/EZConfig.hs view
@@ -80,7 +80,7 @@ -- Note that, unlike in xmonad 0.4 and previous, you can't use modMask to refer -- to the modMask you configured earlier. You must specify mod1Mask (or -- whichever), or add your own @myModMask = mod1Mask@ line.-additionalKeys :: XConfig a -> [((ButtonMask, KeySym), X ())] -> XConfig a+additionalKeys :: XConfig a -> [((KeyMask, KeySym), X ())] -> XConfig a additionalKeys conf keyList =     conf { keys = \cnf -> M.union (M.fromList keyList) (keys conf cnf) } @@ -103,7 +103,7 @@ -- -- > main = xmonad $ def { terminal = "urxvt" } -- >                 `removeKeys` [(mod1Mask .|. shiftMask, n) | n <- [xK_1 .. xK_9]]-removeKeys :: XConfig a -> [(ButtonMask, KeySym)] -> XConfig a+removeKeys :: XConfig a -> [(KeyMask, KeySym)] -> XConfig a removeKeys conf keyList =     conf { keys = \cnf -> keys conf cnf `M.difference` M.fromList (zip keyList $ repeat ()) } 
XMonad/Util/ExtensibleState.hs view
@@ -21,6 +21,7 @@                               , remove                               , get                               , gets+                              , modified                               ) where  import Data.Typeable (typeOf,cast)@@ -115,3 +116,10 @@ -- | Remove the value from the extensible state field that has the same type as the supplied argument remove :: ExtensionClass a => a -> X () remove wit = modifyStateExts $ M.delete (show . typeOf $ wit)++modified :: (ExtensionClass a, Eq a) => (a -> a) -> X Bool+modified f = do+    v <- get+    case f v of+        v' | v' == v   -> return False+           | otherwise -> put v' >> return True
XMonad/Util/Font.hs view
@@ -29,6 +29,7 @@     , textExtentsXMF     , printStringXMF     , stringToPixel+    , pixelToString     , fi     ) where @@ -37,6 +38,8 @@ import Control.Applicative import Control.Exception as E import Data.Maybe+import Data.Bits (shiftR)+import Text.Printf (printf)  #ifdef XFT import Data.List@@ -60,6 +63,19 @@ stringToPixel d s = fromMaybe fallBack <$> io getIt     where getIt    = initColor d s           fallBack = blackPixel d (defaultScreen d)++-- | Convert a @Pixel@ into a @String@.+pixelToString :: (MonadIO m) => Display -> Pixel -> m String+pixelToString d p = do+    let cm = defaultColormap d (defaultScreen d)+    (Color _ r g b _) <- io (queryColor d cm $ Color p 0 0 0 0)+    return ("#" ++ hex r ++ hex g ++ hex b)+  where+    -- NOTE: The @Color@ type has 16-bit values for red, green, and+    -- blue, even though the actual type in X is only 8 bits wide.  It+    -- seems that the upper and lower 8-bit sections of the @Word16@+    -- values are the same.  So, we just discard the lower 8 bits.+    hex = printf "%02x" . (`shiftR` 8)  econst :: a -> IOException -> a econst = const
+ XMonad/Util/Loggers/NamedScratchpad.hs view
@@ -0,0 +1,138 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.Loggers.NamedScratchpad+-- Copyright   :  (c) Brandon S Allbery <allbery.b@gmail.com>+-- License     :  BSD-style (see LICENSE)+--+-- Maintainer  :  Brandon S Allbery <allbery.b@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- 'XMonad.Util.Loggers' for 'XMonad.Util.NamedScratchpad'+--+-----------------------------------------------------------------------------++{-# LANGUAGE DeriveDataTypeable #-}++module XMonad.Util.Loggers.NamedScratchpad (-- * Usage+                                            -- $usage+                                            nspTrackStartup+                                           ,nspTrackHook+                                           ,nspActiveIcon+                                           ,nspActive+                                           ,nspActive') where++import XMonad.Core+import Graphics.X11.Xlib (Window)+import Graphics.X11.Xlib.Extras (Event(..))+import XMonad.Util.Loggers (Logger)+import XMonad.Util.NamedScratchpad (NamedScratchpad(..))+import qualified XMonad.Util.ExtensibleState as XS+import Data.Monoid (All(..))+import Data.Char (chr)+import Control.Monad (forM, foldM)+import qualified Data.IntMap as M+import qualified XMonad.StackSet as W (allWindows)++-- $usage+-- This is a set of 'Logger's for 'NamedScratchpad's.+-- It provides a 'startupHook' and 'handleEventHook' to keep track of+-- 'NamedScratchpad's, and several possible 'Logger's for use in+-- 'XMonad.Hooks.DynamicLog' 'ppExtras'.+--+-- You must add 'nspTrackStartup' to your 'startupHook' to initialize+-- 'NamedScratchpad' tracking and to detect any currently running+-- 'NamedScratchpad's on restart, and 'nspTrackHook' to your 'handleEventHook'+-- to track the coming and going of 'NamedScratchpad's.+--+-- Why would you want to do this? If you aren't using 'EwmhDesktops', this+-- gives you a way to see what 'NamedScratchpad's are running. If you are+-- using 'EwmhDesktops' then you can get that from a taskbar... but you may+-- have noticed that selecting the window from the taskbar moves you to+-- the 'NSP' workspace instead of moving the window to the current workspace.+-- (This is difficult to change; "minimizing" by moving it back to 'NSP'+-- is even harder.)+-- I hide the 'NamedScratchpad's from the taskbar and use this to track+-- them instead (see 'XMonad.Util.NoTaskbar').++-- The extension data for tracking NSP windows+data NSPTrack = NSPTrack [Maybe Window] deriving Typeable+instance ExtensionClass NSPTrack where+  initialValue = NSPTrack []++-- | 'startupHook' to initialize scratchpad activation tracking+--+-- > , startupHook = ... <+> nspTrackStartup scratchpads+--+-- If you kickstart the 'logHook', do it /after/ 'nspTrackStartup'!+nspTrackStartup :: [NamedScratchpad] -> X ()+nspTrackStartup ns = do+  let ns'i = M.fromList $ zip [0..] $ map (const Nothing) ns+  ns' <- withWindowSet $ foldM (isSp ns) ns'i . W.allWindows+  XS.put (NSPTrack (map snd $ M.toAscList ns'))++isSp :: [NamedScratchpad] -> M.IntMap (Maybe Window) -> Window -> X (M.IntMap (Maybe Window))+isSp ns ws w = do+  n <- runQuery (scratchpadWindow ns) w+  return $ case n of+            Nothing -> ws+            Just n' -> M.insert n' (Just w) ws++scratchpadWindow :: [NamedScratchpad] -> Query (Maybe Int)+scratchpadWindow ns = foldM sp' Nothing (zip [0..] ns)+  where sp' :: Maybe Int -> (Int,NamedScratchpad) -> Query (Maybe Int)+        sp' r@(Just _) _              = return r+        sp' Nothing    (n,NS _ _ q _) = q >>= \p -> return $ if p then Just n else Nothing++-- | 'handleEventHook' to track scratchpad activation/deactivation+--+-- > , handleEventHook = ... <+> nspTrackHook scratchpads+nspTrackHook :: [NamedScratchpad] -> Event -> X All+nspTrackHook _ (DestroyWindowEvent {ev_window = w}) = do+  XS.modify $ \(NSPTrack ws) -> NSPTrack $ map (\sw -> if sw == Just w then Nothing else sw) ws+  return (All True)+nspTrackHook ns (ConfigureRequestEvent {ev_window = w}) = do+  NSPTrack ws <- XS.get+  ws' <- forM (zip3 [0..] ws ns) $ \(_,w',NS _ _ q _) -> do+    p <- runQuery q w+    return $ if p then Just w else w'+  XS.put $ NSPTrack ws'+  return (All True)+nspTrackHook _ _ = return (All True)++-- | 'Logger' for scratchpads' state, using Unicode characters as "icons".+--+-- > , ppExtras = [..., nspActive' iconChars showActive showInactive, ...]+nspActiveIcon :: [Char] -> (String -> String) -> (String -> String) -> Logger+nspActiveIcon icns act inact = do+  NSPTrack ws <- XS.get+  return $ if null ws+            then Nothing+            else let icon' n = if n < length icns then icns !! n else '\NUL'+                     icon  n = let c = icon' n+                                in [if c == '\NUL' then chr (0x2460 + n) else c]+                     ckact n w = let icn = icon n+                                  in case w of+                                      Nothing -> inact icn+                                      Just _  -> act   icn+                     s = unwords $ zipWith ckact [0..] ws+                  in Just s++-- | 'Logger' with String-s (and no defaults)+--+-- > , ppExtras = [..., nspActive iconStrs showActive showInactive, ...]+nspActive :: [String] -> (String -> String) -> (String -> String) -> Logger+nspActive icns act inact = do+  NSPTrack ws <- XS.get+  return $ if null ws+            then Nothing+            else let  ckact n w = let icn = icns !! n+                                    in case w of+                                        Nothing -> inact icn+                                        Just _  -> act   icn+                      s = unwords $ zipWith ckact [0..] ws+                  in Just s++-- | Variant of the above getting the String-s from the 'NamedScratchpad's+nspActive' :: [NamedScratchpad] -> (String -> String) -> (String -> String) -> Logger+nspActive' ns = nspActive (map name ns)
+ XMonad/Util/NoTaskbar.hs view
@@ -0,0 +1,33 @@+module XMonad.Util.NoTaskbar (-- * Usage+                              -- $usage+                              noTaskbar+                             ,markNoTaskbar) where++import XMonad.Core+import XMonad.ManageHook+import Graphics.X11.Xlib (Window)+import Graphics.X11.Xlib.Atom (aTOM)+import Graphics.X11.Xlib.Extras (changeProperty32+                                ,propModePrepend)+import Control.Monad.Reader (ask)++-- $usage+-- Utility functions to hide windows from pagers and taskbars. Mostly useful+-- when EWMH doesn't do what you intend (e.g. for 'NamedScratchpad' windows you+-- probably don't want to be dumped into the 'NSP' workspace).++-- | A 'ManageHook' to mark a window to not be shown in pagers or taskbars.+noTaskbar :: ManageHook+noTaskbar = ask >>= (>> idHook) . liftX . markNoTaskbar++-- | An 'X' action to mark a window to not be shown in pagers or taskbars.+markNoTaskbar :: Window -> X ()+markNoTaskbar w = withDisplay $ \d -> do+                    ws <- getAtom "_NET_WM_STATE"+                    ntb <- getAtom "_NET_WM_STATE_SKIP_TASKBAR"+                    npg <- getAtom "_NET_WM_STATE_SKIP_PAGER"+                    io $ changeProperty32 d w ws aTOM propModePrepend [fi ntb,fi npg]++-- sigh+fi :: (Integral i, Num n) => i -> n+fi = fromIntegral
XMonad/Util/Run.hs view
@@ -94,7 +94,7 @@ -- -- to the top of your file) or use seconds in prefix form: ----- > 5.5 seconds+-- > seconds 5.5 seconds :: Rational -> Int seconds = fromEnum . (* 1000000) 
+ XMonad/Util/TreeZipper.hs view
@@ -0,0 +1,177 @@+{-# LANGUAGE RecordWildCards #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Actions.TreeSelect+-- Copyright   :  (c) Tom Smeets <tom.tsmeets@gmail.com>+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  Tom Smeets <tom.tsmeets@gmail.com>+-- Stability   :  unstable+-- Portability :  unportable+--+-- <https://wiki.haskell.org/Zipper Zipper> over the "Data.Tree" data structure.+-- This module is based on <http://hackage.haskell.org/package/rosezipper rosezipper>.+--+-----------------------------------------------------------------------------++module XMonad.Util.TreeZipper(+    -- * Data structure+      TreeZipper(..)+    , cursor++    -- * Conversion+    , fromForest+    , toForest+    , getSubForest++    -- * Navigation+    , rootNode+    , parent+    , children+    , nextChild+    , previousChild++    -- * Utils+    , nodeDepth+    , nodeIndex+    , followPath+    , findChild++    , isLeaf+    , isRoot+    , isLast+    , isFirst+    ) where++import Data.Tree++-- | A <https://wiki.haskell.org/Zipper Zipper> over the "Data.Tree" data structure.+data TreeZipper a = TreeZipper { tz_current :: Tree a -- ^ the currently focused sub-tree under the cursor+                               , tz_before  :: Forest a -- ^ all sub-tree's to the /left/ of the cursor that have the same parent+                               , tz_after   :: Forest a -- ^ all sub-tree's to the /right/ of the cursor that have the same parent+                               , tz_parents :: [(Forest a, a, Forest a)] -- ^ list zippers for each parent level, the first element is the current parent+                               }+-- ^ Very crappy visualization of the 'TreeZipper' data structure+--+-- @+--              (tz_parents)+--        ([*],       *, [*])+--        ([*, *],    *, [])+--        ([],        *                  [*,   *])+--                    |                   |    |+--   +-------+--------+-------+------+  +-*-+  *+--   |       |        |       |      |  |   |+--  (tz_before) (tz_current) (tz_after) *   *+--   |       |                |      |+-- +-*-+     *                *      *+-- |   |+-- *   *+-- @++-- | Get the highlighted value+cursor :: TreeZipper a -> a+cursor = rootLabel . tz_current++-- | Create a 'TreeZipper' from a list of 'Data.Tree.Tree's focused on the first element+fromForest :: Forest a -> TreeZipper a+fromForest [] = error "XMonad.Util.TreeZipper.fromForest: can't create a TreeZipper from an empty list!"+fromForest (x:xs) = TreeZipper { tz_current = x+                               , tz_before  = []+                               , tz_after   = xs+                               , tz_parents = []+                               }++-- | Convert the entire zipper back to a 'Data.Tree.Forest'+toForest :: TreeZipper a -> Forest a+toForest = getSubForest . rootNode++-- | Create a 'Data.Tree.Forest' from all the children of the current parent+getSubForest :: TreeZipper a -> Forest a+getSubForest TreeZipper{..} = reverse tz_before ++ tz_current : tz_after++-- | Go to the upper most node such that+-- nothing is before nor above the cursor+rootNode :: TreeZipper a -> TreeZipper a+rootNode = f+  where+    f z = maybe (g z) f $ parent z+    g z = maybe z g $ previousChild z++-- | Move to the parent node+parent :: TreeZipper a -> Maybe (TreeZipper a)+parent t = case tz_parents t of+    (xs,a,ys) : ps -> Just+        TreeZipper { tz_current  = Node a (reverse (tz_before t) ++ tz_current t : tz_after t)+                   , tz_before   = xs+                   , tz_after    = ys+                   , tz_parents  = ps+                   }+    [] -> Nothing++-- | Move the cursor one level down to the first node+children :: TreeZipper a -> Maybe (TreeZipper a)+children z = case subForest $ tz_current z of+    (n:xs) -> Just+        TreeZipper { tz_current = n+                   , tz_before  = []+                   , tz_after   = xs+                   , tz_parents = (tz_before z, cursor z, tz_after z) : tz_parents z+                   }+    [] -> Nothing++-- | Go to the next child node+nextChild :: TreeZipper a -> Maybe (TreeZipper a)+nextChild z = case tz_after z of+    (n:xs) -> Just+        TreeZipper { tz_current = n+                   , tz_before  = tz_current z : tz_before z+                   , tz_after   = xs+                   , tz_parents = tz_parents z+                   }+    [] -> Nothing++-- | Go to the previous child node+previousChild :: TreeZipper a -> Maybe (TreeZipper a)+previousChild z = case tz_before z of+    (n:xs) -> Just+        TreeZipper { tz_current = n+                   , tz_before  = xs+                   , tz_after   = tz_current z : tz_after z+                   , tz_parents = tz_parents z+                   }+    [] -> Nothing++-- | How many nodes are above this one?+nodeDepth :: TreeZipper a -> Int+nodeDepth = length . tz_parents++-- | How many nodes are before the cursor? (on the current level)+nodeIndex :: TreeZipper a -> Int+nodeIndex = length . tz_before++-- | follow a Path specified by the list of nodes+followPath :: Eq b => (a -> b) -> [b] -> TreeZipper a -> Maybe (TreeZipper a)+followPath _ []     z = Just z+followPath f [x]    z = findChild (\y -> f y == x) z+followPath f (x:xs) z = findChild (\y -> f y == x) z >>= children >>= followPath f xs++-- | go to the first node next to the cursor that matches+findChild :: (a -> Bool) -> TreeZipper a -> Maybe (TreeZipper a)+findChild f z | f (cursor z) = Just z+              | otherwise    = nextChild z >>= findChild f++-- | Check whenther this is a leaf node+isLeaf :: TreeZipper a -> Bool+isLeaf = null . subForest . tz_current++-- | Check whenther this is a leaf node+isRoot :: TreeZipper a -> Bool+isRoot = null . tz_parents++-- | Check whenther this the last child+isLast :: TreeZipper a -> Bool+isLast = null . tz_after++-- | Check whenther this the first child+isFirst :: TreeZipper a -> Bool+isFirst = null . tz_before
+ XMonad/Util/Ungrab.hs view
@@ -0,0 +1,43 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  XMonad.Util.Ungrab+-- Copyright   :  (c) 2016 Brandon S Allbery+-- License     :  BSD-style (see xmonad/LICENSE)+--+-- Maintainer  :  allbery.b@gmail.com+-- Stability   :  unstable+-- Portability :  unportable+--+-- Allow releasing xmonad's keyboard grab+--+-----------------------------------------------------------------------------++module XMonad.Util.Ungrab+    ( -- * Usage:+      -- $usage+      unGrab+    ) where++import Graphics.X11.Xlib.Extras (currentTime)+import Graphics.X11.Xlib.Misc (ungrabKeyboard, ungrabPointer)+import XMonad.Core++-- $usage+-- Start a keyboard action with this if it is going to run something+-- that needs to do a keyboard, pointer, or server grab. For example,+--+-- > , ((modm .|. controlMask, xK_p), unGrab >> spawn "scrot")+--+-- (Other examples are screen lockers and "gksu".)+-- This avoids needing to insert a pause/sleep before running the+-- command.+--+-- xmonad retains the keyboard grab during key actions because if they+-- use a Submap, they need the keyboard to be grabbed, and if they had+-- to assert their own grab then the asynchronous nature of X11 allows+-- race conditions between xmonad, other clients, and the X server that+-- would cause keys to sometimes be "leaked" to the focused window.++-- | Release xmonad's keyboard grab, so other grabbers can do their thing.+unGrab :: X ()+unGrab = withDisplay $ \d -> io (ungrabKeyboard d currentTime >> ungrabPointer d currentTime)
XMonad/Util/XUtils.hs view
@@ -28,6 +28,7 @@     , paintAndWrite     , paintTextAndIcons     , stringToPixel+    , pixelToString     , fi     ) where @@ -208,4 +209,3 @@            set_background_pixel  attributes p            createWindow d rw x y w h 0 (defaultDepthOfScreen s)                         inputOutput visual attrmask attributes-
xmonad-contrib.cabal view
@@ -1,5 +1,5 @@ name:               xmonad-contrib-version:            0.12+version:            0.13 homepage:           http://xmonad.org/ synopsis:           Third party extensions for xmonad description:@@ -35,10 +35,7 @@ build-type:         Simple bug-reports:        https://github.com/xmonad/xmonad-contrib/issues -tested-with:-                    GHC==7.6.3,-                    GHC==7.8.4,-                    GHC==7.10.2+tested-with: GHC==7.6.3, GHC==7.8.4, GHC==7.10.3, GHC==8.0.1  source-repository head   type:     git@@ -54,20 +51,21 @@   default: False  library-    build-depends: base >= 3 && < 5,-                    containers,-                    directory,-                    extensible-exceptions,-                    filepath,-                    old-locale,-                    old-time,-                    process,-                    random,-                    mtl >= 1 && < 3,-                    unix,-                    X11>=1.6.1 && < 1.7,-                    xmonad>=0.12   && < 0.13,-                    utf8-string+    build-depends: base >= 4.5 && < 5,+                   bytestring >= 0.10 && < 0.11,+                   containers >= 0.5 && < 0.6,+                   directory,+                   extensible-exceptions,+                   filepath,+                   old-locale,+                   old-time,+                   process,+                   random,+                   mtl >= 1 && < 3,+                   unix,+                   X11>=1.6.1 && < 1.9,+                   xmonad>=0.13   && < 0.14,+                   utf8-string      if flag(use_xft)         build-depends: X11-xft >= 0.2@@ -82,9 +80,6 @@     if impl(ghc >= 6.12.1)         ghc-options:    -fno-warn-unused-do-bind -    if impl (ghc == 6.10.1) && arch (x86_64)-        ghc-options:    -O0-     exposed-modules:    XMonad.Doc                         XMonad.Doc.Configuring                         XMonad.Doc.Extending@@ -136,6 +131,7 @@                         XMonad.Actions.SwapWorkspaces                         XMonad.Actions.TagWindows                         XMonad.Actions.TopicSpace+                        XMonad.Actions.TreeSelect                         XMonad.Actions.UpdateFocus                         XMonad.Actions.UpdatePointer                         XMonad.Actions.Warp@@ -267,6 +263,7 @@                         XMonad.Layout.SimpleFloat                         XMonad.Layout.Simplest                         XMonad.Layout.SimplestFloat+                        XMonad.Layout.SortedLayout                         XMonad.Layout.Spacing                         XMonad.Layout.Spiral                         XMonad.Layout.Square@@ -299,6 +296,7 @@                         XMonad.Prompt.Shell                         XMonad.Prompt.Ssh                         XMonad.Prompt.Theme+                        XMonad.Prompt.Unicode                         XMonad.Prompt.Window                         XMonad.Prompt.Workspace                         XMonad.Prompt.XMonad@@ -313,9 +311,11 @@                         XMonad.Util.Image                         XMonad.Util.Invisible                         XMonad.Util.Loggers+                        XMonad.Util.Loggers.NamedScratchpad                         XMonad.Util.NamedActions                         XMonad.Util.NamedScratchpad                         XMonad.Util.NamedWindows+                        XMonad.Util.NoTaskbar                         XMonad.Util.Paste                         XMonad.Util.PositionStore                         XMonad.Util.RemoteWindows@@ -328,7 +328,9 @@                         XMonad.Util.StringProp                         XMonad.Util.Themes                         XMonad.Util.Timer+                        XMonad.Util.TreeZipper                         XMonad.Util.Types+                        XMonad.Util.Ungrab                         XMonad.Util.WindowProperties                         XMonad.Util.WindowState                         XMonad.Util.WorkspaceCompare