Xlib 应用被覆盖遮挡或者移出屏幕时,获取窗口截图
在https://www.cnblogs.com/chaichengxun/p/15409996.html这篇文章里已经讲过,如果应用窗口位于屏幕外或者被遮挡,xlib不能获取完整的应用窗口截屏,如下
今天就来解决这个问题。
用到的头文件:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
用到的库:
-lXlib -lXcomposite -lXrender
代码:
static Display *xdisplay = 0; Display *disp() { if (!xdisplay) xdisplay = XOpenDisplay(NULL); return xdisplay; } XImage* GetDrawableThumbnail(Drawable src_drawable, Visual* visual, int src_width, int src_height) { XRenderPictFormat* format = XRenderFindVisualFormat(disp(), visual); if (!format) { cout <<"XRenderFindVisualFormat() failed"; return NULL; } XRenderPictureAttributes pa; pa.subwindow_mode = IncludeInferiors; Picture src = XRenderCreatePicture(disp(), src_drawable, format, CPSubwindowMode, &pa); if (!src) { cout << "XRenderCreatePicture() failed"; return NULL; } Pixmap dst_pixmap = XCreatePixmap(disp(), src_drawable, src_width, src_height, format->depth); if (!dst_pixmap) { cout << "XCreatePixmap() failed"; XRenderFreePicture(disp(), src); return NULL; } Picture dst = XRenderCreatePicture(disp(), dst_pixmap, format, 0, NULL); if (!dst) { cout << "XRenderCreatePicture() failed"; XFreePixmap(disp(), dst_pixmap); XRenderFreePicture(disp(), src); return NULL; } XRenderColor transparent = {0}; XRenderFillRectangle(disp(), PictOpSrc, dst, &transparent, 0, 0, src_width, src_height); XTransform xform = { { { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) } } }; XRenderSetPictureTransform(disp(), src, &xform); XRenderSetPictureFilter(disp(), src, FilterBest, NULL, 0); XRenderComposite(disp(), PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, src_width, src_height); XImage* image = XGetImage(disp(), dst_pixmap, 0, 0, src_width, src_height, AllPlanes, ZPixmap); return image; }
将XImage转换成QPixmap:
void AppListSelDlg::GetPixmap(unsigned long win, QPixmap &pixmap) { Display *display_ = disp(); XCompositeRedirectWindow(display_, win, CompositeRedirectAutomatic); Pixmap src_pixmap = XCompositeNameWindowPixmap(display_, win); if (!src_pixmap) { printf("XCompositeNameWindowPixmap() failed"); return; } XWindowAttributes attr; if (!XGetWindowAttributes(display_, win, &attr)) { printf( "XGetWindowAttributes() failed"); XFreePixmap(display_, src_pixmap); return ; } XImage* pImage = XCompcap::GetDrawableThumbnail(src_pixmap, attr.visual, attr.width, attr.height); QImage image = QImage((const uchar *)(pImage->data), pImage->width, pImage->height, pImage->bytes_per_line, QImage::Format_RGB32); pixmap = QPixmap::fromImage(image); XDestroyImage(pImage); XFreePixmap(display_, src_pixmap); }
看一下实际效果:
可以看出,虽然终端遮挡住了文件夹,但是获取到的图像仍然是完整的图像。