monitoring for non-X events - Xwindows

This is a discussion on monitoring for non-X events - Xwindows ; Hi everyone, How do I monitor for non-X events? My specific situation is this: I am writing a telnet-like application. Once control enters the event loop it blocks on XNextEvent(). How do I then check for incoming data on the ...

+ Reply to Thread
Results 1 to 3 of 3

Thread: monitoring for non-X events

  1. monitoring for non-X events

    Hi everyone,

    How do I monitor for non-X events? My specific situation is this: I am
    writing a telnet-like application. Once control enters the event loop it
    blocks on XNextEvent(). How do I then check for incoming data on the
    telnet socket? XNextEvent() only returns when there is an event related
    to the keyboard, mouse, or window - it doesn't monitor a socket connection.

    I'm just getting started with X, so any help is really appreciated. I
    tried reducing my app down to just a single window that displays anything
    that comes in over the socket. But I don't know how to get XNextEvent()
    to check if the socket has data.

    jimi
    Vs lbh guvax bs argjbex frphevgl nf na vzzhar flfgrz, Jvaqbjf vf UVI.
    -- Wbr Cyhgn


  2. Re: monitoring for non-X events

    jimi wrote:

    |How do I monitor for non-X events? My specific situation is this: I am
    |writing a telnet-like application. Once control enters the event loop it
    |blocks on XNextEvent(). How do I then check for incoming data on the
    |telnet socket? XNextEvent() only returns when there is an event related
    |to the keyboard, mouse, or window - it doesn't monitor a socket connection.

    |I'm just getting started with X, so any help is really appreciated. I
    |tried reducing my app down to just a single window that displays anything
    |that comes in over the socket. But I don't know how to get XNextEvent()
    |to check if the socket has data.

    Use XCheckMaskEvent() or XCheckIfEvent() or a "while XPending()
    XNextEventselect()" loop. When you empty the event queue use select()
    or poll() with both your socket and the fildes from XConnectionNumber().
    Remember that you probably need to handle multiple events for one wakeup
    from select. Xlib can read and buffer multiple events when you make a
    call that returns a single event.

    --
    Mike Stroyan, mike.stroyan@hp.com

  3. Re: monitoring for non-X events

    Hi.

    I wrote something similar some time ago. Unfortunatly
    I don't have the sources here. So the following is some
    code skelet I'm able to reproduce now. It shows how to
    play with select() and XNextEvent() together.

    It should lead you but don't expect to compile
    it at first attempts! I didn't try to compile it.
    Also you should to check return values and handle
    errors properly as your homework :-)

    Finally note that it's somewhat unix/linux-friendly.
    On other platforms it wouldn't worked probably...

    Mity



    #include
    #include
    #include
    #include
    #include


    /* info about FD */
    typedef struct fd_info fd_info_t;
    struct fd_info {
    int fd;
    int user; // 0 .. internal for Xlib, 1 .. our own fd
    fd_info_t* next;
    }

    static fd_set fd_mask; /* set of FD to check */

    static fd_info_t* fd_head = NULL; /* list of our fd_infos */
    static fd_info_t* fd_tail = NULL;

    /* add new FD */
    fd_info_t*
    fd_add(int fd, int user)
    {
    fd_info_t* info = (fd_info_t*) malloc(sizeof(fd_info_t));
    info->fd = fd;
    info->next = NULL;

    /* add it into the list */
    if(fd_tail)
    fd_tail->next = info;
    else
    fd_head = info;
    fd_tail = info;

    /* set the fd_set */
    FD_SET(fd, &fd_mask);

    return info;
    }

    /* remove FD */
    void
    fd_remove(fd_info_t* info)
    {
    fd_info_t* tmp = fd_head;
    fd_info_t* tmp_prev = NULL;

    while(tmp) {
    if(tmp == info) {
    if(tmp_prev)
    tmp_prev->next = info->next;
    else
    fd_head = info->next;
    FD_CLR(info->fd, &fd_mask);
    free(info);
    return;
    }

    tmp_prev = tmp;
    tmp = tmp->next;
    }
    }

    /* callback function registered with XAddConnectionWatch() */
    void
    fd_notify(Display* dpy, XPointer client_data,
    int fd, Bool opening, XPointer *watch_data)
    {
    fd_info_t* info;
    if(opening) { /* Xlib opens new internal FD */
    info = fd_add(fd, 0);
    *watch_data = info;
    } else { /* Xlib closes some internal FD */
    info = *watch_data;
    fd_remove(info);
    }
    }


    static Display* dpy;

    /* initialization */
    void
    open_display(void)
    {
    FD_ZERO(&fd_mask);
    dpy = XOpenConnection(NULL);
    fd_add(ConnectioNumber(dpy));
    XAddConnectionWatch(dpy, fd_notify, NULL);
    }

    /* cleaning up */
    void
    close_display(void)
    {
    XRemoveConnectionWatch(dpy, fd_notify, NULL);
    CloseDisplay(dpy);
    dpy = NULL;
    while(fd_head)
    fd_remove(fd_head);
    }


    int
    main(int argc, char** argv)
    {
    int i, n;
    int fd_socket;
    fd_info_t* info;
    XEvent evt;
    int end = 0;

    open_display();

    // TODO: init fd_socket

    fd_add(fd_socket, 1);

    /* main loop */
    while(!end) {
    /* The XFlush() is required! Normally this is done automatically
    * in XNextEvent() but we need to do it before the select() below.
    */
    XFlush(dpy);

    /* If you want to listen on the socket as well you will need
    * other fd_set variable and pass it to the select() as third
    * parameter (insted of NULL). Ssee 'man select' for more info.
    *
    * Also it would require a bit more complicated logic where
    * we analyze on which fd is some activity.
    *
    * However I beleive that after inspecting this source you will
    * be able to do it yourself...
    */
    n = select(FD_SETSIZE, &fd_mask, NULL, NULL, NULL);
    if(n < 0) {
    if(errno == EINTR) {
    // TODO: select() interrupted by some signal -- handle it
    continue;
    } else {
    // TODO: select() failed, handle the error
    exit(-1);
    }
    }

    /* Analyze which FD(s) changed status */
    i = 0;
    info = fd_head;
    while(i < n && info) {
    if(FD_ISSET(info->fd, &fd_mask)) {
    if(info->user) {
    // TODO: something happened on our socket. handle it
    } else {
    /* Let Xlib to convert the received data to XEvents. */
    XProcessInternalConnection(dpy, info->fd);
    }
    i++;
    }
    info = info->next;
    }

    /* Finaly process all queued events. */
    while(XIsPending(dpy)) {
    XNextEvent(dpy, &evt);
    // TODO: process the event here
    }
    }

    close_display();

    return 0;
    }

+ Reply to Thread