mirror of
https://github.com/xmonad/xmonad.git
synced 2025-08-05 22:51:54 -07:00
basic xinerama support (depends on Graphics.X11.Xinerama in X11-extras)
This commit is contained in:
45
Main.hs
45
Main.hs
@@ -14,6 +14,7 @@
|
||||
--
|
||||
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.Bits hiding (rotate)
|
||||
import qualified Data.Map as M
|
||||
|
||||
@@ -22,6 +23,7 @@ import System.Exit
|
||||
|
||||
import Graphics.X11.Xlib
|
||||
import Graphics.X11.Xlib.Extras
|
||||
import Graphics.X11.Xinerama
|
||||
|
||||
import Control.Monad.State
|
||||
|
||||
@@ -69,10 +71,13 @@ main = do
|
||||
rootw <- rootWindow dpy dflt
|
||||
wmdelt <- internAtom dpy "WM_DELETE_WINDOW" False
|
||||
wmprot <- internAtom dpy "WM_PROTOCOLS" False
|
||||
xinesc <- getScreenInfo dpy
|
||||
|
||||
let st = XState
|
||||
{ display = dpy
|
||||
, screen = dflt
|
||||
, xineScreens = xinesc
|
||||
, wsOnScreen = M.fromList $ map ((\n -> (n,n)) . fromIntegral . xsi_screen_number) xinesc
|
||||
, theRoot = rootw
|
||||
, wmdelete = wmdelt
|
||||
, wmprotocols = wmprot
|
||||
@@ -176,9 +181,10 @@ handle e@(MappingNotifyEvent {window = w}) = do
|
||||
handle e@(CrossingEvent {window = w, event_type = t})
|
||||
| t == enterNotify && mode e == notifyNormal && detail e /= notifyInferior
|
||||
= do ws <- gets workspace
|
||||
if W.member w ws
|
||||
then setFocus w
|
||||
else do b <- isRoot w
|
||||
case W.lookup w ws of
|
||||
Just n -> do setFocus w
|
||||
windows $ W.view n
|
||||
Nothing -> do b <- isRoot w
|
||||
when b setTopFocus
|
||||
|
||||
-- left a window, check if we need to focus root
|
||||
@@ -217,10 +223,17 @@ handle e = trace (eventName e) -- ignoring
|
||||
refresh :: X ()
|
||||
refresh = do
|
||||
ws <- gets workspace
|
||||
whenJust (W.peek ws) $ \w -> withDisplay $ \d -> do
|
||||
(sw,sh) <- gets dimensions
|
||||
io $ do moveResizeWindow d w 0 0 (fromIntegral sw) (fromIntegral sh) -- fullscreen
|
||||
ws2sc <- gets wsOnScreen
|
||||
xinesc <- gets xineScreens
|
||||
forM_ (M.assocs ws2sc) $ \(n, scn) ->
|
||||
whenJust (listToMaybe $ W.index n ws) $ \w -> withDisplay $ \d -> do
|
||||
let sc = xinesc !! scn
|
||||
io $ do moveResizeWindow d w (fromIntegral $ xsi_x_org sc)
|
||||
(fromIntegral $ xsi_y_org sc)
|
||||
(fromIntegral $ xsi_width sc)
|
||||
(fromIntegral $ xsi_height sc) -- fullscreen
|
||||
raiseWindow d w
|
||||
whenJust (W.peek ws) setFocus
|
||||
|
||||
-- | windows. Modify the current window list with a pure function, and refresh
|
||||
windows :: (WorkSpace -> WorkSpace) -> X ()
|
||||
@@ -230,16 +243,12 @@ windows f = do
|
||||
ws <- gets workspace
|
||||
trace (show ws) -- log state changes to stderr
|
||||
|
||||
-- | hide. Hide a list of windows by moving them offscreen.
|
||||
-- | hide. Hide a window by moving it offscreen.
|
||||
hide :: Window -> X ()
|
||||
hide w = withDisplay $ \d -> do
|
||||
(sw,sh) <- gets dimensions
|
||||
io $ moveWindow d w (2*fromIntegral sw) (2*fromIntegral sh)
|
||||
|
||||
-- | reveal. Expose a list of windows, moving them on screen
|
||||
reveal :: Window -> X ()
|
||||
reveal w = withDisplay $ \d -> io $ moveWindow d w 0 0
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- Window operations
|
||||
|
||||
@@ -320,14 +329,22 @@ tag o = do
|
||||
view :: Int -> X ()
|
||||
view o = do
|
||||
ws <- gets workspace
|
||||
ws2sc <- gets wsOnScreen
|
||||
let m = W.current ws
|
||||
when (n /= m) $ do
|
||||
mapM_ reveal (W.index n ws)
|
||||
mapM_ hide (W.index m ws)
|
||||
-- is the workspace we want to switch to currently visible?
|
||||
if M.member n ws2sc
|
||||
then windows $ W.view n
|
||||
else do
|
||||
-- This assumes that the current workspace is visible.
|
||||
-- Is that always going to be true?
|
||||
let Just curscreen = M.lookup m ws2sc
|
||||
modify $ \s -> s { wsOnScreen = M.insert n curscreen (M.delete m ws2sc) }
|
||||
windows $ W.view n
|
||||
mapM_ hide (W.index m ws)
|
||||
setTopFocus
|
||||
where n = o-1
|
||||
|
||||
|
||||
-- | True if window is under management by us
|
||||
isClient :: Window -> X Bool
|
||||
isClient w = liftM (W.member w) (gets workspace)
|
||||
|
@@ -61,6 +61,10 @@ empty n = StackSet { current = 0
|
||||
member :: Ord a => a -> StackSet a -> Bool
|
||||
member a w = M.member a (cache w)
|
||||
|
||||
-- | /O(log n)/. Looks up the stack that x is in, if it is in the StackSet
|
||||
lookup :: (Monad m, Ord a) => a -> StackSet a -> m Int
|
||||
lookup x w = M.lookup x (cache w)
|
||||
|
||||
-- | /O(n)/. Number of stacks
|
||||
size :: StackSet a -> Int
|
||||
size = M.size . stacks
|
||||
|
@@ -28,11 +28,18 @@ import System.Posix.Process (executeFile, forkProcess, getProcessStatus)
|
||||
import System.Exit
|
||||
import Graphics.X11.Xlib
|
||||
|
||||
import Graphics.X11.Xinerama
|
||||
|
||||
import qualified Data.Map as M
|
||||
|
||||
-- | XState, the window manager state.
|
||||
-- Just the display, width, height and a window list
|
||||
data XState = XState
|
||||
{ display :: Display
|
||||
, screen :: {-# UNPACK #-} !ScreenNumber
|
||||
, xineScreens :: {-# UNPACK #-} ![XineramaScreenInfo]
|
||||
-- a mapping of workspaces to xinerama screen numbers
|
||||
, wsOnScreen :: {-# UNPACK #-} !(M.Map Int Int)
|
||||
, theRoot :: {-# UNPACK #-} !Window
|
||||
, wmdelete :: {-# UNPACK #-} !Atom
|
||||
, wmprotocols :: {-# UNPACK #-} !Atom
|
||||
|
Reference in New Issue
Block a user