user5182503
user5182503

Reputation:

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.

Upvotes: 3

Views: 3025

Answers (2)

weltensturm
weltensturm

Reputation: 2162

Late, but for anyone looking for the area that actually changed (ev->area are the window coordinates and size, for me at least):

auto ev = (XDamageNotifyEvent*)e;
auto region = XFixesCreateRegion(display, null, 0);
XDamageSubtract(display, ev->damage, None, region);
int count;
auto area = XFixesFetchRegion(display, region, &count);
if(area){
    for(int i; i < count; i++){
        auto rect = area[i];
        // do something with rect
    }
    XFree(area);
}
XFixesDestroyRegion(display, region);

Upvotes: 2

tofro
tofro

Reputation: 6073

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

Upvotes: 3

Related Questions