Xdamage:获取窗口内容更改的事件

时间:2017-02-14 16:11:15

标签: c++ x11 xlib xorg

我是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。但是如何从事件中发现窗口已经改变。

2 个答案:

答案 0 :(得分: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这是函数返回的 static 类型。它还具有依赖于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;
      ...
   }

答案 1 :(得分:1)

迟到了,但是对于任何寻找实际改变区域的人来说(至少对于我而言,区域是窗口坐标和大小):

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