module Graphics.X11.Xlib.Extras where
import Data.Typeable ( Typeable )
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Types
import Graphics.X11.Xlib.Misc
import Foreign
import Foreign.C.Types
import Foreign.C.String
import Control.Monad
data Event
= AnyEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
}
| ConfigureRequestEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_parent :: !Window
, ev_window :: !Window
, ev_x :: !CInt
, ev_y :: !CInt
, ev_width :: !CInt
, ev_height :: !CInt
, ev_border_width :: !CInt
, ev_above :: !Window
, ev_detail :: !NotifyDetail
, ev_value_mask :: !CULong
}
| ConfigureEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_event :: !Window
, ev_window :: !Window
, ev_x :: !CInt
, ev_y :: !CInt
, ev_width :: !CInt
, ev_height :: !CInt
, ev_border_width :: !CInt
, ev_above :: !Window
, ev_override_redirect :: !Bool
}
| MapRequestEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_parent :: !Window
, ev_window :: !Window
}
| KeyEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_root :: !Window
, ev_subwindow :: !Window
, ev_time :: !Time
, ev_x :: !CInt
, ev_y :: !CInt
, ev_x_root :: !CInt
, ev_y_root :: !CInt
, ev_state :: !KeyMask
, ev_keycode :: !KeyCode
, ev_same_screen :: !Bool
}
| ButtonEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_root :: !Window
, ev_subwindow :: !Window
, ev_time :: !Time
, ev_x :: !CInt
, ev_y :: !CInt
, ev_x_root :: !CInt
, ev_y_root :: !CInt
, ev_state :: !KeyMask
, ev_button :: !Button
, ev_same_screen :: !Bool
}
| MotionEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_x :: !CInt
, ev_y :: !CInt
, ev_window :: !Window
}
| DestroyWindowEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_event :: !Window
, ev_window :: !Window
}
| UnmapEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_event :: !Window
, ev_window :: !Window
, ev_from_configure :: !Bool
}
| MapNotifyEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_event :: !Window
, ev_window :: !Window
, ev_override_redirect :: !Bool
}
| MappingNotifyEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_request :: !MappingRequest
, ev_first_keycode :: !KeyCode
, ev_count :: !CInt
}
| CrossingEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_root :: !Window
, ev_subwindow :: !Window
, ev_time :: !Time
, ev_x :: !CInt
, ev_y :: !CInt
, ev_x_root :: !CInt
, ev_y_root :: !CInt
, ev_mode :: !NotifyMode
, ev_detail :: !NotifyDetail
, ev_same_screen :: !Bool
, ev_focus :: !Bool
, ev_state :: !Modifier
}
| SelectionRequest
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_owner :: !Window
, ev_requestor :: !Window
, ev_selection :: !Atom
, ev_target :: !Atom
, ev_property :: !Atom
, ev_time :: !Time
}
| PropertyEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_atom :: !Atom
, ev_time :: !Time
, ev_propstate :: !CInt
}
| ExposeEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_x :: !CInt
, ev_y :: !CInt
, ev_width :: !CInt
, ev_height :: !CInt
, ev_count :: !CInt
}
| ClientMessageEvent
{ ev_event_type :: !EventType
, ev_serial :: !CULong
, ev_send_event :: !Bool
, ev_event_display :: Display
, ev_window :: !Window
, ev_message_type :: !Atom
, ev_data :: ![CInt]
}
deriving ( Show, Typeable )
eventTable :: [(EventType, String)]
eventTable =
[ (keyPress , "KeyPress")
, (keyRelease , "KeyRelease")
, (buttonPress , "ButtonPress")
, (buttonRelease , "ButtonRelease")
, (motionNotify , "MotionNotify")
, (enterNotify , "EnterNotify")
, (leaveNotify , "LeaveNotify")
, (focusIn , "FocusIn")
, (focusOut , "FocusOut")
, (keymapNotify , "KeymapNotify")
, (expose , "Expose")
, (graphicsExpose , "GraphicsExpose")
, (noExpose , "NoExpose")
, (visibilityNotify , "VisibilityNotify")
, (createNotify , "CreateNotify")
, (destroyNotify , "DestroyNotify")
, (unmapNotify , "UnmapNotify")
, (mapNotify , "MapNotify")
, (mapRequest , "MapRequest")
, (reparentNotify , "ReparentNotify")
, (configureNotify , "ConfigureNotify")
, (configureRequest , "ConfigureRequest")
, (gravityNotify , "GravityNotify")
, (resizeRequest , "ResizeRequest")
, (circulateNotify , "CirculateNotify")
, (circulateRequest , "CirculateRequest")
, (propertyNotify , "PropertyNotify")
, (selectionClear , "SelectionClear")
, (selectionRequest , "SelectionRequest")
, (selectionNotify , "SelectionNotify")
, (colormapNotify , "ColormapNotify")
, (clientMessage , "ClientMessage")
, (mappingNotify , "MappingNotify")
, (lASTEvent , "LASTEvent")
]
eventName :: Event -> String
eventName e = maybe ("unknown " ++ show x) id $ lookup x eventTable
where x = fromIntegral $ ev_event_type e
getEvent :: XEventPtr -> IO Event
getEvent p = do
type_ <- (\hsc_ptr -> peekByteOff hsc_ptr 0) p
serial <- (\hsc_ptr -> peekByteOff hsc_ptr 4) p
send_event <- (\hsc_ptr -> peekByteOff hsc_ptr 8) p
display <- fmap Display ((\hsc_ptr -> peekByteOff hsc_ptr 12) p)
case () of
_ | type_ == configureRequest -> do
parent <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
x <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
y <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
width <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
height <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
border_width <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
above <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
detail <- (\hsc_ptr -> peekByteOff hsc_ptr 48) p
value_mask <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
return $ ConfigureRequestEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_parent = parent
, ev_window = window
, ev_x = x
, ev_y = y
, ev_width = width
, ev_height = height
, ev_border_width = border_width
, ev_above = above
, ev_detail = detail
, ev_value_mask = value_mask
}
| type_ == configureNotify -> do
return (ConfigureEvent type_ serial send_event display)
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 16) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 20) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 24) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 28) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 32) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 36) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 40) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 44) p
`ap` (\hsc_ptr -> peekByteOff hsc_ptr 48) p
| type_ == mapRequest -> do
parent <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
return $ MapRequestEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_parent = parent
, ev_window = window
}
| type_ == mapNotify -> do
event <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
override_redirect <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
return $ MapNotifyEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_event = event
, ev_window = window
, ev_override_redirect = override_redirect
}
| type_ == mappingNotify -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
request <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
first_keycode <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
count <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
return $ MappingNotifyEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_window = window
, ev_request = request
, ev_first_keycode = first_keycode
, ev_count = count
}
| type_ == keyPress || type_ == keyRelease -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
root <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
subwindow <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
time <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
x <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
y <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
x_root <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
y_root <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
state <- ((\hsc_ptr -> peekByteOff hsc_ptr 48) p) :: IO CUInt
keycode <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
same_screen <- (\hsc_ptr -> peekByteOff hsc_ptr 56) p
return $ KeyEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_window = window
, ev_root = root
, ev_subwindow = subwindow
, ev_time = time
, ev_x = x
, ev_y = y
, ev_x_root = x_root
, ev_y_root = y_root
, ev_state = fromIntegral state
, ev_keycode = keycode
, ev_same_screen = same_screen
}
| type_ == buttonPress || type_ == buttonRelease -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
root <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
subwindow <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
time <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
x <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
y <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
x_root <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
y_root <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
state <- ((\hsc_ptr -> peekByteOff hsc_ptr 48) p) :: IO CUInt
button <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
same_screen <- (\hsc_ptr -> peekByteOff hsc_ptr 56) p
return $ ButtonEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_window = window
, ev_root = root
, ev_subwindow = subwindow
, ev_time = time
, ev_x = x
, ev_y = y
, ev_x_root = x_root
, ev_y_root = y_root
, ev_state = fromIntegral state
, ev_button = button
, ev_same_screen = same_screen
}
| type_ == motionNotify -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
x <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
y <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
return $ MotionEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_x = x
, ev_y = y
, ev_window = window
}
| type_ == destroyNotify -> do
event <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
return $ DestroyWindowEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_event = event
, ev_window = window
}
| type_ == unmapNotify -> do
event <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
from_configure <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
return $ UnmapEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_event = event
, ev_window = window
, ev_from_configure = from_configure
}
| type_ == enterNotify || type_ == leaveNotify -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
root <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
subwindow <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
time <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
x <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
y <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
x_root <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
y_root <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
mode <- (\hsc_ptr -> peekByteOff hsc_ptr 48) p
detail <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
same_screen <- (\hsc_ptr -> peekByteOff hsc_ptr 56) p
focus <- (\hsc_ptr -> peekByteOff hsc_ptr 60) p
state <- ((\hsc_ptr -> peekByteOff hsc_ptr 64) p) :: IO CUInt
return $ CrossingEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_window = window
, ev_root = root
, ev_subwindow = subwindow
, ev_time = time
, ev_x = x
, ev_y = y
, ev_x_root = x_root
, ev_y_root = y_root
, ev_mode = mode
, ev_detail = detail
, ev_same_screen = same_screen
, ev_focus = focus
, ev_state = fromIntegral state
}
| type_ == selectionRequest -> do
owner <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
requestor <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
selection <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
target <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
property <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
time <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
return $ SelectionRequest
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_owner = owner
, ev_requestor = requestor
, ev_selection = selection
, ev_target = target
, ev_property = property
, ev_time = time
}
| type_ == propertyNotify -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
atom <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
time <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
state <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
return $ PropertyEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_window = window
, ev_atom = atom
, ev_time = time
, ev_propstate = state
}
| type_ == expose -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
x <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
y <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
width <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
height <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
count <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
return $ ExposeEvent
{ ev_event_type = type_
, ev_serial = serial
, ev_send_event = send_event
, ev_event_display = display
, ev_window = window
, ev_x = x
, ev_y = y
, ev_width = width
, ev_height = height
, ev_count = count
}
| type_ == clientMessage -> do
window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p