{-# INCLUDE "XlibExtras.h" #-}
{-# LINE 1 "Graphics/X11/Xlib/Extras.hsc" #-}
-----------------------------------------------------------------------------
{-# LINE 2 "Graphics/X11/Xlib/Extras.hsc" #-}
-- |
-- Module      :
-- Copyright   :  (c) Spencer Janssen
-- License     :  BSD3-style (see LICENSE)
-- 
-- Stability   :  stable
--
-----------------------------------------------------------------------------
--
-- missing functionality from the X11 library
--

module Graphics.X11.Xlib.Extras where

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


{-# LINE 25 "Graphics/X11/Xlib/Extras.hsc" #-}

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

    deriving Show

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
    -- All events share this layout and naming convention, there is also a
    -- common Window field, but the names for this field vary.
    type_      <- (\hsc_ptr -> peekByteOff hsc_ptr 0) p
{-# LINE 211 "Graphics/X11/Xlib/Extras.hsc" #-}
    serial     <- (\hsc_ptr -> peekByteOff hsc_ptr 4) p
{-# LINE 212 "Graphics/X11/Xlib/Extras.hsc" #-}
    send_event <- (\hsc_ptr -> peekByteOff hsc_ptr 8) p
{-# LINE 213 "Graphics/X11/Xlib/Extras.hsc" #-}
    display    <- fmap Display ((\hsc_ptr -> peekByteOff hsc_ptr 12) p)
{-# LINE 214 "Graphics/X11/Xlib/Extras.hsc" #-}
    case () of

        -------------------------
        -- ConfigureRequestEvent:
        -------------------------
        _ | type_ == configureRequest -> do
            parent       <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 221 "Graphics/X11/Xlib/Extras.hsc" #-}
            window       <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 222 "Graphics/X11/Xlib/Extras.hsc" #-}
            x            <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 223 "Graphics/X11/Xlib/Extras.hsc" #-}
            y            <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
{-# LINE 224 "Graphics/X11/Xlib/Extras.hsc" #-}
            width        <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
{-# LINE 225 "Graphics/X11/Xlib/Extras.hsc" #-}
            height       <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
{-# LINE 226 "Graphics/X11/Xlib/Extras.hsc" #-}
            border_width <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
{-# LINE 227 "Graphics/X11/Xlib/Extras.hsc" #-}
            above        <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
{-# LINE 228 "Graphics/X11/Xlib/Extras.hsc" #-}
            detail       <- (\hsc_ptr -> peekByteOff hsc_ptr 48) p
{-# LINE 229 "Graphics/X11/Xlib/Extras.hsc" #-}
            value_mask   <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
{-# LINE 230 "Graphics/X11/Xlib/Extras.hsc" #-}
            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
                        }

          ------------------
          -- ConfigureEvent:
          ------------------
          | type_ == configureNotify -> do
            return (ConfigureEvent type_ serial send_event display)
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 253 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 254 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 255 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 28) p
{-# LINE 256 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 32) p
{-# LINE 257 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 36) p
{-# LINE 258 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 40) p
{-# LINE 259 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 44) p
{-# LINE 260 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` (\hsc_ptr -> peekByteOff hsc_ptr 48) p
{-# LINE 261 "Graphics/X11/Xlib/Extras.hsc" #-}

          -------------------
          -- MapRequestEvent:
          -------------------
          | type_ == mapRequest -> do
            parent <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 267 "Graphics/X11/Xlib/Extras.hsc" #-}
            window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 268 "Graphics/X11/Xlib/Extras.hsc" #-}
            return $ MapRequestEvent
                        { ev_event_type    = type_
                        , ev_serial        = serial
                        , ev_send_event    = send_event
                        , ev_event_display = display
                        , ev_parent        = parent
                        , ev_window        = window
                        }

          -------------------
          -- MapNotifyEvent
          -------------------
          | type_ == mapNotify -> do
            event             <- (\hsc_ptr -> peekByteOff hsc_ptr 16)  p
{-# LINE 282 "Graphics/X11/Xlib/Extras.hsc" #-}
            window            <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 283 "Graphics/X11/Xlib/Extras.hsc" #-}
            override_redirect <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 284 "Graphics/X11/Xlib/Extras.hsc" #-}
            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
                        }

          -------------------
          -- MappingNotifyEvent
          -------------------
          | type_ == mappingNotify -> do
            window        <- (\hsc_ptr -> peekByteOff hsc_ptr 16)          p
{-# LINE 299 "Graphics/X11/Xlib/Extras.hsc" #-}
            request       <- (\hsc_ptr -> peekByteOff hsc_ptr 20)         p
{-# LINE 300 "Graphics/X11/Xlib/Extras.hsc" #-}
            first_keycode <- (\hsc_ptr -> peekByteOff hsc_ptr 24)   p
{-# LINE 301 "Graphics/X11/Xlib/Extras.hsc" #-}
            count         <- (\hsc_ptr -> peekByteOff hsc_ptr 28)           p
{-# LINE 302 "Graphics/X11/Xlib/Extras.hsc" #-}

            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
                        }

          ------------
          -- KeyEvent:
          ------------
          | type_ == keyPress || type_ == keyRelease -> do
            window      <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 319 "Graphics/X11/Xlib/Extras.hsc" #-}
            root        <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 320 "Graphics/X11/Xlib/Extras.hsc" #-}
            subwindow   <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 321 "Graphics/X11/Xlib/Extras.hsc" #-}
            time        <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
{-# LINE 322 "Graphics/X11/Xlib/Extras.hsc" #-}
            x           <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
{-# LINE 323 "Graphics/X11/Xlib/Extras.hsc" #-}
            y           <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
{-# LINE 324 "Graphics/X11/Xlib/Extras.hsc" #-}
            x_root      <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
{-# LINE 325 "Graphics/X11/Xlib/Extras.hsc" #-}
            y_root      <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
{-# LINE 326 "Graphics/X11/Xlib/Extras.hsc" #-}
            state       <- ((\hsc_ptr -> peekByteOff hsc_ptr 48) p) :: IO CUInt
{-# LINE 327 "Graphics/X11/Xlib/Extras.hsc" #-}
            keycode     <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
{-# LINE 328 "Graphics/X11/Xlib/Extras.hsc" #-}
            same_screen <- (\hsc_ptr -> peekByteOff hsc_ptr 56) p
{-# LINE 329 "Graphics/X11/Xlib/Extras.hsc" #-}
            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
                        }

          ---------------
          -- ButtonEvent:
          ---------------
          | type_ == buttonPress || type_ == buttonRelease -> do

            window      <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 353 "Graphics/X11/Xlib/Extras.hsc" #-}
            root        <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 354 "Graphics/X11/Xlib/Extras.hsc" #-}
            subwindow   <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 355 "Graphics/X11/Xlib/Extras.hsc" #-}
            time        <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
{-# LINE 356 "Graphics/X11/Xlib/Extras.hsc" #-}
            x           <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
{-# LINE 357 "Graphics/X11/Xlib/Extras.hsc" #-}
            y           <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
{-# LINE 358 "Graphics/X11/Xlib/Extras.hsc" #-}
            x_root      <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
{-# LINE 359 "Graphics/X11/Xlib/Extras.hsc" #-}
            y_root      <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
{-# LINE 360 "Graphics/X11/Xlib/Extras.hsc" #-}
            state       <- ((\hsc_ptr -> peekByteOff hsc_ptr 48) p) :: IO CUInt
{-# LINE 361 "Graphics/X11/Xlib/Extras.hsc" #-}
            button      <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
{-# LINE 362 "Graphics/X11/Xlib/Extras.hsc" #-}
            same_screen <- (\hsc_ptr -> peekByteOff hsc_ptr 56) p
{-# LINE 363 "Graphics/X11/Xlib/Extras.hsc" #-}

            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
                        }

          ----------------------
          -- DestroyWindowEvent:
          ----------------------
          | type_ == destroyNotify -> do
            event  <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 387 "Graphics/X11/Xlib/Extras.hsc" #-}
            window <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 388 "Graphics/X11/Xlib/Extras.hsc" #-}
            return $ DestroyWindowEvent
                        { ev_event_type    = type_
                        , ev_serial        = serial
                        , ev_send_event    = send_event
                        , ev_event_display = display
                        , ev_event         = event
                        , ev_window        = window
                        }


          --------------------
          -- UnmapNotifyEvent:
          --------------------
          | type_ == unmapNotify -> do
            event          <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 403 "Graphics/X11/Xlib/Extras.hsc" #-}
            window         <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 404 "Graphics/X11/Xlib/Extras.hsc" #-}
            from_configure <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 405 "Graphics/X11/Xlib/Extras.hsc" #-}
            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
                        }

          --------------------
          -- CrossingEvent
          --------------------
          | type_ == enterNotify || type_ == leaveNotify -> do
            window        <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 420 "Graphics/X11/Xlib/Extras.hsc" #-}
            root          <- (\hsc_ptr -> peekByteOff hsc_ptr 20) p
{-# LINE 421 "Graphics/X11/Xlib/Extras.hsc" #-}
            subwindow     <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 422 "Graphics/X11/Xlib/Extras.hsc" #-}
            time          <- (\hsc_ptr -> peekByteOff hsc_ptr 28) p
{-# LINE 423 "Graphics/X11/Xlib/Extras.hsc" #-}
            x             <- (\hsc_ptr -> peekByteOff hsc_ptr 32) p
{-# LINE 424 "Graphics/X11/Xlib/Extras.hsc" #-}
            y             <- (\hsc_ptr -> peekByteOff hsc_ptr 36) p
{-# LINE 425 "Graphics/X11/Xlib/Extras.hsc" #-}
            x_root        <- (\hsc_ptr -> peekByteOff hsc_ptr 40) p
{-# LINE 426 "Graphics/X11/Xlib/Extras.hsc" #-}
            y_root        <- (\hsc_ptr -> peekByteOff hsc_ptr 44) p
{-# LINE 427 "Graphics/X11/Xlib/Extras.hsc" #-}
            mode          <- (\hsc_ptr -> peekByteOff hsc_ptr 48) p
{-# LINE 428 "Graphics/X11/Xlib/Extras.hsc" #-}
            detail        <- (\hsc_ptr -> peekByteOff hsc_ptr 52) p
{-# LINE 429 "Graphics/X11/Xlib/Extras.hsc" #-}
            same_screen   <- (\hsc_ptr -> peekByteOff hsc_ptr 56) p
{-# LINE 430 "Graphics/X11/Xlib/Extras.hsc" #-}
            focus         <- (\hsc_ptr -> peekByteOff hsc_ptr 60) p
{-# LINE 431 "Graphics/X11/Xlib/Extras.hsc" #-}
            state         <- ((\hsc_ptr -> peekByteOff hsc_ptr 64) p) :: IO CUInt
{-# LINE 432 "Graphics/X11/Xlib/Extras.hsc" #-}

            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
                        }

          -- We don't handle this event specifically, so return the generic
          -- AnyEvent.
          | otherwise -> do
            window <- (\hsc_ptr -> peekByteOff hsc_ptr 16) p
{-# LINE 457 "Graphics/X11/Xlib/Extras.hsc" #-}
            return $ AnyEvent
                        { ev_event_type    = type_
                        , ev_serial        = serial
                        , ev_send_event    = send_event
                        , ev_event_display = display
                        , ev_window        = window
                        }

data WindowChanges = WindowChanges
                        { wc_x :: CInt
                        , wc_y :: CInt
                        , wc_width :: CInt
                        , wc_height:: CInt
                        , wc_border_width :: CInt
                        , wc_sibling :: Window
                        , wc_stack_mode :: CInt
                        }

instance Storable WindowChanges where
    sizeOf _ = (28)
{-# LINE 477 "Graphics/X11/Xlib/Extras.hsc" #-}

    -- I really hope this is right:
    alignment _ = alignment (undefined :: CInt)

    poke p wc = do
        (\hsc_ptr -> pokeByteOff hsc_ptr 0) p $ wc_x wc
{-# LINE 483 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 4) p $ wc_y wc
{-# LINE 484 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 8) p $ wc_width wc
{-# LINE 485 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 12) p $ wc_height wc
{-# LINE 486 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 16) p $ wc_border_width wc
{-# LINE 487 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 20) p $ wc_sibling wc
{-# LINE 488 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 24) p $ wc_stack_mode wc
{-# LINE 489 "Graphics/X11/Xlib/Extras.hsc" #-}
        
    peek p = return WindowChanges
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 0) p)
{-# LINE 492 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 4) p)
{-# LINE 493 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 8) p)
{-# LINE 494 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 12) p)
{-# LINE 495 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 16) p)
{-# LINE 496 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 20) p)
{-# LINE 497 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 24) p)
{-# LINE 498 "Graphics/X11/Xlib/Extras.hsc" #-}

--
-- Some extra constants
--

none :: XID
none = 0
{-# LINE 505 "Graphics/X11/Xlib/Extras.hsc" #-}

anyButton :: Button
anyButton = 0
{-# LINE 508 "Graphics/X11/Xlib/Extras.hsc" #-}

anyKey :: KeyCode
anyKey = toEnum 0
{-# LINE 511 "Graphics/X11/Xlib/Extras.hsc" #-}

currentTime :: Time
currentTime = 0
{-# LINE 514 "Graphics/X11/Xlib/Extras.hsc" #-}

--
-- The use of Int rather than CInt isn't 64 bit clean.
--

foreign import ccall unsafe "XlibExtras.h XConfigureWindow"
    xConfigureWindow :: Display -> Window -> CULong -> Ptr WindowChanges -> IO CInt

foreign import ccall unsafe "XlibExtras.h XKillClient"
    killClient :: Display -> Window -> IO CInt

configureWindow :: Display -> Window -> CULong -> WindowChanges -> IO ()
configureWindow d w m c = do
    with c (xConfigureWindow d w m)
    return ()

foreign import ccall unsafe "XlibExtras.h XFree"
    xFree :: Ptr a -> IO CInt

foreign import ccall unsafe "XlibExtras.h XQueryTree"
    xQueryTree :: Display -> Window -> Ptr Window -> Ptr Window -> Ptr (Ptr Window) -> Ptr CInt -> IO Status

queryTree :: Display -> Window -> IO (Window, Window, [Window])
queryTree d w =
    alloca $ \root_return ->
    alloca $ \parent_return ->
    alloca $ \children_return ->
    alloca $ \nchildren_return -> do
        xQueryTree d w root_return parent_return children_return nchildren_return
        p <- peek children_return
        n <- fmap fromIntegral $ peek nchildren_return
        ws <- peekArray n p
        xFree p
        liftM3 (,,) (peek root_return) (peek parent_return) (return ws)

-- TODO: this data type is incomplete wrt. the C struct
data WindowAttributes = WindowAttributes
            { wa_x, wa_y, wa_width, wa_height, wa_border_width :: CInt
            , wa_map_state :: CInt
            , wa_override_redirect :: Bool
            }

instance Storable WindowAttributes where
    -- this might be incorrect
    alignment _ = alignment (undefined :: CInt)
    sizeOf _ = (92)
{-# LINE 560 "Graphics/X11/Xlib/Extras.hsc" #-}
    peek p = return WindowAttributes
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 0) p)
{-# LINE 562 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 4) p)
{-# LINE 563 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 8) p)
{-# LINE 564 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 12) p)
{-# LINE 565 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 16) p)
{-# LINE 566 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 68) p)
{-# LINE 567 "Graphics/X11/Xlib/Extras.hsc" #-}
                `ap` ((\hsc_ptr -> peekByteOff hsc_ptr 84) p)
{-# LINE 568 "Graphics/X11/Xlib/Extras.hsc" #-}
    poke p wa = do
        (\hsc_ptr -> pokeByteOff hsc_ptr 0) p $ wa_x wa
{-# LINE 570 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 4) p $ wa_y wa
{-# LINE 571 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 8) p $ wa_width wa
{-# LINE 572 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 12) p $ wa_height wa
{-# LINE 573 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 16) p $ wa_border_width wa
{-# LINE 574 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 68) p $ wa_map_state wa
{-# LINE 575 "Graphics/X11/Xlib/Extras.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 84) p $ wa_override_redirect wa
{-# LINE 576 "Graphics/X11/Xlib/Extras.hsc" #-}

foreign import ccall unsafe "XlibExtras.h XGetWindowAttributes"
    xGetWindowAttributes :: Display -> Window -> Ptr (WindowAttributes) -> IO Status

getWindowAttributes d w = alloca $ \p -> do
    xGetWindowAttributes d w p
    peek p

waIsViewable :: CInt
waIsViewable = fromIntegral $ 2
{-# LINE 586 "Graphics/X11/Xlib/Extras.hsc" #-}

-- | Run an action with the server
withServer :: Display -> IO () -> IO ()
withServer dpy f = do
    grabServer dpy
    f
    ungrabServer dpy

foreign import ccall unsafe "XlibExtras.h XFetchName"
    xFetchName :: Display -> Window -> Ptr CString -> IO Status

fetchName :: Display -> Window -> IO (Maybe String)
fetchName d w = alloca $ \p -> do
    xFetchName d w p
    cstr <- peek p
    if cstr == nullPtr
        then return Nothing
        else do
            str <- peekCString cstr
            xFree cstr
            return $ Just str

foreign import ccall unsafe "XlibExtras.h XGetTransientForHint"
    xGetTransientForHint :: Display -> Window -> Ptr Window -> IO Status

getTransientForHint :: Display -> Window -> IO (Maybe Window)
getTransientForHint d w = alloca $ \wp -> do
    status <- xGetTransientForHint d w wp
    if status == 0
        then return Nothing
        else Just `liftM` peek wp

------------------------------------------------------------------------
-- setWMProtocols :: Display -> Window -> [Atom] -> IO ()

{-
setWMProtocols :: Display -> Window -> [Atom] -> IO ()
setWMProtocols display w protocols =
    withArray protocols $ \ protocol_array ->
    xSetWMProtocols display w protocol_array (length protocols)
foreign import ccall unsafe "HsXlib.h XSetWMProtocols"
    xSetWMProtocols :: Display -> Window -> Ptr Atom -> CInt -> IO ()
-}

-- | The XGetWMProtocols function returns the list of atoms
-- stored in the WM_PROTOCOLS property on the specified win­
-- dow.  These atoms describe window manager protocols in
-- which the owner of this window is willing to participate.
-- If the property exists, is of type ATOM, is of format 32,
-- and the atom WM_PROTOCOLS can be interned, XGetWMProtocols
-- sets the protocols_return argument to a list of atoms,
-- sets the count_return argument to the number of elements
-- in the list, and returns a nonzero status.  Otherwise, it
-- sets neither of the return arguments and returns a zero
-- status.  To release the list of atoms, use XFree.
--
getWMProtocols :: Display -> Window -> IO [Atom]
getWMProtocols display w = do
    alloca $ \atom_ptr_ptr ->
      alloca $ \count_ptr -> do

       st <- xGetWMProtocols display w atom_ptr_ptr count_ptr
       if st == 0
            then return []
            else do sz       <- peek count_ptr
                    print sz
                    atom_ptr <- peek atom_ptr_ptr
                    atoms    <- peekArray (fromIntegral sz) atom_ptr
                    xFree atom_ptr
                    return atoms

foreign import ccall unsafe "HsXlib.h XGetWMProtocols"
    xGetWMProtocols :: Display -> Window -> Ptr (Ptr Atom) -> Ptr CInt -> IO Status


------------------------------------------------------------------------
-- Creating events

setEventType :: XEventPtr -> EventType -> IO ()
setEventType = (\hsc_ptr -> pokeByteOff hsc_ptr 0)
{-# LINE 666 "Graphics/X11/Xlib/Extras.hsc" #-}

-- hacky way to set up an XClientMessageEvent
-- Should have a Storable instance for XEvent/Event?
setClientMessageEvent :: XEventPtr -> Window -> Atom -> CInt -> Atom -> Time -> IO ()
setClientMessageEvent p window message_type format l_0_ l_1_ = do
    (\hsc_ptr -> pokeByteOff hsc_ptr 16)         p window
{-# LINE 672 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 20)   p message_type
{-# LINE 673 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 24)         p format
{-# LINE 674 "Graphics/X11/Xlib/Extras.hsc" #-}
    let datap = (\hsc_ptr -> hsc_ptr `plusPtr` 28) p :: Ptr CLong
{-# LINE 675 "Graphics/X11/Xlib/Extras.hsc" #-}
    poke        datap   (fromIntegral l_0_) -- does this work?
    pokeElemOff datap 1 (fromIntegral l_1_)

    return ()


{-
       typedef struct {
            int type;                /* ClientMessage */
            unsigned long serial;    /* # of last request processed by server */
            Bool send_event;         /* true if this came from a SendEvent request */
            Display *display;        /* Display the event was read from */
            Window window;
            Atom message_type;
            int format;
            union {
                 char b[20];
                 short s[10];
                 long l[5];
                    } data;
       } XClientMessageEvent;

-}

------------------------------------------------------------------------
-- XErrorEvents
-- 
-- I'm too lazy to write the binding
--

foreign import ccall unsafe "XlibExtras.h x11_extras_set_error_handler"
    xSetErrorHandler   :: IO ()

-- | refreshKeyboardMapping.  TODO Remove this binding when the fix has been commited to
-- X11
refreshKeyboardMapping :: Event -> IO ()
refreshKeyboardMapping ev@(MappingNotifyEvent {ev_event_display = (Display d)})
 = allocaBytes (32) $ \p -> do
{-# LINE 713 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 0) p $ ev_event_type    ev
{-# LINE 714 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 4) p $ ev_serial        ev
{-# LINE 715 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 8) p $ ev_send_event    ev
{-# LINE 716 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 12) p $ d
{-# LINE 717 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 16) p $ ev_window        ev
{-# LINE 718 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 20) p $ ev_request       ev
{-# LINE 719 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 24) p $ ev_first_keycode ev
{-# LINE 720 "Graphics/X11/Xlib/Extras.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 28) p $ ev_count         ev
{-# LINE 721 "Graphics/X11/Xlib/Extras.hsc" #-}
    xRefreshKeyboardMapping p
    return ()
refreshKeyboardMapping _ = return ()

foreign import ccall unsafe "XlibExtras.h XRefreshKeyboardMapping"
    xRefreshKeyboardMapping :: Ptr () -> IO CInt

-- Properties

foreign import ccall unsafe "XlibExtras.h XChangeProperty"
    xChangeProperty :: Display -> Window -> Atom -> Atom -> CInt -> CInt -> Ptr CUChar -> CInt -> IO Status

-- this assumes bytes are 8 bits.  I hope X isn't more portable than that :(

changeProperty8 :: Display -> Window -> Atom -> Atom -> CInt -> [Char] -> IO ()
changeProperty8 dpy w prop typ mode dat =
    withArrayLen (map (fromIntegral . fromEnum) dat) $ \ len ptr -> do
        xChangeProperty dpy w prop typ 8 mode ptr (fromIntegral len)
        return ()

propModeReplace, propModePrepend, propModeAppend :: CInt
propModeReplace = 0
{-# LINE 743 "Graphics/X11/Xlib/Extras.hsc" #-}
propModePrepend = 1
{-# LINE 744 "Graphics/X11/Xlib/Extras.hsc" #-}
propModeAppend = 2
{-# LINE 745 "Graphics/X11/Xlib/Extras.hsc" #-}