mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 03:20:21 -07:00
The links were broken due to: 1. Incorrect quotes (' instead of " for module links and occasionally vice-versa). 2. Changes in the name of the "target" module not reflected in the "source" docs. 3. Typos to begin with. 4. Use of `<foo>` in the docs is rendered as just `foo` with a link to `/foo`. 5. Similarly for `"Foo"` if it starts with a capital letter (and hence could be a module). 6. Markup inside `@` code blocks still being applied. e.g. `@M-<arrow-keys>@` is rendered as `M-arrow-keys` with a spurious hyperlink from arrow-keys to `/arrow-keys`, which is confusing. Three links from XMonad.Util.Run have been removed outright, since they're no longer examples of the usage of 'runProcessWithInput'. WmiiActions has been gone since 2008, while XMonad.Prompt.Directory and XMonad.Layout.WorkspaceDir haven't been using 'runProcessWithInput' since 2020 and 2012, respectively. In some cases the `<foo>` were surrounded with @, especially in the case of key definitions, for consistency. (This wasn't done everywhere, because it looks ugly in the source.) MoreManageHelpers has never been in xmonad-contrib. ManageHelpers seems to fill the expected role. In the case of the module description for X.H.ManageDebug the quotes were simply removed because none of the likely options to make the link work were successful.
149 lines
7.0 KiB
Haskell
149 lines
7.0 KiB
Haskell
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Actions.PhysicalScreens
|
|
-- Description : Manipulate screens ordered by physical location instead of ID.
|
|
-- 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
|
|
, onNextNeighbour
|
|
, onPrevNeighbour
|
|
, horizontalScreenOrderer
|
|
, verticalScreenOrderer
|
|
, ScreenComparator(ScreenComparator)
|
|
, getScreenIdAndRectangle
|
|
, screenComparatorById
|
|
, screenComparatorByRectangle
|
|
) where
|
|
|
|
import XMonad
|
|
import XMonad.Prelude (elemIndex, fromMaybe, on, sortBy)
|
|
import qualified XMonad.StackSet as W
|
|
|
|
{- $usage
|
|
|
|
This module allows you name Xinerama screens from XMonad using their
|
|
physical location relative to each other (as reported by Xinerama),
|
|
rather than their @ScreenID@ s, which are arbitrarily determined by
|
|
your X server and graphics hardware.
|
|
|
|
You can specify how to order the screen by giving a ScreenComparator.
|
|
To create a screen comparator you can use screenComparatorByRectangle or screenComparatorByScreenId.
|
|
The default ScreenComparator orders screens 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
|
|
> import Data.Default
|
|
|
|
> , ((modMask, xK_a), onPrevNeighbour def W.view)
|
|
> , ((modMask, xK_o), onNextNeighbour def W.view)
|
|
> , ((modMask .|. shiftMask, xK_a), onPrevNeighbour def W.shift)
|
|
> , ((modMask .|. shiftMask, xK_o), onNextNeighbour def W.shift)
|
|
|
|
> --
|
|
> -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
|
|
> -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3
|
|
> --
|
|
> [((modm .|. mask, key), f sc)
|
|
> | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
|
|
> , (f, mask) <- [(viewScreen def, 0), (sendToScreen def, shiftMask)]]
|
|
|
|
For detailed instructions on editing your key bindings, see
|
|
<https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
|
|
-}
|
|
|
|
-- | The type of the index of a screen by location
|
|
newtype PhysicalScreen = P Int deriving (Eq,Ord,Show,Read,Enum,Num,Integral,Real)
|
|
|
|
getScreenIdAndRectangle :: W.Screen i l a ScreenId ScreenDetail -> (ScreenId, Rectangle)
|
|
getScreenIdAndRectangle screen = (W.screen screen, rect) where
|
|
rect = screenRect $ W.screenDetail screen
|
|
|
|
-- | Translate a physical screen index to a 'ScreenId'
|
|
getScreen:: ScreenComparator -> PhysicalScreen -> X (Maybe ScreenId)
|
|
getScreen (ScreenComparator cmpScreen) (P i) = do w <- gets windowset
|
|
let screens = W.current w : W.visible w
|
|
if i<0 || i >= length screens
|
|
then return Nothing
|
|
else let ss = sortBy (cmpScreen `on` getScreenIdAndRectangle) screens
|
|
in return $ Just $ W.screen $ ss !! i
|
|
|
|
-- | Switch to a given physical screen
|
|
viewScreen :: ScreenComparator -> PhysicalScreen -> X ()
|
|
viewScreen sc p = do i <- getScreen sc p
|
|
whenJust i $ \s -> do
|
|
w <- screenWorkspace s
|
|
whenJust w $ windows . W.view
|
|
|
|
-- | Send the active window to a given physical screen
|
|
sendToScreen :: ScreenComparator -> PhysicalScreen -> X ()
|
|
sendToScreen sc p = do i <- getScreen sc p
|
|
whenJust i $ \s -> do
|
|
w <- screenWorkspace s
|
|
whenJust w $ windows . W.shift
|
|
|
|
-- | A ScreenComparator allow to compare two screen based on their coordonate and Xinerama Id
|
|
newtype ScreenComparator = ScreenComparator ((ScreenId, Rectangle) -> (ScreenId, Rectangle) -> Ordering)
|
|
|
|
-- | The default ScreenComparator orders screens by the upper-left-most corner, from top-to-bottom
|
|
instance Default ScreenComparator where
|
|
def= verticalScreenOrderer
|
|
|
|
-- | Compare screen only by their coordonate
|
|
screenComparatorByRectangle :: (Rectangle -> Rectangle -> Ordering) -> ScreenComparator
|
|
screenComparatorByRectangle rectComparator = ScreenComparator comparator where
|
|
comparator (_, rec1) (_, rec2) = rectComparator rec1 rec2
|
|
|
|
-- | Compare screen only by their Xinerama id
|
|
screenComparatorById :: (ScreenId -> ScreenId -> Ordering) -> ScreenComparator
|
|
screenComparatorById idComparator = ScreenComparator comparator where
|
|
comparator (id1, _) (id2, _) = idComparator id1 id2
|
|
|
|
-- | orders screens by the upper-left-most corner, from top-to-bottom
|
|
verticalScreenOrderer :: ScreenComparator
|
|
verticalScreenOrderer = screenComparatorByRectangle comparator where
|
|
comparator (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (y1, x1) (y2, x2)
|
|
|
|
-- | orders screens by the upper-left-most corner, from left-to-right
|
|
horizontalScreenOrderer :: ScreenComparator
|
|
horizontalScreenOrderer = screenComparatorByRectangle comparator where
|
|
comparator (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (x1, y1) (x2, y2)
|
|
|
|
-- | Get ScreenId for neighbours of the current screen based on position offset.
|
|
getNeighbour :: ScreenComparator -> Int -> X ScreenId
|
|
getNeighbour (ScreenComparator cmpScreen) d =
|
|
do w <- gets windowset
|
|
let ss = map W.screen $ sortBy (cmpScreen `on` getScreenIdAndRectangle) $ W.current w : W.visible w
|
|
curPos = fromMaybe 0 $ elemIndex (W.screen (W.current w)) ss
|
|
pos = (curPos + d) `mod` length ss
|
|
return $ ss !! pos
|
|
|
|
neighbourWindows :: ScreenComparator -> Int -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
|
|
neighbourWindows sc d f = do s <- getNeighbour sc d
|
|
w <- screenWorkspace s
|
|
whenJust w $ windows . f
|
|
|
|
-- | Apply operation on a WindowSet with the WorkspaceId of the next screen in the physical order as parameter.
|
|
onNextNeighbour :: ScreenComparator -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
|
|
onNextNeighbour sc = neighbourWindows sc 1
|
|
|
|
-- | Apply operation on a WindowSet with the WorkspaceId of the previous screen in the physical order as parameter.
|
|
onPrevNeighbour :: ScreenComparator -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
|
|
onPrevNeighbour sc = neighbourWindows sc (-1)
|