packages feed

x11-xim-0.0.9.0: tests/useXim.hs

{-# LANGUAGE FlexibleContexts #-}

import Graphics.X11		(
	Display, openDisplay, closeDisplay, defaultScreen, rootWindow,
	whitePixel, blackPixel,
	Window, createSimpleWindow, destroyWindow, mapWindow,
	GC, createGC, freeGC, supportsLocale, setLocaleModifiers,
	selectInput, exposureMask, keyPressMask, focusChangeMask,
	Atom, internAtom, setWMProtocols, XEventPtr, nextEvent, allocaXEvent	)
import Graphics.X11.Xlib.Extras	(
	Event(ClientMessageEvent, KeyEvent), getEvent, ev_data,
	FontSet, createFontSet
									)
import Graphics.X11.Types	( xK_Return				)
import Graphics.X11.Xim		(
	XIM, openIM, closeIM, XIC, createIC, destroyIC, getICValue,
	filterEvent, XNInputStyle(..),
	utf8LookupString, utf8DrawString				)
import Data.IORef		( IORef, newIORef, readIORef, writeIORef,
					modifyIORef			)
import Data.Maybe		( fromMaybe				)
import Data.Bits		( (.|.)					)
import Data.Convertible		( Convertible, convert			)
import Control.Monad		( unless, when				)
import Control.Monad.Tools	( doUntil_ 				)
import System.Exit		( exitFailure				)
import System.Locale.SetLocale	( setLocale, Category(..)		)
import Foreign.C.Types		( CInt					)

setLocaleAndCheck :: IO ()
setLocaleAndCheck = do
	ret <- setLocale LC_CTYPE Nothing
	case ret of
		Nothing -> putStrLn "Can't set locale." >> exitFailure
		_	-> return ()

supportsLocaleAndCheck :: IO ()
supportsLocaleAndCheck = do
	sl <- supportsLocale
	unless sl $ putStrLn "Current locale is not supported" >> exitFailure

keyEventAction :: Display -> Window -> FontSet -> GC -> XIC -> IORef Int ->
			IORef Int -> XEventPtr -> IO Bool
keyEventAction dpy win fs gc ic posx posy e = do
	( mstr, mks ) <- utf8LookupString ic e
	x <- readIORef posx
	y <- readIORef posy
	if ( mks == Just xK_Return )
		then do
			putStrLn ""
			writeIORef posx 5
			modifyIORef posy (+ 13)
		else case ( mstr, mks ) of
			( Just str, _ ) -> do
				modifyIORef posx (+ length str * 13)
				putStr str
				utf8DrawString dpy win fs gc x y str
			_ -> return ()
	return False

runWithXIM ::
	( Display -> Window -> GC -> XIM -> XIC -> Atom -> FontSet -> XEventPtr
			-> IO () )
			-> IO ()
runWithXIM act = do
	setLocaleAndCheck
	supportsLocaleAndCheck
	_ <- setLocaleModifiers ""
	dpy	<-openDisplay ""
	let	scr	=  defaultScreen dpy
		black	=  blackPixel dpy scr
		white	=  whitePixel dpy scr
	rootWin		<- rootWindow dpy scr
	win		<- createSimpleWindow dpy rootWin 0 0 100 100 1
				black white
	gc		<- createGC dpy win
	im		<- openIM dpy Nothing Nothing Nothing
	ic		<- createIC im [ XIMPreeditNothing, XIMStatusNothing ] win
	fevent		<- getICValue ic "filterEvents"
	selectInput dpy win $ exposureMask .|. keyPressMask .|.
			focusChangeMask .|. fevent
	delWin		<- internAtom dpy "WM_DELETE_WINDOW" True
	setWMProtocols dpy win [ delWin ]
	mapWindow dpy win
	( _, _, fs )	<- createFontSet dpy
				"-*-fixed-medium-r-normal--14-*-*-*"
	allocaXEvent $ \e -> act dpy win gc im ic delWin fs e
	destroyIC ic
	closeIM im
	freeGC dpy gc
	destroyWindow dpy win
	closeDisplay dpy

nextNotFilteredEvent :: Display -> XEventPtr -> IO ()
nextNotFilteredEvent dpy e = do
	nextEvent dpy e
	filtOut <- filterEvent e 0
	if filtOut
		then nextNotFilteredEvent dpy e
		else return ()

main :: IO ()
main = runWithXIM $ \dpy win gc im ic delWin fs e -> do
	setICFocus ic
	posx	<- newIORef 5
	posy	<- newIORef 20
	doUntil_ $ do
		nextNotFilteredEvent dpy e
		ev <- getEvent e
		case ev of
			KeyEvent {} -> keyEventAction dpy win fs gc ic posx posy e
			ClientMessageEvent {} ->
				return $ getClientMessageAtom ev == delWin
			_                     -> return False

getClientMessageAtom :: Convertible CInt a => Event -> a
getClientMessageAtom = convert . head . ev_data