packages feed

fudgets-0.18.3: hsrc/ghc-dialogue/EncodeEvent.hs

{-# LANGUAGE CPP #-}
{- Obsolete OPTIONS -optc-I/usr/X11R6/include -#include <X11/Xlib.h> -#include <X11/Xutil.h> -fvia-C -}
module EncodeEvent(getNextEvent,motionCompress) where

import Event
import Xtypes
--import ResourceIds

import XCallTypes
import StructFuns
import Xlib
import Marshall
import MyForeign
import qualified Foreign as F

import FudUTF8(decodeUTF8)
import Data.Maybe(fromMaybe)
--import Ap

--import GlaExts hiding(Word) --(primIOToIO,CCallable,CReturnable,Addr)
--import MutableArray(MutableByteArray#)
--import PrelGHC
--import PrelBase
--import GhcWord
--import CString(unpackCStringIO)
--import Command
--import Font

#include "newstructfuns.h"

getNextEvent d = do
   ev <- newXEvent
   xNextEvent d ev
   window <- GET(XAnyEvent,WindowId,ev,window)
   fev <- encodeEvent ev
   return (window,fev) -- no freePtr?!

checkWindowEvent d w evmask = do
   ev <- newXEvent
   found <- xCheckWindowEvent d w (toC (evmask::[EventMask])) ev
   if found
     then Just <$> encodeEvent ev
     else freePtr ev >> return Nothing

motionCompress d e@(w,fev@MotionNotify{}) =
  do me <- checkWindowEvent d w [PointerMotionMask]
     case me of
       Nothing -> return e
       Just fev' -> motionCompress d (w,fev')
motionCompress _ e = return e


encodeEvent ev = do
   evno <- GET(XAnyEvent,Int,ev,type)
   case evno :: Int of

{- ghc doesn't handle literal (``KeyPress'') patterns yet -}

#define X_KeyPress		2
#define X_KeyRelease		3
#define X_ButtonPress		4
#define X_ButtonRelease		5
#define X_MotionNotify		6
#define X_EnterNotify		7
#define X_LeaveNotify		8
#define X_FocusIn		9
#define X_FocusOut		10
#define X_KeymapNotify		11
#define X_Expose		12
#define X_GraphicsExpose	13
#define X_NoExpose		14
#define X_VisibilityNotify	15
#define X_CreateNotify		16
#define X_DestroyNotify		17
#define X_UnmapNotify		18
#define X_MapNotify		19
#define X_MapRequest		20
#define X_ReparentNotify	21
#define X_ConfigureNotify	22
#define X_ConfigureRequest	23
#define X_GravityNotify		24
#define X_ResizeRequest		25
#define X_CirculateNotify	26
#define X_CirculateRequest	27
#define X_PropertyNotify	28
#define X_SelectionClear	29
#define X_SelectionRequest	30
#define X_SelectionNotify	31
#define X_ColormapNotify	32
#define X_ClientMessage		33
#define X_MappingNotify		34
     X_KeyPress      	-> putKeyEvent ev Pressed
     X_KeyRelease    	-> putKeyEvent ev Released
     X_ButtonPress   	-> putButtonEvent ev Pressed
     X_ButtonRelease 	-> putButtonEvent ev Released
     X_MotionNotify  	-> putMotionEvent ev
     X_EnterNotify   	-> putCrossingEvent ev True
     X_LeaveNotify   	-> putCrossingEvent ev False
     X_FocusIn       	-> putFocusChangeEvent ev True
     X_FocusOut      	-> putFocusChangeEvent ev False
     X_KeymapNotify  	-> return KeymapNotify
     X_Expose	       	-> putExposeEvent ev
     X_GraphicsExpose	-> putGraphicsExposeEvent ev
     X_NoExpose		-> return NoExpose
     X_VisibilityNotify	-> putVisibilityEvent ev
     X_CreateNotify	-> putStructEvent ev CreateNotify
     X_DestroyNotify	-> putStructEvent ev DestroyNotify
     X_UnmapNotify	-> putStructEvent ev UnmapNotify
     X_MapNotify	-> putStructEvent ev MapNotify
     X_MapRequest	-> putStructEvent ev MapRequest
     X_ReparentNotify	-> return ReparentNotify
     X_ConfigureNotify	-> putConfigureEvent ev
     X_ConfigureRequest	-> return ConfigureRequest
     X_GravityNotify	-> return GravityNotify
     X_ResizeRequest	-> putResizeRequestEvent ev
     X_CirculateNotify	-> return CirculateNotify
     X_CirculateRequest	-> return CirculateRequest
     X_PropertyNotify	-> return PropertyNotify
     X_SelectionClear	-> putSelectionClearEvent ev
     X_SelectionRequest	-> putSelectionRequestEvent ev
     X_SelectionNotify	-> putSelectionNotifyEvent ev
     X_ColormapNotify	-> return ColormapNotify
     X_ClientMessage	-> putClientMessageEvent ev
     X_MappingNotify	-> return MappingNotify

mkClientData ev = do
  format <- GET(XClientMessageEvent,Int,ev,format)
  d <- AGET(XClientMessageEvent,Addr,ev,data)
  case format::Int of
    32 -> Long <$> mapM (CINDEX(long) (d::Addr)) [0..(4::Int)]
    16 -> Short <$> mapM (CINDEX(short) d) [0..(9::Int)]
    8  -> Byte <$> mapM (CINDEX(char) d) [0..(19::Int)]

putKeyEvent ev p = do
  (key,l) <- xLookupString ev 100
  KeyEvent
   <$> GET(XKeyEvent,Time,ev,time)
   <*> mkPoint GET(XKeyEvent,Int,ev,x) GET(XKeyEvent,Int,ev,y)
   <*> mkPoint GET(XKeyEvent,Int,ev,x_root) GET(XKeyEvent,Int,ev,y_root)
   <*> fmap fromC GET(XKeyEvent,Int,ev,state)
   <*> return p
   <*> fmap KeyCode GET(XKeyEvent,Int,ev,keycode)
   <*> return key
   <*> return (decodeUTF8 l)
             -- !! Assume that XLookupString returns a UTF-8 string
             -- https://gitlab.freedesktop.org/xorg/lib/libx11/-/issues/39

putButtonEvent ev p =
   ButtonEvent
   <$> GET(XButtonEvent,Time,ev,time)
   <*> mkPoint GET(XButtonEvent,Int,ev,x) GET(XButtonEvent,Int,ev,y)
   <*> mkPoint GET(XButtonEvent,Int,ev,x_root) GET(XButtonEvent,Int,ev,y_root)
   <*> fmap fromC GET(XButtonEvent,Int,ev,state)
   <*> return p
   <*> fmap Button GET(XButtonEvent,Int,ev,button)

putMotionEvent ev =
   MotionNotify
   <$> GET(XMotionEvent,Time,ev,time)
   <*> mkPoint GET(XMotionEvent,Int,ev,x) GET(XMotionEvent,Int,ev,y)
   <*> mkPoint GET(XMotionEvent,Int,ev,x_root) GET(XMotionEvent,Int,ev,y_root)
   <*> fmap fromC GET(XMotionEvent,Int,ev,state)

putCrossingEvent ev c =
   (if c then EnterNotify else LeaveNotify)
   <$> GET(XCrossingEvent,Time,ev,time)
   <*> mkPoint GET(XCrossingEvent,Int,ev,x) GET(XCrossingEvent,Int,ev,y)
   <*> mkPoint GET(XCrossingEvent,Int,ev,x_root) GET(XCrossingEvent,Int,ev,y_root)
   <*> fmap fromC GET(XCrossingEvent,Int,ev,detail)
   <*> fmap fromC GET(XCrossingEvent,Int,ev,mode)
   <*> fmap fromC GET(XCrossingEvent,Int,ev,focus)


putFocusChangeEvent ev c =
   (if c then FocusIn else FocusOut)
   <$> fmap fromC GET(XFocusChangeEvent,Int,ev,detail)
   <*> fmap fromC GET(XFocusChangeEvent,Int,ev,mode)

putExposeEvent ev =
   Expose
   <$> mkRect GET(XExposeEvent,Int,ev,x) GET(XExposeEvent,Int,ev,y)
	       GET(XExposeEvent,Int,ev,width) GET(XExposeEvent,Int,ev,height) 
   <*> GET(XExposeEvent,Int,ev,count)

putGraphicsExposeEvent ev =
   GraphicsExpose 
   <$> mkRect GET(XGraphicsExposeEvent,Int,ev,x) GET(XGraphicsExposeEvent,Int,ev,y)
	       GET(XGraphicsExposeEvent,Int,ev,width) GET(XGraphicsExposeEvent,Int,ev,height) 
   <*> GET(XGraphicsExposeEvent,Int,ev,count)
   <*> GET(XGraphicsExposeEvent,Int,ev,major_code)
   <*> GET(XGraphicsExposeEvent,Int,ev,minor_code)

putVisibilityEvent ev =
  VisibilityNotify . fromC <$> GET(XVisibilityEvent,Int,ev,state)

putStructEvent ev c = c <$> GET(XMapEvent,WindowId,ev,window)

putConfigureEvent ev =
   ConfigureNotify
   <$> mkRect GET(XConfigureEvent,Int,ev,x) GET(XConfigureEvent,Int,ev,y)
               GET(XConfigureEvent,Int,ev,width) GET(XConfigureEvent,Int,ev,height)
   <*> GET(XConfigureEvent,Int,ev,border_width)

putResizeRequestEvent ev =
   ResizeRequest 
  <$> mkPoint GET(XResizeRequestEvent,Int,ev,width)
             GET(XResizeRequestEvent,Int,ev,height)

putSelectionClearEvent ev = SelectionClear
 <$> GET(XSelectionClearEvent,Atom,ev,selection)

putSelectionRequestEvent ev =
  SelectionRequest
  <$> GET(XSelectionRequestEvent,Time,ev,time)
  <*> GET(XSelectionRequestEvent,WindowId,ev,requestor)
  <*> (Selection <$> GET(XSelectionRequestEvent,Atom,ev,selection)
		<*> GET(XSelectionRequestEvent,Atom,ev,target)
		<*> GET(XSelectionRequestEvent,Atom,ev,property))

putSelectionNotifyEvent ev =
  SelectionNotify
  <$> GET(XSelectionEvent,Time,ev,time)
  <*> (Selection <$> GET(XSelectionEvent,Atom,ev,selection)
		<*> GET(XSelectionEvent,Atom,ev,target)
		<*> GET(XSelectionEvent,Atom,ev,property))

putClientMessageEvent ev =
  ClientMessage
  <$> GET(XClientMessageEvent,Atom,ev,message_type)
  <*> mkClientData ev

foreign import ccall "X11/Xlib.h XLookupString"
  cXLookupString :: CXKeyEvent -> Addr -> Int -> F.Ptr XlibKeySym -> Addr -> IO Int

xLookupString :: CXKeyEvent -> Int -> IO (KeySym,String)
xLookupString xev len =
    alloca len $ \ arr ->
    F.alloca $ \ keysyma ->
    do len' <- {- _casm_ ``%r=(int)XLookupString((XKeyEvent *)%0,
					  (char *)%1,
					  (int)%2,
					  (KeySym *)%3,
					  NULL);'' xev arr len keysyma -}
           cXLookupString xev arr len keysyma nullAddr
       keysym <- F.peek keysyma
       key <- xKeysymToString keysym
       let key' = fromMaybe "(undefined)" key
       str <- unmarshallString' (CString arr) len'
       return (key',str)

instance FromC Detail where fromC = toEnum' NotifyAncestor
instance FromC Mode where fromC = toEnum' NotifyNormal
instance FromC Visibility where fromC = toEnum' VisibilityUnobscured


instance F.Storable XID where
  sizeOf (XID x) = F.sizeOf x
  alignment (XID x) = F.alignment x

  peek a = fmap XID (F.peek (F.castPtr a))
  poke a (XID x) = F.poke (F.castPtr a) x