• X11 Xlib截屏问题及深入分析四 —— XOpenDisplay函数源码分析(1)


    XOpenDisplay函数对应的源码在src/OpenDis.c中。完整源码请参见:

    X11 Xlib截屏问题及深入分析二 —— 源码实现1_蓝天居士的博客-CSDN博客

    XOpenDisplay函数很长,有500行左右。在此为了便于分析,列出函数名和前边变量定义的部分。代码如下:

    1. /*
    2. * Connects to a server, creates a Display object and returns a pointer to
    3. * the newly created Display back to the caller.
    4. */
    5. Display *
    6. XOpenDisplay (
    7. register _Xconst char *display)
    8. {
    9. register Display *dpy; /* New Display object being created. */
    10. register int i;
    11. int j, k; /* random iterator indexes */
    12. char *display_name; /* pointer to display name */
    13. char *setup = NULL; /* memory allocated at startup */
    14. int iscreen; /* screen number */
    15. xConnSetupPrefix prefix; /* prefix information */
    16. int vendorlen; /* length of vendor string */
    17. union {
    18. xConnSetup *setup;
    19. char *failure;
    20. char *vendor;
    21. xPixmapFormat *sf;
    22. xWindowRoot *rp;
    23. xDepth *dp;
    24. xVisualType *vp;
    25. } u; /* proto data returned from server */
    26. long setuplength; /* number of bytes in setup message */
    27. long usedbytes = 0; /* number of bytes we have processed */
    28. unsigned long mask;
    29. long int conn_buf_size;
    30. char *xlib_buffer_size;
    31. ……
    32. }

    余下的代码分块来进行分析。

    第1部分代码

    1. /*
    2. * If the display specifier string supplied as an argument to this
    3. * routine is NULL or a pointer to NULL, read the DISPLAY variable.
    4. */
    5. if (display == NULL || *display == '\0') {
    6. if ((display_name = getenv("DISPLAY")) == NULL) {
    7. /* Oops! No DISPLAY environment variable - error. */
    8. return(NULL);
    9. }
    10. }
    11. else {
    12. /* Display is non-NULL, copy the pointer */
    13. display_name = (char *)display;
    14. }

    如果XOpenDisplay函数的输入参数display为空或者字符串结束符,则默认从环境变量中获取对应的值,赋给char *display_name;否则直接将display赋值给display_name。笔者环境变量DISPLAY对应的值为:

    1. $ echo $DISPLAY
    2. :0

    在例程(同样参见《X11 Xlib截屏问题及深入分析二》)中是如此调用的XOpenDisplay:

    Display *display = XOpenDisplay(NULL);

    综上,最终得到display_name的值为":0"。

    第2部分代码

    1. /*
    2. * Set the default error handlers. This allows the global variables to
    3. * default to NULL for use with shared libraries.
    4. */
    5. if (_XErrorFunction == NULL) (void) XSetErrorHandler (NULL);
    6. if (_XIOErrorFunction == NULL) (void) XSetIOErrorHandler (NULL);

    这部分代码比较好理解,设置默认的错误处理函数和IO错误处理函数。

    _XErrorFunction和_XIOErrorFunction是函数指针,在include/X11/Xlibint.h中定义:

    1. extern int (*_XIOErrorFunction)(
    2. Display* /* dpy */
    3. );
    4. extern int (*_XErrorFunction)(
    5. Display* /* dpy */,
    6. XErrorEvent* /* error_event */
    7. );

    第3部分代码

    1. /*
    2. * Attempt to allocate a display structure. Return NULL if allocation fails.
    3. */
    4. if ((dpy = Xcalloc(1, sizeof(Display))) == NULL) {
    5. return(NULL);
    6. }
    7. if ((dpy->display_name = strdup(display_name)) == NULL) {
    8. OutOfMemory(dpy);
    9. return(NULL);
    10. }

    这段代码也好理解,动态分配Display对象,赋给register Display *dpy;并且将dpy->display_name的值赋为":0"。

    Display结构的定义在include/X11/Xlib.h中:

    1. /*
    2. * Display datatype maintaining display specific data.
    3. * The contents of this structure are implementation dependent.
    4. * A Display should be treated as opaque by application code.
    5. */
    6. #ifndef XLIB_ILLEGAL_ACCESS
    7. typedef struct _XDisplay Display;
    8. #endif
    9. struct _XPrivate; /* Forward declare before use for C++ */
    10. struct _XrmHashBucketRec;
    11. typedef struct
    12. #ifdef XLIB_ILLEGAL_ACCESS
    13. _XDisplay
    14. #endif
    15. {
    16. XExtData *ext_data; /* hook for extension to hang data */
    17. struct _XPrivate *private1;
    18. int fd; /* Network socket. */
    19. int private2;
    20. int proto_major_version;/* major version of server's X protocol */
    21. int proto_minor_version;/* minor version of servers X protocol */
    22. char *vendor; /* vendor of the server hardware */
    23. XID private3;
    24. XID private4;
    25. XID private5;
    26. int private6;
    27. XID (*resource_alloc)( /* allocator function */
    28. struct _XDisplay*
    29. );
    30. int byte_order; /* screen byte order, LSBFirst, MSBFirst */
    31. int bitmap_unit; /* padding and data requirements */
    32. int bitmap_pad; /* padding requirements on bitmaps */
    33. int bitmap_bit_order; /* LeastSignificant or MostSignificant */
    34. int nformats; /* number of pixmap formats in list */
    35. ScreenFormat *pixmap_format; /* pixmap format list */
    36. int private8;
    37. int release; /* release of the server */
    38. struct _XPrivate *private9, *private10;
    39. int qlen; /* Length of input event queue */
    40. unsigned long last_request_read; /* seq number of last event read */
    41. unsigned long request; /* sequence number of last request. */
    42. XPointer private11;
    43. XPointer private12;
    44. XPointer private13;
    45. XPointer private14;
    46. unsigned max_request_size; /* maximum number 32 bit words in request*/
    47. struct _XrmHashBucketRec *db;
    48. int (*private15)(
    49. struct _XDisplay*
    50. );
    51. char *display_name; /* "host:display" string used on this connect*/
    52. int default_screen; /* default screen for operations */
    53. int nscreens; /* number of screens on this server*/
    54. Screen *screens; /* pointer to list of screens */
    55. unsigned long motion_buffer; /* size of motion buffer */
    56. unsigned long private16;
    57. int min_keycode; /* minimum defined keycode */
    58. int max_keycode; /* maximum defined keycode */
    59. XPointer private17;
    60. XPointer private18;
    61. int private19;
    62. char *xdefaults; /* contents of defaults from server */
    63. /* there is more to this structure, but it is private to Xlib */
    64. }

    Display结构中有很多成员,后边用到哪个的时候再针对于哪个进行详细说明。

    为了便于理解,本文对于XOpenDisplay函数就分析到第3部分代码,接来下的文章继续分析其余部分。

  • 相关阅读:
    组合模式
    Git命令大全
    SP34009 CTTC - Counting Child
    Fiddle日常运用手册(2)-使用过滤器进行接口精准拦截
    Vue编程式路由导航
    机器人微控制器编程(CoCube)-深度融合
    虚拟机里为什么桥接模式可以广播,NAT模式不能广播?
    企业年会直播来个虚拟舞台场景如何?
    早在多久MySQL 啥时候用表锁,啥时候用行锁?
    【docker专栏7】容器自启动与守护进程停止后容器保活
  • 原文地址:https://blog.csdn.net/phmatthaus/article/details/127963182