X11无法捕获GTK窗口的活动窗口截图。

5

这是一个更大研究项目的子项目。我试图每100毫秒拍摄一次活动窗口(浏览器)的截图,然后将其存储在内存中以供OpenCV处理。我从一个类似的问题中找到了一个截屏解决方案,目前正在尝试使用它。下面的代码片段似乎可以在拍摄整个桌面截图或特定窗口截图时正常工作,但对于GTK窗口则不起作用。我尝试在Debian Squeeze上拍摄Iceweasel和Nautilus的截图,但它根本不起作用。我是X11的新手,不知道如何检查错误,或者是否有什么我错过的东西,因为这似乎适用于QT窗口。

typedef int (*handler)(Display *, XErrorEvent *);

int handleX11Error(Display *d, XErrorEvent *er)
{
   std::cout << "X11 Error: " << er->error_code << std::endl;
}

int main()
{
    std::cout << "Sleeping 5 seconds" << std::endl;
   // we may need to sleep if we want to focus another window.
   sleep(5); 
   std::cout << "taking screenshot" << std::endl;

   Display *display = XOpenDisplay(NULL);
   //Window root = DefaultRootWindow(display);
   XWindowAttributes gwa;
   int revert = RevertToNone;
   Window active;
   XErrorEvent *error;
   handler myHandler = &handleX11Error;
   XSetErrorHandler(myHandler);

   // X11 - Get Window that has focus
   XGetInputFocus(display,&active,&revert);

   //XGetWindowAttributes(display, root, &gwa);
   if (!XGetWindowAttributes(display, active, &gwa))
     std::cout << "XGetWindowAttributes failed" << std::endl;

   int width = gwa.width;
   int height = gwa.height;

   //XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);
   XImage *image = XGetImage(display,active, 0,0 , width,height,XAllPlanes(), ZPixmap);

   unsigned char *array = new unsigned char[width * height * 3];
   CImg<unsigned char> pic(array,width,height,1,3);

   for (int x = 0; x < width; x++){
      for (int y = 0; y < height ; y++){
     pic(x,y,0) = (XGetPixel(image,x,y) & image->red_mask ) >> 16;
     pic(x,y,1) = (XGetPixel(image,x,y) & image->green_mask ) >> 8;
     pic(x,y,2) = XGetPixel(image,x,y) & image->blue_mask;
      }
   }
   delete[] array;
   pic.save_png("blah.png");
   std::cout <<  "Finished" << std::endl;
   return 0;
}

上述代码适用于完整的桌面截图或QT。我没有收到任何错误(不知道我是否正确处理了它们)。只是一张几个字节的空白图片,这让我想到其中一个X函数失败了(XGetInputFocus、XGetWindowAttributes、XGetImage),我认为是XGetFocus没有正常工作。我错过了什么,还是有其他替代方法吗?请注意,我正在运行KDE(4.4.5),如果有任何重要性,请告诉我。
更新:
我尝试使用Qt4进行截图,虽然它可以正常工作,但在尝试从X11获取焦点窗口时也遇到了同样的问题。
int main(int argc, char **argv)
{
    sleep(5);
    Display *display = XOpenDisplay(NULL);
    int revert = RevertToNone;
    Window active;
    XGetInputFocus(display,&active,&revert);
    QApplication app(argc, argv);    
    QPixmap pixmap = QPixmap::grabWindow(active);
    pixmap.save("test.png","PNG");
    QPushButton quit("Quit");
    quit.resize(75, 30);
    quit.setFont(QFont("Times", 18, QFont::Bold));
    QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));
    quit.show();
    return app.exec();
}

我相信是XGetInputFocus()出了问题,导致了这个错误。
1个回答

7

由于我还没有得到任何答案,而且我已经花了一整天的时间寻找解决方案,所以我想分享一下我是如何让这个工作的。 系统是Debian Squeeze,运行着KDE 4.4.5。 显然,KDE和GTK应用程序不能很好地协同工作。引用来自其他stackoverflow帖子和互联网上的人的话,非kde应用程序可能不会遵守_NET_WM_STATE,或者可能是其他什么问题,我真的不知道。但是我尝试的GTK应用程序与所有Qt4应用程序都适用的代码片段不起作用的事实,暗示了与某种形式的报告相关的问题。在网上发现的一些罕见的(我真的是罕见的)解决方案指出,也许可以遍历X11窗口树以查找活动窗口,但对我而言,这似乎太复杂了,并且我看到有人发布帖子没有得到成功的结果。 我想出来的(这是从网络上找到的片段中拼凑而成的)是以下使用xdo(Debian上的libxdo)

   Display *display = XOpenDisplay(NULL);
   Window active;
   XWindowAttributes gwa;

   // Use xdo to find the active window - care on the display !
   xdo_t* xdocontext = xdo_new(0);
   xdo_window_get_active(xdocontext, &active);
   if(active){
      XGetWindowAttributes(display, active, &gwa);
      XImage *image = XGetImage(display,active, 0,0 , gwa.width,gwa.height,XAllPlanes(), ZPixmap);
      unsigned char *array = new unsigned char[gwa.width * gwa.height * 3];
      CImg<unsigned char> pic(array,gwa.width,gwa.height,1,3);

      for (int x = 0; x < gwa.width; x++){
         for (int y = 0; y < gwa.height ; y++){
             pic(x,y,0) = (XGetPixel(image,x,y) & image->red_mask ) >> 16;
             pic(x,y,1) = (XGetPixel(image,x,y) & image->green_mask ) >> 8;
             pic(x,y,2) = XGetPixel(image,x,y) & image->blue_mask;
         }
      }
      delete[] array;
      pic.save_png("blah.png");
   } else std::cout << "xdo failed to get active window" << std::endl;

上面的方法适用于GTK和KDE应用程序,我希望这可以帮助那些遇到问题的人,因为网上似乎很少有相关的帖子。

我测试过了,但是当应用于这个程序时,对我的nautilus窗口不起作用:https://dev59.com/H2Eh5IYBdhLWcg3wKQnY - Minimus Heximus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接