[Haskell-cafe] X Haskell Bindings

Spencer Janssen spencerjanssen at gmail.com
Sun Aug 17 20:34:42 EDT 2008


On Sat, Aug 16, 2008 at 04:07:25PM -0500, Antoine Latter wrote:
> Haskellers,
> 
> I'm slowly porting XCB (the X C Bindings) to Haskell, and I would like
> input from any interested parties.
> 
> The following is a summary of my plan so far.  I'm interested in
> hearing any suggestions or concerns about what a Haskell library for
> writing X clients should look like.  This is not a release
> announcement, and I can't make any promises about when this will be
> delivered.
> 
> Code is available in darcs:
> --  darcs get http://community.haskell.org/~aslatter/code/xhb
> 
> Some of the  advantages XCB claims over xlib are:
>   + smaller API
>   + latency hiding when communicating with the X server
>   + direct access to the X protocol
>   + improved threading support
>   + easier to extend
> 
> What I plan for the X Haskell Bindings (XHB) are as follows:
> 
>  + All requests to the server are non-blocking (under most circumstances)
> 
>  + Requests which produce a reply from the server return a "token" or "receipt"
> 
>  + The caller may then, at a time of their choosing, query the receipt
> for the response (or error) from the
>     server.  This query is blocking.
> 
> The API will look something like:
> 
> > -- | Create a window as specified
> > createWindow :: Connection -> CreateWindow -> IO ()
> 
> > -- | Instruct the server that it should begin displaying the named window
> > mapWindow :: Connection -> WINDOW -> IO ()
> 
> > -- | List all of the extensions supported by the server
> > listExtensions :: Connection -> IO (Receipt (ListExtensionsReply))
> 
> > -- | Query a receipt for a response
> > getReply :: Receipt a -> IO (Either XError a)
> 
> Note that the first two requests do not have replies, whereas the
> third request expects a reply from the server.
> 
> Since the request to create a window has so many parameters, these
> parameters are all wrapped up into a "CreateWindow" data type, which
> is only ever used by the "createWindow" function.  The "mapWindow"
> request only has one parameter, so it does not need it's own
> "MapWindow" data type.

I think this is a nice idea.  This type signature from the X11 library is
absolutely unmanageable:

    createWindow :: Display -> Window -> Position -> Position -> Dimension
                 -> Dimension -> CInt -> CInt -> WindowClass -> Visual ->
                 AttributeMask -> Ptr SetWindowAttributes -> IO Window

> What I don't have planned out is what to do with the stream of events
> and errors that come back from the server.
> 
> If an error is related to an outstanding receipt, it gets dumped there
> for the caller to examine directly.  Other errors go into an error
> queue.
> 
> Events go into a similar event queue.
> 
> How should this queue be exposed in the API?  Should the user of the
> library register an error/event callback?
> 
> > registerErrorCallback :: Connection -> (XError -> IO ()) -> IO ()

Classic libX11 does this, and it is rather inconvenient to program with.
Occasionally it is necessary to handle an error thrown by a specific request,
yielding code like this:

    do h <- getHandler c -- save the old handler so we can restore it later
       setHandler c myHandlingFn
       performSomeActionsWhichMayFail
       setHandler c h

Not only is this code ugly, it does not work correctly when the connection may
be concurrently used by several threads.

> Or is something like this enough:
> 
> > pollForError :: Connection -> IO (Maybe (XError))
> 
> > waitForError :: Connection -> IO XError

I think XCB's error system is particularly nice.  Requests with no
corresponding responses have two variants: unchecked (the default), and
checked.  Unchecked requests have a void return type, and any errors they
generate go in the error queue.  Checked requests return a cookie (the same
mechanism used for requests with responses) which can be used to collect any
errors generated by that response.

> Each X extension defines its own set of errors and events
> (potentially).  Should all of these be lumped together into one giant
> sum-type for errors and one for events?
> 
> Take care,
> Antoine


Cheers,
Spencer Janssen


More information about the Haskell-Cafe mailing list