aboutsummaryrefslogtreecommitdiffstats
path: root/XMonad/Actions/PhysicalScreens.hs
diff options
context:
space:
mode:
Diffstat (limited to 'XMonad/Actions/PhysicalScreens.hs')
-rw-r--r--XMonad/Actions/PhysicalScreens.hs88
1 files changed, 88 insertions, 0 deletions
diff --git a/XMonad/Actions/PhysicalScreens.hs b/XMonad/Actions/PhysicalScreens.hs
new file mode 100644
index 0000000..10d192d
--- /dev/null
+++ b/XMonad/Actions/PhysicalScreens.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module : XMonad.Actions.PhysicalScreens
+-- Copyright : (c) Nelson Elhage <nelhage@mit.edu>
+-- License : BSD
+--
+-- Maintainer : Nelson Elhage <nelhage@mit.edu>
+-- Stability : unstable
+-- Portability : unportable
+--
+-- Manipulate screens ordered by physical location instead of ID
+-----------------------------------------------------------------------------
+
+module XMonad.Actions.PhysicalScreens (
+ -- * Usage
+ -- $usage
+ PhysicalScreen(..)
+ , getScreen
+ , viewScreen
+ , sendToScreen
+ ) where
+
+import XMonad
+import qualified XMonad.StackSet as W
+
+import qualified Graphics.X11.Xlib as X
+import Graphics.X11.Xinerama
+
+import Data.List (sortBy)
+import Data.Function (on)
+
+{- $usage
+
+This module allows you name Xinerama screens from XMonad using their
+physical location reletive to each other (as reported by Xinerama),
+rather than their @ScreenID@ s, which are arbitrarily determined by
+your X server and graphics hardware.
+
+Screens are ordered by the upper-left-most corner, from top-to-bottom
+and then left-to-right.
+
+Example usage in your @~\/.xmonad\/xmonad.hs@ file:
+
+> import XMonad.Actions.PhysicalSCreens
+
+> --
+> -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
+> -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3
+> --
+> [((modMask .|. mask, key), f sc)
+> | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
+> , (f, mask) <- [(viewScreen, 0), (sendToScreen, shiftMask)]]
+
+For detailed instructions on editing your key bindings, see
+"XMonad.Doc.Extending#Editing_key_bindings".
+ -}
+
+-- | The type of the index of a screen by location
+newtype PhysicalScreen = P Int deriving (Eq,Ord,Show,Read,Enum,Num,Integral,Real)
+
+-- | Translate a physical screen index to a "ScreenId"
+getScreen :: PhysicalScreen -> X (Maybe ScreenId)
+getScreen (P i) = withDisplay $ \dpy -> do
+ screens <- io $ getScreenInfo dpy
+ if i >= length screens
+ then return Nothing
+ else let ss = sortBy (cmpScreen `on` fst) $ zip screens [0..]
+ in return $ Just $ snd $ ss !! i
+
+-- | Switch to a given physical screen
+viewScreen :: PhysicalScreen -> X ()
+viewScreen p = do i <- getScreen p
+ whenJust i $ \s -> do
+ w <- screenWorkspace s
+ whenJust w $ windows . W.view
+
+-- | Send the active window to a given physical screen
+sendToScreen :: PhysicalScreen -> X ()
+sendToScreen p = do i <- getScreen p
+ whenJust i $ \s -> do
+ w <- screenWorkspace s
+ whenJust w $ windows . W.shift
+
+-- | Compare two screens by their top-left corners, ordering
+-- | top-to-bottom and then left-to-right.
+cmpScreen :: Rectangle -> Rectangle -> Ordering
+cmpScreen (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (y1,x1) (y2,x2)