Copyright | (c) 2009 Daniel Wagner |
---|---|
License | BSD3 |
Maintainer | <daniel@wagner-home.com> |
Stability | unstable |
Portability | unportable |
Safe Haskell | None |
Language | Haskell98 |
Utility functions for simulating independent sets of workspaces on each screen (like dwm's workspace model), using internal tags to distinguish workspaces associated with each screen.
Synopsis
- type VirtualWorkspace = WorkspaceId
- type PhysicalWorkspace = WorkspaceId
- workspaces' :: XConfig l -> [VirtualWorkspace]
- withScreens :: ScreenId -> [VirtualWorkspace] -> [PhysicalWorkspace]
- onCurrentScreen :: (VirtualWorkspace -> WindowSet -> a) -> PhysicalWorkspace -> WindowSet -> a
- marshallPP :: ScreenId -> PP -> PP
- whenCurrentOn :: ScreenId -> PP -> PP
- countScreens :: (MonadIO m, Integral i) => m i
- marshall :: ScreenId -> VirtualWorkspace -> PhysicalWorkspace
- unmarshall :: PhysicalWorkspace -> (ScreenId, VirtualWorkspace)
- unmarshallS :: PhysicalWorkspace -> ScreenId
- unmarshallW :: PhysicalWorkspace -> VirtualWorkspace
- marshallWindowSpace :: ScreenId -> WindowSpace -> WindowSpace
- unmarshallWindowSpace :: WindowSpace -> WindowSpace
- marshallSort :: ScreenId -> ([WindowSpace] -> [WindowSpace]) -> [WindowSpace] -> [WindowSpace]
Usage
You can use this module with the following in your ~/.xmonad/xmonad.hs
:
import XMonad.Layout.IndependentScreens
You can define your workspaces by calling withScreens
:
myConfig = def { workspaces = withScreens 2 ["web", "email", "irc"] }
This will create "physical" workspaces with distinct internal names for each (screen, virtual workspace) pair.
Then edit any keybindings that use the list of workspaces or refer to specific workspace names. In the default configuration, only the keybindings for changing workspace do this:
keyBindings conf = let m = modMask conf in fromList $ {- lots of other keybindings -} [((m .|. modm, k), windows $ f i) | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9] , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
This should change to
keyBindings conf = let m = modMask conf in fromList $ {- lots of other keybindings -} [((m .|. modm, k), windows $ onCurrentScreen f i) | (i, k) <- zip (workspaces' conf) [xK_1 .. xK_9] , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
In particular, the analogue of XMonad.workspaces
is
workspaces'
, and you can use onCurrentScreen
to convert functions
of virtual workspaces to functions of physical workspaces, which work
by marshalling the virtual workspace name and the currently focused
screen into a physical workspace name.
A complete example abusing many of the functions below is available in the XMonad.Config.Dmwit module.
type VirtualWorkspace = WorkspaceId Source #
type PhysicalWorkspace = WorkspaceId Source #
workspaces' :: XConfig l -> [VirtualWorkspace] Source #
:: ScreenId | The number of screens to make workspaces for |
-> [VirtualWorkspace] | The desired virtual workspace names |
-> [PhysicalWorkspace] | A list of all internal physical workspace names |
onCurrentScreen :: (VirtualWorkspace -> WindowSet -> a) -> PhysicalWorkspace -> WindowSet -> a Source #
marshallPP :: ScreenId -> PP -> PP Source #
This turns a naive pretty-printer into one that is aware of the independent screens. That is, you can write your pretty printer to behave the way you want on virtual workspaces; this function will convert that pretty-printer into one that first filters out physical workspaces on other screens, then converts all the physical workspaces on this screen to their virtual names.
For example, if you have handles hLeft
and hRight
for bars on the left and right screens, respectively, and pp
is a pretty-printer function that takes a handle, you could write
logHook = let log screen handle = dynamicLogWithPP . marshallPP screen . pp $ handle in log 0 hLeft >> log 1 hRight
whenCurrentOn :: ScreenId -> PP -> PP Source #
Take a pretty-printer and turn it into one that only runs when the current
workspace is one associated with the given screen. The way this works is a
bit hacky, so beware: the ppOutput
field of the input will not be invoked
if either of the following conditions is met:
- The
ppSort
of the input returns an empty list (when not given one). - The
ppOrder
of the input returns the exact string"\0"
.
For example, you can use this to create a pipe which tracks the title of the window currently focused on a given screen (even if the screen is not current) by doing something like this:
ppFocus s = whenCurrentOn s def { ppOrder = \(_:_:title:_) -> [title] , ppOutput = appendFile ("focus" ++ show s) . (++ "\n") }
Sequence a few of these pretty-printers to get a log hook that keeps each screen's title up-to-date.
countScreens :: (MonadIO m, Integral i) => m i Source #
In case you don't know statically how many screens there will be, you can call this in main before starting xmonad. For example, part of my config reads
main = do nScreens <- countScreens xmonad $ def { ... workspaces = withScreens nScreens (workspaces def), ... }
Converting between virtual and physical workspaces
You shouldn't need to use the functions below very much. They are used internally. However, in some cases, they may be useful, and so are exported just in case. In general, the "marshall" functions convert the convenient form (like "web") you would like to use in your configuration file to the inconvenient form (like "2_web") that xmonad uses internally. Similarly, the "unmarshall" functions convert in the other direction.
marshall :: ScreenId -> VirtualWorkspace -> PhysicalWorkspace Source #
marshallWindowSpace :: ScreenId -> WindowSpace -> WindowSpace Source #
Convert the tag of the WindowSpace
from a VirtualWorkspace
to a PhysicalWorkspace
.
unmarshallWindowSpace :: WindowSpace -> WindowSpace Source #
Convert the tag of the WindowSpace
from a PhysicalWorkspace
to a VirtualWorkspace
.
marshallSort :: ScreenId -> ([WindowSpace] -> [WindowSpace]) -> [WindowSpace] -> [WindowSpace] Source #
If vSort
is a function that sorts WindowSpace
s with virtual names, then marshallSort s vSort
is a function which sorts WindowSpace
s with physical names in an analogous way -- but keeps only the spaces on screen s
.