xmonad

Portability | not portable, uses cunning newtype deriving
Stability | unstable
Maintainer | spencerjanssen@gmail.com

XMonad.Core

Description

The `X` monad, a state monad transformer over `IO`, for the window manager state, and support routines.

Synopsis

- data X a
- type WindowSet = StackSet WorkspaceId (Layout Window) Window ScreenId ScreenDetail
- type WindowSpace = Workspace WorkspaceId (Layout Window) Window
- type WorkspaceId = String
- newtype ScreenId = S Int
- data ScreenDetail = SD {
  - screenRect :: !Rectangle
  }
- data XState = XState {
  - windowset :: !WindowSet
  - mapped :: !(Set Window)
  - waitingUnmap :: !(Map Window Int)
  - dragging :: !(Maybe (Position -> Position -> X (), X ()))
  - numberlockMask :: !KeyMask
  - extensibleState :: !(Map String (Either String StateExtension))
  }
- data XConf = XConf {
  - display :: Display
  - config :: !(XConfig Layout)
  - theRoot :: !Window
  - normalBorder :: !Pixel
  - focusedBorder :: !Pixel
  - keyActions :: !(Map (KeyMask, KeySym) (X ()))
  - buttonActions :: !(Map (KeyMask, Button) (Window -> X ()))
  - mouseFocused :: !Bool
  - mousePosition :: !(Maybe (Position, Position))
  }
- data XConfig l = XConfig {
  - normalBorderColor :: !String
  - focusedBorderColor :: !String
  - terminal :: !String
  - layoutHook :: !(l Window)
  - manageHook :: !ManageHook
  - handleEventHook :: !(Event -> X All)
  - workspaces :: ![String]
  - modMask :: !KeyMask
  - keys :: !(XConfig Layout -> Map (ButtonMask, KeySym) (X ()))
  - mouseBindings :: !(XConfig Layout -> Map (ButtonMask, Button) (Window -> X ()))
  - borderWidth :: !Dimension
  - logHook :: !(X ())
  - startupHook :: !(X ())
  - focusFollowsMouse :: !Bool
  }
- class Show (layout a) => LayoutClass layout a where
  - runLayout :: Workspace WorkspaceId (layout a) a -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
  - doLayout :: layout a -> Rectangle -> Stack a -> X ([(a, Rectangle)], Maybe (layout a))
  - pureLayout :: layout a -> Rectangle -> Stack a -> [(a, Rectangle)]
  - emptyLayout :: layout a -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
  - handleMessage :: layout a -> SomeMessage -> X (Maybe (layout a))
  - pureMessage :: layout a -> SomeMessage -> Maybe (layout a)
  - description :: layout a -> String
- data Layout a = forall l . (LayoutClass l a, Read (l a)) => Layout (l a)
- readsLayout :: Layout a -> String -> [(Layout a, String)]
- class Typeable a
- class Typeable a => Message a
- data SomeMessage = forall a . Message a => SomeMessage a
- fromMessage :: Message m => SomeMessage -> Maybe m
- data LayoutMessages
  - = Hide
  - | ReleaseResources
- data StateExtension
  - = forall a . ExtensionClass a => StateExtension a
  - | forall a . (Read a, Show a, ExtensionClass a) => PersistentExtension a
- class Typeable a => ExtensionClass a where
  - initialValue :: a
  - extensionType :: a -> StateExtension
- runX :: XConf -> XState -> X a -> IO (a, XState)
- catchX :: X a -> X a -> X a
- userCode :: X a -> X (Maybe a)
- userCodeDef :: a -> X a -> X a
- io :: MonadIO m => IO a -> m a
- catchIO :: MonadIO m => IO () -> m ()
- installSignalHandlers :: MonadIO m => m ()
- uninstallSignalHandlers :: MonadIO m => m ()
- withDisplay :: (Display -> X a) -> X a
- withWindowSet :: (WindowSet -> X a) -> X a
- isRoot :: Window -> X Bool
- runOnWorkspaces :: (WindowSpace -> X WindowSpace) -> X ()
- getAtom :: String -> X Atom
- spawn :: MonadIO m => String -> m ()
- spawnPID :: MonadIO m => String -> m ProcessID
- xfork :: MonadIO m => IO () -> m ProcessID
- getXMonadDir :: MonadIO m => m String
- recompile :: MonadIO m => Bool -> m Bool
- trace :: MonadIO m => String -> m ()
- whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()
- whenX :: X Bool -> X () -> X ()
- atom_WM_STATE :: X Atom
- atom_WM_PROTOCOLS :: X Atom
- atom_WM_DELETE_WINDOW :: X Atom
- type ManageHook = Query (Endo WindowSet)
- newtype Query a = Query (ReaderT Window X a)
- runQuery :: Query a -> Window -> X a

# Documentation

data X a

The X monad, `ReaderT` and `StateT` transformers over `IO` encapsulating the window manager configuration and state, respectively.

Dynamic components may be retrieved with `get`, static components with `ask`. With newtype deriving we get readers and state monads instantiated on `XConf` and `XState` automatically.

Instances

Monad X |
Functor X |
Typeable1 X |
Applicative X |
MonadIO X |
MonadState XState X |
MonadReader XConf X |
Monoid a => Monoid (X a) |

type WindowSet = StackSet WorkspaceId (Layout Window) Window ScreenId ScreenDetail

type WindowSpace = Workspace WorkspaceId (Layout Window) Window

type WorkspaceId = String

Virtual workspace indices

newtype ScreenId

Physical screen indices

Constructors

S Int |

Instances

Enum ScreenId |
Eq ScreenId |
Integral ScreenId |
Num ScreenId |
Ord ScreenId |
Read ScreenId |
Real ScreenId |
Show ScreenId |

data ScreenDetail

The `Rectangle` with screen dimensions

Constructors

SD |
Fields screenRect :: !Rectangle

Instances

Eq ScreenDetail |
Read ScreenDetail |
Show ScreenDetail |

data XState

XState, the (mutable) window manager state.

Constructors

XState |
Fields windowset :: !WindowSet workspace list mapped :: !(Set Window) the Set of mapped windows waitingUnmap :: !(Map Window Int) the number of expected UnmapEvents dragging :: !(Maybe (Position -> Position -> X (), X ())) numberlockMask :: !KeyMask The numlock modifier extensibleState :: !(Map String (Either String StateExtension)) stores custom state information. The module XMonad.Utils.ExtensibleState in xmonad-contrib provides additional information and a simple interface for using this.

Instances

MonadState XState X |

data XConf

XConf, the (read-only) window manager configuration.

Constructors

XConf |
Fields display :: Display the X11 display config :: !(XConfig Layout) initial user configuration theRoot :: !Window the root window normalBorder :: !Pixel border color of unfocused windows focusedBorder :: !Pixel border color of the focused window keyActions :: !(Map (KeyMask, KeySym) (X ())) a mapping of key presses to actions buttonActions :: !(Map (KeyMask, Button) (Window -> X ())) a mapping of button presses to actions mouseFocused :: !Bool was refocus caused by mouse action? mousePosition :: !(Maybe (Position, Position)) position of the mouse according to the event currently being processed

Instances

MonadReader XConf X |

data XConfig l

Constructors

XConfig |
Fields normalBorderColor :: !String Non focused windows border color. Default: "#dddddd" focusedBorderColor :: !String Focused windows border color. Default: "#ff0000" terminal :: !String The preferred terminal application. Default: "xterm" layoutHook :: !(l Window) The available layouts manageHook :: !ManageHook The action to run when a new window is opened handleEventHook :: !(Event -> X All) Handle an X event, returns (All True) if the default handler should also be run afterwards. mappend should be used for combining event hooks in most cases. workspaces :: ![String] The list of workspaces' names modMask :: !KeyMask the mod modifier keys :: !(XConfig Layout -> Map (ButtonMask, KeySym) (X ())) The key binding: a map from key presses and actions mouseBindings :: !(XConfig Layout -> Map (ButtonMask, Button) (Window -> X ())) The mouse bindings borderWidth :: !Dimension The border width logHook :: !(X ()) The action to perform when the windows set is changed startupHook :: !(X ()) The action to perform on startup focusFollowsMouse :: !Bool Whether window entry events can change focus

class Show (layout a) => LayoutClass layout a where

Every layout must be an instance of `LayoutClass`, which defines the basic layout operations along with a sensible default for each.

Minimal complete definition:

- `runLayout` || ((`doLayout` || `pureLayout`) && `emptyLayout`), and
- `handleMessage` || `pureMessage`

You should also strongly consider implementing `description`, although it is not required.

Note that any code which uses `LayoutClass` methods should only ever call `runLayout`, `handleMessage`, and `description`! In other words, the only calls to `doLayout`, `pureMessage`, and other such methods should be from the default implementations of `runLayout`, `handleMessage`, and so on. This ensures that the proper methods will be used, regardless of the particular methods that any `LayoutClass` instance chooses to define.

Methods

runLayout :: Workspace WorkspaceId (layout a) a -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))

By default, `runLayout` calls `doLayout` if there are any windows to be laid out, and `emptyLayout` otherwise. Most instances of `LayoutClass` probably do not need to implement `runLayout`; it is only useful for layouts which wish to make use of more of the `Workspace` information (for example, XMonad.Layout.PerWorkspace).

doLayout :: layout a -> Rectangle -> Stack a -> X ([(a, Rectangle)], Maybe (layout a))

Given a `Rectangle` in which to place the windows, and a `Stack` of windows, return a list of windows and their corresponding Rectangles. If an element is not given a Rectangle by `doLayout`, then it is not shown on screen. The order of windows in this list should be the desired stacking order.

Also possibly return a modified layout (by returning `Just newLayout`), if this layout needs to be modified (e.g. if it keeps track of some sort of state). Return `Nothing` if the layout does not need to be modified.

Layouts which do not need access to the `X` monad (`IO`, window manager state, or configuration) and do not keep track of their own state should implement `pureLayout` instead of `doLayout`.

pureLayout :: layout a -> Rectangle -> Stack a -> [(a, Rectangle)]

This is a pure version of `doLayout`, for cases where we don't need access to the `X` monad to determine how to lay out the windows, and we don't need to modify the layout itself.

emptyLayout :: layout a -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))

`emptyLayout` is called when there are no windows.

handleMessage :: layout a -> SomeMessage -> X (Maybe (layout a))

`handleMessage` performs message handling. If `handleMessage` returns `Nothing`, then the layout did not respond to the message and the screen is not refreshed. Otherwise, `handleMessage` returns an updated layout and the screen is refreshed.

Layouts which do not need access to the `X` monad to decide how to handle messages should implement `pureMessage` instead of `handleMessage` (this restricts the risk of error, and makes testing much easier).

pureMessage :: layout a -> SomeMessage -> Maybe (layout a)

Respond to a message by (possibly) changing our layout, but taking no other action. If the layout changes, the screen will be refreshed.

description :: layout a -> String

This should be a human-readable string that is used when selecting layouts by name. The default implementation is `show`, which is in some cases a poor default.

Instances

LayoutClass Layout Window |
LayoutClass Tall a |
LayoutClass Full a |
LayoutClass l a => LayoutClass (Mirror l) a |
(LayoutClass l a, LayoutClass r a) => LayoutClass (Choose l r) a |

data Layout a

An existential type that can hold any object that is in `Read` and `LayoutClass`.

Constructors

forall l . (LayoutClass l a, Read (l a)) => Layout (l a) |

Instances

LayoutClass Layout Window |
Show (Layout a) |

readsLayout :: Layout a -> String -> [(Layout a, String)]

Using the `Layout` as a witness, parse existentially wrapped windows from a `String`.

class Typeable a

The class `Typeable` allows a concrete representation of a type to be calculated.

Instances

Typeable Bool |
Typeable Char |
Typeable Double |
Typeable Float |
Typeable Int |
Typeable Int8 |
Typeable Int16 |
Typeable Int32 |
Typeable Int64 |
Typeable Integer |
Typeable Ordering |
Typeable RealWorld |
Typeable Word |
Typeable Word8 |
Typeable Word16 |
Typeable Word32 |
Typeable Word64 |
Typeable () |
Typeable XErrorEvent |
Typeable XComposeStatus |
Typeable XTextProperty |
Typeable FdSet |
Typeable TimeZone |
Typeable GCValues |
Typeable Event |
Typeable XEvent |
Typeable Display |
Typeable Screen |
Typeable Visual |
Typeable GC |
Typeable SetWindowAttributes |
Typeable Image |
Typeable Point |
Typeable Rectangle |
Typeable Arc |
Typeable Segment |
Typeable Color |
Typeable Handle |
Typeable Handle__ |
Typeable Version |
Typeable DataType |
Typeable CDev |
Typeable CIno |
Typeable CMode |
Typeable COff |
Typeable CPid |
Typeable CSsize |
Typeable CGid |
Typeable CNlink |
Typeable CUid |
Typeable CCc |
Typeable CSpeed |
Typeable CTcflag |
Typeable CRLim |
Typeable Fd |
Typeable PatternMatchFail |
Typeable RecSelError |
Typeable RecConError |
Typeable RecUpdError |
Typeable NoMethodError |
Typeable NonTermination |
Typeable NestedAtomically |
Typeable BlockedIndefinitelyOnMVar |
Typeable BlockedIndefinitelyOnSTM |
Typeable Deadlock |
Typeable AssertionFailed |
Typeable AsyncException |
Typeable ArrayException |
Typeable ExitCode |
Typeable WordPtr |
Typeable IntPtr |
Typeable CChar |
Typeable CSChar |
Typeable CUChar |
Typeable CShort |
Typeable CUShort |
Typeable CInt |
Typeable CUInt |
Typeable CLong |
Typeable CULong |
Typeable CLLong |
Typeable CULLong |
Typeable CFloat |
Typeable CDouble |
Typeable CPtrdiff |
Typeable CSize |
Typeable CWchar |
Typeable CSigAtomic |
Typeable CClock |
Typeable CTime |
Typeable CIntPtr |
Typeable CUIntPtr |
Typeable CIntMax |
Typeable CUIntMax |
Typeable IOException |
Typeable SomeException |
Typeable ErrorCall |
Typeable ArithException |
Typeable TypeRep |
Typeable TyCon |
Typeable Handler |
Typeable LayoutMessages |
Typeable NextNoWrap |
Typeable ChangeLayout |
Typeable IncMasterN |
Typeable Resize |
(Typeable1 s, Typeable a) => Typeable (s a) | One Typeable instance for all Typeable1 instances

class Typeable a => Message a

Based on ideas in /An Extensible Dynamically-Typed Hierarchy of Exceptions/, Simon Marlow, 2006. Use extensible messages to the `handleMessage` handler.

User-extensible messages must be a member of this class.

Instances

Message Event |
Message LayoutMessages |
Message NextNoWrap |
Message ChangeLayout |
Message IncMasterN |
Message Resize |

data SomeMessage

A wrapped value of some type in the `Message` class.

Constructors

forall a . Message a => SomeMessage a |

fromMessage :: Message m => SomeMessage -> Maybe m

And now, unwrap a given, unknown `Message` type, performing a (dynamic) type check on the result.

data LayoutMessages

`LayoutMessages` are core messages that all layouts (especially stateful layouts) should consider handling.

Constructors

Hide | sent when a layout becomes non-visible
ReleaseResources | sent when xmonad is exiting or restarting

Instances

Eq LayoutMessages |
Typeable LayoutMessages |
Message LayoutMessages |

data StateExtension

Existential type to store a state extension.

Constructors

forall a . ExtensionClass a => StateExtension a | Non-persistent state extension
forall a . (Read a, Show a, ExtensionClass a) => PersistentExtension a | Persistent extension

class Typeable a => ExtensionClass a where

Every module must make the data it wants to store an instance of this class.

Minimal complete definition: initialValue

Methods

initialValue :: a

Defines an initial value for the state extension

extensionType :: a -> StateExtension

Specifies whether the state extension should be persistent. Setting this method to `PersistentExtension` will make the stored data survive restarts, but requires a to be an instance of Read and Show.

It defaults to `StateExtension`, i.e. no persistence.

runX :: XConf -> XState -> X a -> IO (a, XState)

Run the `X` monad, given a chunk of `X` monad code, and an initial state Return the result, and final state

catchX :: X a -> X a -> X a

Run in the `X` monad, and in case of exception, and catch it and log it to stderr, and run the error case.

userCode :: X a -> X (Maybe a)

Execute the argument, catching all exceptions. Either this function or `catchX` should be used at all callsites of user customized code.

userCodeDef :: a -> X a -> X a

Same as userCode but with a default argument to return instead of using Maybe, provided for convenience.

io :: MonadIO m => IO a -> m a

General utilities

Lift an `IO` action into the `X` monad

catchIO :: MonadIO m => IO () -> m ()

Lift an `IO` action into the `X` monad. If the action results in an `IO` exception, log the exception to stderr and continue normal execution.

installSignalHandlers :: MonadIO m => m ()

Ignore SIGPIPE to avoid termination when a pipe is full, and SIGCHLD to avoid zombie processes, and clean up any extant zombie processes.

uninstallSignalHandlers :: MonadIO m => m ()

withDisplay :: (Display -> X a) -> X a

Run a monad action with the current display settings

withWindowSet :: (WindowSet -> X a) -> X a

Run a monadic action with the current stack set

isRoot :: Window -> X Bool

True if the given window is the root window

runOnWorkspaces :: (WindowSpace -> X WindowSpace) -> X ()

This is basically a map function, running a function in the `X` monad on each workspace with the output of that function being the modified workspace.

getAtom :: String -> X Atom

Wrapper for the common case of atom internment

spawn :: MonadIO m => String -> m ()

spawn. Launch an external application. Specifically, it double-forks and runs the `String` you pass as a command to /bin/sh.

Note this function assumes your locale uses utf8.

spawnPID :: MonadIO m => String -> m ProcessID

Like `spawn`, but returns the `ProcessID` of the launched application

xfork :: MonadIO m => IO () -> m ProcessID

A replacement for `forkProcess` which resets default signal handlers.

getXMonadDir :: MonadIO m => m String

Return the path to `~/.xmonad`.

recompile :: MonadIO m => Bool -> m Bool

'recompile force', recompile `~/.xmonad/xmonad.hs` when any of the following apply:

- force is `True`
- the xmonad executable does not exist
- the xmonad executable is older than xmonad.hs or any file in ~/.xmonad/lib

The -i flag is used to restrict recompilation to the xmonad.hs file only, and any files in the ~/.xmonad/lib directory.

Compilation errors (if any) are logged to ~/.xmonad/xmonad.errors. If GHC indicates failure with a non-zero exit code, an xmessage displaying that file is spawned.

`False` is returned if there are compilation errors.

trace :: MonadIO m => String -> m ()

A `trace` for the `X` monad. Logs a string to stderr. The result may be found in your .xsession-errors file

whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()

Conditionally run an action, using a `Maybe a` to decide.

whenX :: X Bool -> X () -> X ()

Conditionally run an action, using a `X` event to decide

atom_WM_STATE :: X Atom

atom_WM_PROTOCOLS :: X Atom

atom_WM_DELETE_WINDOW :: X Atom

Common non-predefined atoms

type ManageHook = Query (Endo WindowSet)

newtype Query a

Constructors

Query (ReaderT Window X a) |

Instances

Monad Query |
Functor Query |
MonadIO Query |
MonadReader Window Query |
Monoid a => Monoid (Query a) |

runQuery :: Query a -> Window -> X a