X11 Xlib截屏问题及深入分析二 —— 源码实现1
接上一篇文章《X11 Xlib截屏问题及深入分析一 —— 源码位置》,链接为:
X11 Xlib截屏问题及深入分析一 —— 源码位置_蓝天居士的博客-CSDN博客
上一篇文章讲到了源码包的内容,本文看一下几个接口函数对应的位置。再次列出应用源码:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>int main(int argc, char *argv[])
{Display *display = XOpenDisplay(NULL);if(!display){printf("XOpenDisplay failed\n");return -1;}int screen_num = DefaultScreen(display);printf("default screen_num is: %d\n", screen_num);int screen_width = DisplayWidth(display, screen_num);int screen_height = DisplayHeight(display, screen_num);printf("screen_width: %d, screen_height: %d\n", screen_width, screen_height);Window root_win = RootWindow(display, screen_num);if(!root_win){printf("can not get root window\n");return -1;}Window disp_win = XCreateSimpleWindow(display, root_win, 0, 0, screen_width, screen_height, 1, 0, 0) ;if(!disp_win){printf("can not get snapshot display window\n");return -1;}XMapWindow(display, disp_win);XImage *img = XGetImage(display, root_win, 0, 0, screen_width, screen_height, ~0, ZPixmap); XPutImage(display, disp_win, DefaultGC(display, screen_num), img, 0, 0, 0, 0, screen_width, screen_height);char c = getchar();//XDestroyImage(img);XCloseDisplay(display);printf("screen_snapshot finished\n");return 0;
}
由以上代码可以看到,总共调用了几个接口函数:
- XOpenDisplay
- XCloseDisplay
- XCreateSimpleWindow
- XMapWindow
- XGetImage
- XPutImage
下边分别列出各个接口函数对应源码。
- XOpenDisplay源码
XOpenDisplay函数对应的源码在src/OpenDis.c中。如下所示:
/** Connects to a server, creates a Display object and returns a pointer to* the newly created Display back to the caller.*/
Display *
XOpenDisplay (register _Xconst char *display)
{register Display *dpy; /* New Display object being created. */register int i;int j, k; /* random iterator indexes */char *display_name; /* pointer to display name */char *setup = NULL; /* memory allocated at startup */int iscreen; /* screen number */xConnSetupPrefix prefix; /* prefix information */int vendorlen; /* length of vendor string */union {xConnSetup *setup;char *failure;char *vendor;xPixmapFormat *sf;xWindowRoot *rp;xDepth *dp;xVisualType *vp;} u; /* proto data returned from server */long setuplength; /* number of bytes in setup message */long usedbytes = 0; /* number of bytes we have processed */unsigned long mask;long int conn_buf_size;char *xlib_buffer_size;/** If the display specifier string supplied as an argument to this* routine is NULL or a pointer to NULL, read the DISPLAY variable.*/if (display == NULL || *display == '\0') {if ((display_name = getenv("DISPLAY")) == NULL) {/* Oops! No DISPLAY environment variable - error. */return(NULL);}}else {/* Display is non-NULL, copy the pointer */display_name = (char *)display;}/** Set the default error handlers. This allows the global variables to* default to NULL for use with shared libraries.*/if (_XErrorFunction == NULL) (void) XSetErrorHandler (NULL);if (_XIOErrorFunction == NULL) (void) XSetIOErrorHandler (NULL);/** Attempt to allocate a display structure. Return NULL if allocation fails.*/if ((dpy = Xcalloc(1, sizeof(Display))) == NULL) {return(NULL);}if ((dpy->display_name = strdup(display_name)) == NULL) {OutOfMemory(dpy);return(NULL);}/** Call the Connect routine to get the transport connection object.* If NULL is returned, the connection failed.*/if(!_XConnectXCB(dpy, display, &iscreen)) {OutOfMemory(dpy);return NULL;}/* Initialize as much of the display structure as we can.* Initialize pointers to NULL so that XFreeDisplayStructure will* work if we run out of memory before we finish initializing.*/dpy->keysyms = (KeySym *) NULL;dpy->modifiermap = NULL;dpy->lock_meaning = NoSymbol;dpy->keysyms_per_keycode = 0;dpy->xdefaults = (char *)NULL;dpy->scratch_length = 0L;dpy->scratch_buffer = NULL;dpy->key_bindings = NULL;dpy->ext_procs = (_XExtension *)NULL;dpy->ext_data = (XExtData *)NULL;dpy->ext_number = 0;dpy->event_vec[X_Error] = _XUnknownWireEvent;dpy->event_vec[X_Reply] = _XUnknownWireEvent;dpy->wire_vec[X_Error] = _XUnknownNativeEvent;dpy->wire_vec[X_Reply] = _XUnknownNativeEvent;for (i = KeyPress; i < LASTEvent; i++) {dpy->event_vec[i] = _XWireToEvent;dpy->wire_vec[i] = NULL;}for (i = LASTEvent; i < 128; i++) {dpy->event_vec[i] = _XUnknownWireEvent;dpy->wire_vec[i] = _XUnknownNativeEvent;}dpy->resource_id = 0;dpy->db = (struct _XrmHashBucketRec *)NULL;dpy->cursor_font = None;dpy->flags = 0;dpy->async_handlers = NULL;dpy->screens = NULL;dpy->vendor = NULL;dpy->buffer = NULL;dpy->atoms = NULL;dpy->error_vec = NULL;dpy->context_db = NULL;dpy->free_funcs = NULL;dpy->pixmap_format = NULL;dpy->cms.clientCmaps = NULL;dpy->cms.defaultCCCs = NULL;dpy->cms.perVisualIntensityMaps = NULL;dpy->im_filters = NULL;dpy->bigreq_size = 0;dpy->lock = NULL;dpy->lock_fns = NULL;dpy->qfree = NULL;dpy->next_event_serial_num = 1;dpy->im_fd_info = NULL;dpy->im_fd_length = 0;dpy->conn_watchers = NULL;dpy->watcher_count = 0;dpy->filedes = NULL;dpy->flushes = NULL;dpy->xcmisc_opcode = 0;dpy->xkb_info = NULL;dpy->exit_handler_data = NULL;/** Setup other information in this display structure.*/dpy->vnumber = X_PROTOCOL;dpy->resource_alloc = _XAllocID;dpy->idlist_alloc = _XAllocIDs;dpy->synchandler = NULL;dpy->savedsynchandler = NULL;X_DPY_SET_REQUEST(dpy, 0);X_DPY_SET_LAST_REQUEST_READ(dpy, 0);dpy->default_screen = iscreen; /* Value returned by ConnectDisplay */dpy->last_req = (char *)&_dummy_request;dpy->error_threads = NULL;dpy->exit_handler = _XDefaultIOErrorExit;/* Initialize the display lock */if (InitDisplayLock(dpy) != 0) {OutOfMemory (dpy);return(NULL);}if (!_XPollfdCacheInit(dpy)) {OutOfMemory (dpy);return(NULL);}/* Set up the output buffers. */
#ifndef XLIBDEFAULTBUFSIZE
#define XLIBDEFAULTBUFSIZE 16384 /* 16k */
#endif
#ifndef XLIBMINBUFSIZE
#define XLIBMINBUFSIZE BUFSIZE /* old default buffer size */
#endifxlib_buffer_size = getenv("XLIBBUFFERSIZE");#ifdef __sun /* Backwards compatibility for old Solaris libX11 name */if (xlib_buffer_size == NULL)xlib_buffer_size = getenv("XSUNBUFFERSIZE");
#endifif (xlib_buffer_size == NULL)conn_buf_size = XLIBDEFAULTBUFSIZE;elseconn_buf_size = 1024 * strtol(xlib_buffer_size, NULL, 10);if (conn_buf_size < XLIBMINBUFSIZE)conn_buf_size = XLIBMINBUFSIZE;if ((dpy->bufptr = dpy->buffer = Xcalloc(1, conn_buf_size)) == NULL) {OutOfMemory (dpy);return(NULL);}dpy->xcb->real_bufmax = dpy->buffer + conn_buf_size;dpy->bufmax = dpy->buffer;/* Set up the input event queue and input event queue parameters. */dpy->head = dpy->tail = NULL;dpy->qlen = 0;/* Set up free-function record */if ((dpy->free_funcs = Xcalloc(1, sizeof(_XFreeFuncRec))) == NULL) {OutOfMemory (dpy);return(NULL);}{const struct xcb_setup_t *xcbsetup = xcb_get_setup(dpy->xcb->connection);memcpy(&prefix, xcbsetup, sizeof(prefix));setuplength = prefix.length << 2;setup = (char *) xcbsetup;setup += SIZEOF(xConnSetupPrefix);u.setup = (xConnSetup *) setup;}/** Check if the reply was long enough to get any information out of it.*/usedbytes = sz_xConnSetup;if (setuplength < usedbytes ) {fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);OutOfMemory(dpy);return (NULL);}/** We succeeded at authorization, so let us move the data into* the display structure.*/dpy->proto_major_version= prefix.majorVersion;dpy->proto_minor_version= prefix.minorVersion;dpy->release = u.setup->release;dpy->resource_base = u.setup->ridBase;dpy->resource_mask = u.setup->ridMask;dpy->min_keycode = u.setup->minKeyCode;dpy->max_keycode = u.setup->maxKeyCode;dpy->motion_buffer = u.setup->motionBufferSize;dpy->nformats = u.setup->numFormats;dpy->nscreens = u.setup->numRoots;dpy->byte_order = u.setup->imageByteOrder;dpy->bitmap_unit = u.setup->bitmapScanlineUnit;dpy->bitmap_pad = u.setup->bitmapScanlinePad;dpy->bitmap_bit_order = u.setup->bitmapBitOrder;dpy->max_request_size = u.setup->maxRequestSize;mask = dpy->resource_mask;dpy->resource_shift = 0;if (!mask){fprintf (stderr, "Xlib: connection to \"%s\" invalid setup\n",dpy->display_name);OutOfMemory(dpy);return (NULL);}while (!(mask & 1)) {dpy->resource_shift++;mask = mask >> 1;}dpy->resource_max = (dpy->resource_mask >> dpy->resource_shift) - 5;
/** now extract the vendor string... String must be null terminated,* padded to multiple of 4 bytes.*//* Check for a sane vendor string length */if (u.setup->nbytesVendor > 256) {OutOfMemory(dpy);return (NULL);}dpy->vendor = Xmalloc(u.setup->nbytesVendor + 1);if (dpy->vendor == NULL) {OutOfMemory(dpy);return (NULL);}vendorlen = u.setup->nbytesVendor;/** validate setup length*/usedbytes += (vendorlen + 3) & ~3;if (setuplength < usedbytes) {fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);OutOfMemory(dpy);return (NULL);}u.setup = (xConnSetup *) (((char *) u.setup) + sz_xConnSetup);(void) strncpy(dpy->vendor, u.vendor, (size_t) vendorlen);dpy->vendor[vendorlen] = '\0';vendorlen = (vendorlen + 3) & ~3; /* round up */u.vendor += vendorlen;/** Now iterate down setup information.....*/dpy->pixmap_format = Xcalloc(dpy->nformats, sizeof(ScreenFormat));if (dpy->pixmap_format == NULL) {OutOfMemory (dpy);return(NULL);}
/** First decode the Z axis Screen format information.*/usedbytes += dpy->nformats * sz_xPixmapFormat;if (setuplength < usedbytes) {fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);OutOfMemory (dpy);return(NULL);}for (i = 0; i < dpy->nformats; i++) {register ScreenFormat *fmt = &dpy->pixmap_format[i];fmt->depth = u.sf->depth;fmt->bits_per_pixel = u.sf->bitsPerPixel;fmt->scanline_pad = u.sf->scanLinePad;fmt->ext_data = NULL;u.sf = (xPixmapFormat *) (((char *) u.sf) + sz_xPixmapFormat);}/** next the Screen structures.*/dpy->screens = Xcalloc(dpy->nscreens, sizeof(Screen));if (dpy->screens == NULL) {OutOfMemory (dpy);return(NULL);}/** Now go deal with each screen structure.*/for (i = 0; i < dpy->nscreens; i++) {register Screen *sp = &dpy->screens[i];VisualID root_visualID;usedbytes += sz_xWindowRoot;if (setuplength < usedbytes) {fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);OutOfMemory (dpy);return(NULL);}root_visualID = u.rp->rootVisualID;sp->display = dpy;sp->root = u.rp->windowId;sp->cmap = u.rp->defaultColormap;sp->white_pixel = u.rp->whitePixel;sp->black_pixel = u.rp->blackPixel;sp->root_input_mask = u.rp->currentInputMask;sp->width = u.rp->pixWidth;sp->height = u.rp->pixHeight;sp->mwidth = u.rp->mmWidth;sp->mheight = u.rp->mmHeight;sp->min_maps = u.rp->minInstalledMaps;sp->max_maps = u.rp->maxInstalledMaps;sp->backing_store= u.rp->backingStore;sp->save_unders = u.rp->saveUnders;sp->root_depth = u.rp->rootDepth;sp->ndepths = u.rp->nDepths;sp->ext_data = NULL;u.rp = (xWindowRoot *) (((char *) u.rp) + sz_xWindowRoot);
/** lets set up the depth structures.*/sp->depths = Xcalloc(sp->ndepths, sizeof(Depth));if (sp->depths == NULL) {OutOfMemory (dpy);return(NULL);}/** for all depths on this screen.*/for (j = 0; j < sp->ndepths; j++) {Depth *dp = &sp->depths[j];usedbytes += sz_xDepth;if (setuplength < usedbytes) {fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);OutOfMemory (dpy);return(NULL);}dp->depth = u.dp->depth;dp->nvisuals = u.dp->nVisuals;u.dp = (xDepth *) (((char *) u.dp) + sz_xDepth);if (dp->nvisuals > 0) {dp->visuals = Xcalloc(dp->nvisuals, sizeof(Visual));if (dp->visuals == NULL) {OutOfMemory (dpy);return(NULL);}for (k = 0; k < dp->nvisuals; k++) {register Visual *vp = &dp->visuals[k];usedbytes += sz_xVisualType;if (setuplength < usedbytes) {fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);OutOfMemory (dpy);return(NULL);}vp->visualid = u.vp->visualID;vp->class = u.vp->class;vp->bits_per_rgb= u.vp->bitsPerRGB;vp->map_entries = u.vp->colormapEntries;vp->red_mask = u.vp->redMask;vp->green_mask = u.vp->greenMask;vp->blue_mask = u.vp->blueMask;vp->ext_data = NULL;u.vp = (xVisualType *) (((char *) u.vp) +sz_xVisualType);}if (dp->depth == 32 && getenv ("XLIB_SKIP_ARGB_VISUALS")){Xfree (dp->visuals);dp->visuals = NULL;dp->nvisuals = 0;}} else {dp->visuals = (Visual *) NULL;}}sp->root_visual = _XVIDtoVisual(dpy, root_visualID);}if(usedbytes != setuplength){/* Sanity check, shouldn't happen. */fprintf(stderr, "Xlib: Did not parse entire setup message: ""parsed: %ld, message: %ld\n",usedbytes, setuplength);OutOfMemory(dpy);return(NULL);}/** Now start talking to the server to setup all other information...*//** Make sure default screen is legal.*/if (iscreen >= dpy->nscreens) {OutOfMemory(dpy);return(NULL);}/** get availability of large requests*/dpy->bigreq_size = xcb_get_maximum_request_length(dpy->xcb->connection);if(dpy->bigreq_size <= dpy->max_request_size)dpy->bigreq_size = 0;/** Set up other stuff clients are always going to use.*/for (i = 0; i < dpy->nscreens; i++) {register Screen *sp = &dpy->screens[i];XGCValues values;values.foreground = sp->black_pixel;values.background = sp->white_pixel;if ((sp->default_gc = XCreateGC (dpy, sp->root,GCForeground|GCBackground,&values)) == NULL) {OutOfMemory(dpy);return (NULL);}}
/** call into synchronization routine so that all programs can be* forced synchronous*/(void) XSynchronize(dpy, _Xdebug);/** get the resource manager database off the root window.*/LockDisplay(dpy);{xGetPropertyReply reply;xGetPropertyReq *req;GetReq (GetProperty, req);req->window = RootWindow(dpy, 0);req->property = XA_RESOURCE_MANAGER;req->type = XA_STRING;req->delete = False;req->longOffset = 0;req->longLength = 100000000L;if (_XReply (dpy, (xReply *) &reply, 0, xFalse)) {if (reply.format == 8 && reply.propertyType == XA_STRING &&(reply.nItems + 1 > 0) &&(reply.nItems <= req->longLength * 4) &&(dpy->xdefaults = Xmalloc (reply.nItems + 1))) {_XReadPad (dpy, dpy->xdefaults, reply.nItems);dpy->xdefaults[reply.nItems] = '\0';}else if (reply.propertyType != None)_XEatDataWords(dpy, reply.length);}}UnlockDisplay(dpy);#ifdef MOTIFBC{extern Display *_XHeadOfDisplayList;_XHeadOfDisplayList = dpy;}
#endif
#ifdef XKBXkbUseExtension(dpy,NULL,NULL);
#endif
/** and return successfully*/return(dpy);
}
- XCloseDisplay源码
XCloseDisplay函数对应的源码在src/ClDisplay.c中。如下所示:
/** XCloseDisplay - XSync the connection to the X Server, close the connection,* and free all associated storage. Extension close procs should only free* memory and must be careful about the types of requests they generate.*/int
XCloseDisplay (register Display *dpy)
{register _XExtension *ext;register int i;if (!(dpy->flags & XlibDisplayClosing)){dpy->flags |= XlibDisplayClosing;for (i = 0; i < dpy->nscreens; i++) {register Screen *sp = &dpy->screens[i];XFreeGC (dpy, sp->default_gc);}if (dpy->cursor_font != None) {XUnloadFont (dpy, dpy->cursor_font);}XSync(dpy, 1); /* throw away pending events, catch errors *//* call out to any extensions interested */for (ext = dpy->ext_procs; ext; ext = ext->next) {if (ext->close_display)(*ext->close_display)(dpy, &ext->codes);}/* if the closes generated more protocol, sync them up */if (X_DPY_GET_REQUEST(dpy) != X_DPY_GET_LAST_REQUEST_READ(dpy))XSync(dpy, 1);}xcb_disconnect(dpy->xcb->connection);_XFreeDisplayStructure (dpy);return 0;
}
由于源码已经比较长了,为了方便理解和阅读,把余下的函数放到下一篇中。
X11 Xlib截屏问题及深入分析二 —— 源码实现1相关推荐
- Spectacle/Flameshot/X11 Xlib截屏问题现象及解决方法
最近一个时期可以看到我的博客文章都是围绕系统截屏展开的,从Spectale到FlameShot再到X11/Xlib,及至最近的libX11,都是在设法找到工作中遇到的一个比较严重的Bug的根源--截屏 ...
- X11 Xlib截屏代码所遇问题及初步分析
综合了两篇博客中的例程并做一定修改,得到了基于X11 Xlib的截屏代码. 两篇博客链接分别如下: X11 截图与鼠标事件-SkyMei777-ChinaUnix博客 xlib实现截图报错-编程语言- ...
- 深入分析Ribbon源码分析
本文来分析下Ribbon源码 文章目录 Ribbon源码分析 负载均衡器 AbstractLoadBalancer BaseLoadBalancer DynamicServerListLoadBala ...
- 录屏工具Gif软件 附带源码
录制完可以快速一键复制录好的 GIF 文件添加图片.很多软件复制的 GIF 有兼容性问题,例如到浏览器编辑器粘贴,或在 QQ 里粘贴 --会出现无效像,动画变静态图像,上传报错等问题.Gif123 复 ...
- qcustomplot圆_QCustomplot使用分享(二) 源码解读
一.头文件概述 从这篇文章开始,我们将正式的进入到QCustomPlot的实践学习中来,首先我们先来学习下QCustomPlot的类图,如果下载了QCustomPlot源码的同学可以自己去QCusto ...
- QCustomplot(二) 源码解读
阅读目录 一.头文件概述 二.一个简单的示例 三.示例下载 四.相关文章 回到顶部 一.头文件概述 从这篇文章开始,我们将正式的进入到QCustomPlot的实践学习中来,首先我们先来学习下QCust ...
- Java毕设项目智慧公寓系统演示录屏2021计算机(附源码+系统+数据库+LW)
Java毕设项目智慧公寓系统演示录屏2021计算机(附源码+系统+数据库+LW) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也 ...
- IOS手机全屏长按识别二维码HTML代码
代码段作用讲解: 1. 二维码的全屏样式, opacity: 0; 透明样式, touch-callout: none; -webkit-touch-callout: none; -ms-touch- ...
- 海康威视道闸进出口LED屏DS-TVL224系列开发C#源码
1.类库源码: using System; using System.Collections.Generic; using System.Drawing; using System.Linq; usi ...
最新文章
- TCP连接的建立和终止
- 如何设计一个好的数据结构?
- 第十期 华为拓扑-OSPF配置
- 将Windows 8.1 系统窗口背景设置成淡绿色?
- HDU - 2825 Wireless Password(AC自动机+状压dp)
- 在没有XML的情况下测试Spring和Hibernate
- 利用scipy包计算表格线的峰值,还原表格得到表格结构
- SpringAop通知
- Android第五十二期 - 云之讯的代码混淆
- 不能注册DLL/OCX:RegSvr32失败 0x5
- DTCC参会归来有感
- C# 死循环等待方式
- 编写java判断闰年_Java 判断闰年代码实例
- 严昊:25岁接手世界500强企业,公司一年净赚80亿
- 25. Green Living 绿色生活
- 软件工程与计算机科学的区别
- 有软件负载均衡,也有硬件负载均衡,选择哪个?
- threejs(webgl)-shader入门教程(1)
- Java基础之刨根问底第6集——集合与List
- 【优化求解】基于PESA—II实现多目标优化求解matlab源码
热门文章
- SQL Server 查看被锁的表
- fastadmin 子账号看不到菜单,菜单没有查看,编辑等选项
- Android圆盘控件,DiscView 圆盘控件 动态展示百分比等数据 @codeKK Android开源站
- 小米平板android版本,小米平板系统是什么?小米平板能升级安卓4.2吗?
- 视频点播RTMP推流直播流媒体服务二次开发集成接口
- 视频教程-Python数据分析与案例教程:分析人口普查数据-Python
- 面试时,没有谈薪资,叫回去等通知,还有机会吗
- 2面之后说等HR通知,等不到怎么办
- Hadoop 集群项目(类似百度网盘)
- 开发人员必知的5个CI/CD工具