/* Copyright (C) 2003 Jamey Sharp. * This file is licensed under the MIT license. See the file COPYING. */ #include "Xlibint.h" #include "xclint.h" #include #include #include void _XFreeDisplayStructure(Display *dpy); static XCBAuthInfo xauth; static void *alloc_copy(const void *src, size_t *dstn, size_t n) { void *dst; if(n <= 0) { *dstn = 0; return 0; } dst = Xmalloc(n); if(!dst) return 0; memcpy(dst, src, n); *dstn = n; return dst; } XCBConnection *XCBConnectionOfDisplay(Display *dpy) { return dpy->xcl->connection; } void XSetAuthorization(char *name, int namelen, char *data, int datalen) { _XLockMutex(_Xglobal_lock); Xfree(xauth.name); Xfree(xauth.data); /* if either of these allocs fail, _XConnectXCB won't use this auth * data, so we don't need to check it here. */ xauth.name = alloc_copy(name, &xauth.namelen, namelen); xauth.data = alloc_copy(data, &xauth.datalen, datalen); #if 0 /* but, for the paranoid among us: */ if((namelen > 0 && !xauth.name) || (datalen > 0 && !xauth.data)) { Xfree(xauth.name); Xfree(xauth.data); xauth.name = xauth.data = 0; xauth.namelen = xauth.datalen = 0; } #endif _XUnlockMutex(_Xglobal_lock); } int _XConnectXCB(Display *dpy, _Xconst char *display, char **fullnamep, int *screenp) { char *host; int n = 0; int len; XCBConnection *c; dpy->fd = -1; dpy->xcl = Xcalloc(1, sizeof(XCLPrivate)); if(!dpy->xcl) return 0; if(!XCBParseDisplay(display, &host, &n, screenp)) return 0; len = strlen(host) + (1 + 20 + 1 + 20 + 1); *fullnamep = Xmalloc(len); snprintf(*fullnamep, len, "%s:%d.%d", host, n, *screenp); free(host); _XLockMutex(_Xglobal_lock); if(xauth.name && xauth.data) c = XCBConnectToDisplayWithAuthInfo(display, &xauth, 0); else c = XCBConnect(display, 0); _XUnlockMutex(_Xglobal_lock); if(!c) return 0; dpy->fd = XCBGetFileDescriptor(c); dpy->xcl->connection = c; dpy->xcl->pending_requests_tail = &dpy->xcl->pending_requests; return 1; } static int init_pixmap_formats(Display *dpy, XCBConnection *c) { int i; ScreenFormat *fmtdst; XCBFORMAT *fmtsrc; dpy->nformats = XCBConnSetupSuccessRepPixmapFormatsLength(XCBGetSetup(c)); /* Now iterate down setup information... */ fmtdst = Xmalloc(dpy->nformats * sizeof(ScreenFormat)); if(!fmtdst) return 0; dpy->pixmap_format = fmtdst; fmtsrc = XCBConnSetupSuccessRepPixmapFormats(XCBGetSetup(c)); /* First decode the Z axis Screen format information. */ for(i = dpy->nformats; i; --i, ++fmtsrc, ++fmtdst) { fmtdst->depth = fmtsrc->depth; fmtdst->bits_per_pixel = fmtsrc->bits_per_pixel; fmtdst->scanline_pad = fmtsrc->scanline_pad; fmtdst->ext_data = NULL; } return 1; } static int init_visuals(int len, XCBVISUALTYPE *vpsrc, Visual **dst) { Visual *vpdst; *dst = vpdst = Xmalloc(len * sizeof(Visual)); if(!vpdst) return 0; for(; len; --len, ++vpsrc, ++vpdst) { vpdst->visualid = vpsrc->visual_id.id; vpdst->class = vpsrc->_class; vpdst->bits_per_rgb = vpsrc->bits_per_rgb_value; vpdst->map_entries = vpsrc->colormap_entries; vpdst->red_mask = vpsrc->red_mask; vpdst->green_mask = vpsrc->green_mask; vpdst->blue_mask = vpsrc->blue_mask; vpdst->ext_data = NULL; } return 1; } static int init_depths(XCBDEPTHIter dpsrc, Depth **dst, CARD8 root_depth) { Depth *dpdst; *dst = dpdst = Xmalloc(dpsrc.rem * sizeof(Depth)); if(!dpdst) return 0; /* for all depths on this screen. */ for(; dpsrc.rem; XCBDEPTHNext(&dpsrc), ++dpdst) { dpdst->depth = dpsrc.data->depth; if (dpsrc.data->depth != root_depth && getenv ("XLIB_SKIP_EXTRA_VISUALS")) { dpdst->nvisuals = 0; dpdst->visuals = 0; } else { dpdst->nvisuals = XCBDEPTHVisualsLength(dpsrc.data); if(!init_visuals(dpdst->nvisuals, XCBDEPTHVisuals(dpsrc.data), &dpdst->visuals)) return 0; } } return 1; } static int init_screens(Display *dpy, XCBConnection *c) { Screen *spdst; XCBSCREENIter spsrc = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(c)); dpy->nscreens = spsrc.rem; spdst = Xmalloc(spsrc.rem * sizeof(Screen)); if(!spdst) return 0; dpy->screens = spdst; /* Now go deal with each screen structure. */ for(; spsrc.rem; XCBSCREENNext(&spsrc), ++spdst) { spdst->display = dpy; spdst->root = spsrc.data->root.xid; spdst->cmap = spsrc.data->default_colormap.xid; spdst->white_pixel = spsrc.data->white_pixel; spdst->black_pixel = spsrc.data->black_pixel; spdst->root_input_mask = spsrc.data->current_input_masks; spdst->width = spsrc.data->width_in_pixels; spdst->height = spsrc.data->height_in_pixels; spdst->mwidth = spsrc.data->width_in_millimeters; spdst->mheight = spsrc.data->height_in_millimeters; spdst->min_maps = spsrc.data->min_installed_maps; spdst->max_maps = spsrc.data->max_installed_maps; spdst->backing_store = spsrc.data->backing_stores; spdst->save_unders = spsrc.data->save_unders; spdst->root_depth = spsrc.data->root_depth; spdst->ndepths = spsrc.data->allowed_depths_len; spdst->ext_data = NULL; if(!init_depths(XCBSCREENAllowedDepthsIter(spsrc.data), &spdst->depths, spsrc.data->root_depth)) return 0; spdst->root_visual = _XVIDtoVisual(dpy, spsrc.data->root_visual.id); } return 1; } int _XConnectSetupXCB(Display *dpy) { XCBConnection *c = dpy->xcl->connection; XCBConnSetupSuccessRep *setup = XCBGetSetup(c); dpy->proto_major_version = setup->protocol_major_version; dpy->proto_minor_version = setup->protocol_minor_version; dpy->release = setup->release_number; dpy->resource_base = setup->resource_id_base; dpy->resource_mask = setup->resource_id_mask; dpy->min_keycode = setup->min_keycode.id; dpy->max_keycode = setup->max_keycode.id; dpy->motion_buffer = setup->motion_buffer_size; dpy->byte_order = setup->image_byte_order; dpy->bitmap_unit = setup->bitmap_format_scanline_unit; dpy->bitmap_pad = setup->bitmap_format_scanline_pad; dpy->bitmap_bit_order = setup->bitmap_format_bit_order; dpy->max_request_size = setup->maximum_request_length; dpy->resource_shift = 0; { unsigned long mask; for (mask = dpy->resource_mask; !(mask & 1); mask >>= 1) ++dpy->resource_shift; } dpy->resource_max = (dpy->resource_mask >> dpy->resource_shift) - 5; { int len = XCBConnSetupSuccessRepVendorLength(setup); dpy->vendor = Xmalloc(len + 1); if(!dpy->vendor) return 0; memcpy(dpy->vendor, XCBConnSetupSuccessRepVendor(setup), len); dpy->vendor[len] = '\0'; } if(!init_pixmap_formats(dpy, c)) return 0; if(!init_screens(dpy, c)) return 0; dpy->bigreq_size = XCBGetMaximumRequestLength(c); if(dpy->bigreq_size <= dpy->max_request_size) dpy->bigreq_size = 0; return 1; }