basic xinerama support (depends on Graphics.X11.Xinerama in X11-extras)

This commit is contained in:
Jason Creighton
2007-03-17 23:49:04 +00:00
parent 397cdbda0e
commit bb43b2ad6f
3 changed files with 47 additions and 19 deletions

45
Main.hs
View File

@@ -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)

View File

@@ -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

View File

@@ -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