Question

I'm simply trying to understand the technique of how event handlers are called in X11. So in Linux/X11, if a window registers for events in ASyncMode (i.e. PointerMotion), how does X11 call the event handler for that process?

Are they using some form of interrupts?

What baffles me is that my process has nothing that is polling for X11 events. I even attached gdb and verified that there are no threads running under the scene that could've been started by X11 libs. So there must a gap in my knowledge as to how this actually works.

overflow me!

Was it helpful?

Solution

X11 clients use tcp or unix socket connection (usually port 6000 + display number for tcp and '/tmp/.X11-unix/X' + display number for domain socket) for communication. The protocol itself is duplex, you can send requests at any time and you receive replies, errors and events. Events and errors are always 32 bytes long packets.

There are various strategies on how to process incoming data from X server. With xlib, after each request known to produce response there is blocking read() call to read that much data. During 'idle' time you are expected to read all events and errors from connection manually:

   while(1) {
     XNextEvent(d, &e);
                        /* draw or redraw the window */
     if(e.type==Expose) {
       XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
     }
                        /* exit on key press */
     if(e.type==KeyPress)
       break;

     // Handle Windows Close Event
     if(e.type==ClientMessage)
        break;
   }

In this snippet XNextEvent consumes 32 bytes of data from socket into e structure, and code in while loop dispatches it depending on app logic and event type and payload.

In some other libraries like node-x11 (note: I'm author) event loop is hidden behind framework async io model and happens implicitly.

var x11 = require('x11');
var PointerMotion = x11.eventMask.PointerMotion;

x11.createClient(function(err, display) {
    var X = display.client;
    var root = display.screen[0].root;
    var wid = X.AllocID();
    X.CreateWindow(
       wid, root, 
       0, 0, 400, 300, 
       0, 0, 0, 0,
       { 
           eventMask: PointerMotion  
       }
    );
    X.MapWindow(wid);

    X.on('event', function(ev) {
        if (ev.name == 'PointerMotion')
        {
            console.log('Mouse motion!', [ev.x, ev.y]);
        }
    });

    X.on('error', function(e) {
        console.log(e);
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top