2017-02-14 18 views
1

Я новичок в xlib и хочу поймать событие при изменении содержимого окна. Например, если какая-то область изменилась. Я читал, что мне нужно использовать Xdamage для этого, и это мой код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); 

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

+0

Вы хотите проверить возвращаемое значение 'XDamageQueryExtension'. Не гарантируется, что расширение фактически загружено. – tofro

ответ

4

То, что вы на самом деле получения являются 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; 
     ... 
    } 
+0

Спасибо за ваш ответ. Но можете ли вы объяснить, как я могу получить 'XDamageNotifyEvent' вместо' XEvent'? –

+0

Обратите внимание, что XEvent имеет как * статический * (его тип «C»), так и тип * dynamic *. 'XNextEvnet' возвращает' XEvent', который фактически может быть событием 'XDamage', если его динамический тип говорит об этом. Пример добавлен в ответ. – tofro

+0

Я разработчик Java. Если вам не сложно, можете ли вы показать, как получить 'XDamageNotifyEvent'? –

1

Поздно, но для тех, кто ищет в области, которая на самом деле изменилось (EV-> область координаты и размер окна, для меня по крайней мере):

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); 
Смежные вопросы