Search code examples
c++x11xlibxorg

Xdamage: get event on window content changes


I am a beginner in xlib and I want to catch event on window content changes. For examples if some region changed. I've read that I need to use Xdamage for that and this is my code

    Display* display = XOpenDisplay(NULL);
    Window root = DefaultRootWindow(display);
    XWindowAttributes attributes = {0};
    XGetWindowAttributes(display, root, &attributes);
    int width, height;
    width = attributes.width;
    height = attributes.height;
    //XDAMAGE INIT
    int damage_event, damage_error, test;
    test = XDamageQueryExtension(display, &damage_event, &damage_error);
    Damage damage = XDamageCreate(display, root, XDamageReportNonEmpty);
    while (true){
        XEvent event;
        XNextEvent(display,&event);
        //HERE I GET EVENT
        XDamageSubtract(display,damage,None,None);
    }
    XCloseDisplay(display);

So, I have a working example in which I can get event and its type.The types, as I understand are xlib types - https://tronche.com/gui/x/xlib/events/types.html. But how can I find out from event that window was changed.


Solution

  • What you are actually receiving are DamageNotify events in your normal event loop that look like so:

    typedef struct {
       int type;            /* event base */
       unsigned long serial;
       Bool send_event;
       Display *display;
       Drawable drawable;
       Damage damage;
       int level;
       Bool more;           /* more events will be delivered immediately */
       Time timestamp;
       XRectangle area;
       XRectangle geometry;
    } XDamageNotifyEvent;
    

    according to the documentation from https://www.x.org/releases/current/doc/damageproto/damageproto.txt

    The area member reports the damaged rectangular area as an XRectangle.

    The drawable member normally reports the window that was damaged.

    Note XNextEvent will always return an XEvent That is the static type returned by the function. It also has a dynamic type that depends on the ev->type member. - Check its type field to find out if you may cast it to an XDamageEvent:

    XEvent ev;
    
    /* We might need a pointer to an XDamageEvent... */
    XDamageNotifyEvent *dev;
    
    while (1) {
       XNextEvent(display,&ev);
       switch (ev.type){
          ...
          case DamageNotify:
             dev = (XDamageNotifyEvent*)&ev; /* if type matches, cast to XDamageNotify  event */
             printf ("Damage notification in window %d\n", dev->drawable);
             printf ("Rectangle x=%d, y=%d, w=%d, h=%d\n",
                     dev->area.x, dev->area.y, 
                     dev->area.width, dev->area.height);
             break;
          ...
       }