X11-extras-0.0: Graphics/X11/Xinerama.hsc
-- | Interface to Xinerama API
module Graphics.X11.Xinerama
(XineramaScreenInfo(..),
xineramaIsActive,
xineramaQueryExtension,
xineramaQueryVersion,
xineramaQueryScreens,
getScreenInfo) where
#include <config.h>
import Foreign
import Foreign.C.Types
import Graphics.X11.Xlib
import Control.Monad
-- | Representation of the XineramaScreenInfo struct
data XineramaScreenInfo = XineramaScreenInfo
{ xsi_screen_number :: CInt,
xsi_x_org :: CShort,
xsi_y_org :: CShort,
xsi_width :: CShort,
xsi_height :: CShort }
deriving (Show)
-- | Wrapper around xineramaQueryScreens that fakes a single screen when
-- Xinerama is not active. This is the preferred interface to
-- Graphics.X11.Xinerama.
getScreenInfo :: Display -> IO [Rectangle]
getScreenInfo dpy = maybe [singleScreen] (map xsiToRect) `liftM` xineramaQueryScreens dpy
where dflt = defaultScreen dpy
xsiToRect xsi = Rectangle
{ rect_x = fromIntegral $ xsi_x_org xsi
, rect_y = fromIntegral $ xsi_y_org xsi
, rect_width = fromIntegral $ xsi_width xsi
, rect_height = fromIntegral $ xsi_height xsi
}
singleScreen = Rectangle
{ rect_x = 0
, rect_y = 0
, rect_width = fromIntegral $ displayWidth dpy dflt
, rect_height = fromIntegral $ displayHeight dpy dflt
}
#ifdef HAVE_X11_EXTENSIONS_XINERAMA_H
-- We have Xinerama, so the library will actually work
-- for XFree() (already included from Xinerama.h, but I don't know if I can count on that.)
#include <X11/Xlib.h>
#include <X11/extensions/Xinerama.h>
instance Storable XineramaScreenInfo where
sizeOf _ = #{size XineramaScreenInfo}
-- FIXME: Is this right?
alignment _ = alignment (undefined :: CInt)
poke p xsi = do
#{poke XineramaScreenInfo, screen_number } p $ xsi_screen_number xsi
#{poke XineramaScreenInfo, x_org } p $ xsi_x_org xsi
#{poke XineramaScreenInfo, y_org } p $ xsi_y_org xsi
#{poke XineramaScreenInfo, width } p $ xsi_width xsi
#{poke XineramaScreenInfo, height } p $ xsi_height xsi
peek p = return XineramaScreenInfo
`ap` (#{peek XineramaScreenInfo, screen_number} p)
`ap` (#{peek XineramaScreenInfo, x_org} p)
`ap` (#{peek XineramaScreenInfo, y_org} p)
`ap` (#{peek XineramaScreenInfo, width} p)
`ap` (#{peek XineramaScreenInfo, height} p)
foreign import ccall "XineramaIsActive"
xineramaIsActive :: Display -> IO Bool
xineramaQueryExtension :: Display -> IO (Maybe (CInt, CInt))
xineramaQueryExtension dpy = wrapPtr2 (cXineramaQueryExtension dpy) go
where go False _ _ = Nothing
go True eventbase errorbase = Just (fromIntegral eventbase, fromIntegral errorbase)
xineramaQueryVersion :: Display -> IO (Maybe (CInt, CInt))
xineramaQueryVersion dpy = wrapPtr2 (cXineramaQueryVersion dpy) go
where go False _ _ = Nothing
go True major minor = Just (fromIntegral major, fromIntegral minor)
xineramaQueryScreens :: Display -> IO (Maybe [XineramaScreenInfo])
xineramaQueryScreens dpy =
withPool $ \pool -> do intp <- pooledMalloc pool
p <- cXineramaQueryScreens dpy intp
if p == nullPtr
then return Nothing
else do nscreens <- peek intp
screens <- peekArray (fromIntegral nscreens) p
cXFree p
return (Just screens)
foreign import ccall "XineramaQueryExtension"
cXineramaQueryExtension :: Display -> Ptr CInt -> Ptr CInt -> IO Bool
foreign import ccall "XineramaQueryVersion"
cXineramaQueryVersion :: Display -> Ptr CInt -> Ptr CInt -> IO Bool
foreign import ccall "XineramaQueryScreens"
cXineramaQueryScreens :: Display -> Ptr CInt -> IO (Ptr XineramaScreenInfo)
foreign import ccall "XFree"
cXFree :: Ptr a -> IO CInt
wrapPtr2 :: (Storable a, Storable b) => (Ptr a -> Ptr b -> IO c) -> (c -> a -> b -> d) -> IO d
wrapPtr2 cfun f =
withPool $ \pool -> do aptr <- pooledMalloc pool
bptr <- pooledMalloc pool
ret <- cfun aptr bptr
a <- peek aptr
b <- peek bptr
return (f ret a b)
#else
-- No Xinerama, but if we fake a non-active Xinerama interface, "getScreenInfo"
-- will continue to work fine in the single-screen case.
xineramaIsActive :: Display -> IO Bool
xineramaIsActive _ = return False
xineramaQueryExtension :: Display -> IO (Maybe (CInt, CInt))
xineramaQueryExtension _ = return Nothing
xineramaQueryVersion :: Display -> IO (Maybe (CInt, CInt))
xineramaQueryVersion _ = return Nothing
xineramaQueryScreens :: Display -> IO (Maybe [XineramaScreenInfo])
xineramaQueryScreens _ = return Nothing
#endif