Xdamage: получить событие при изменении содержимого окна

Я новичок в xlib и хочу отлавливать события при изменении содержимого окна. Например, если какой-то регион изменился. Я прочитал, что мне нужно использовать Xdamage для этого, и это мой код

    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);

Итак, у меня есть рабочий пример, в котором я могу получить событие и его тип. Типы, как я понимаю, являются типами xlib — https://tronche.com/gui/x/xlib/events/types.html. Но как я могу узнать из события, что окно было изменено.

1

Решение

То, что вы на самом деле получаете DamageNotify события в вашем обычном цикле событий, которые выглядят так:

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;

согласно документации от https://www.x.org/releases/current/doc/damageproto/damageproto.txt

area член сообщает о поврежденной прямоугольной области как XRectangle.

drawable участник обычно сообщает о поврежденном окне.

Заметка XNextEvent всегда будет возвращать XEvent Это статический тип, возвращаемый функцией. Он также имеет динамический тип, который зависит от ev->type член. — проверь его type поле, чтобы узнать, если вы можете привести его к 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;
...
}
4

Другие решения

Поздно, но для любого, кто ищет область, которая действительно изменилась (ev-> area — это координаты и размер окна, по крайней мере, для меня):

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);
1

По вопросам рекламы [email protected]