1b3307321Smrg/** ------------------------------------------------------------------------ 2b3307321Smrg This file contains functions to create a list of regions which 374a3f230Smrg tile a specified window. Each region contains all visible 4b3307321Smrg portions of the window which are drawn with the same visual. 5b3307321Smrg If the window consists of subwindows of two different visual types, 6b3307321Smrg there will be two regions in the list. The list can be traversed 7b3307321Smrg to correctly pull an image of the window using XGetImage or the 8b3307321Smrg Image Library. 9b3307321Smrg 10b3307321SmrgCopyright 1994 Hewlett-Packard Co. 11b3307321SmrgCopyright 1996, 1998 The Open Group 12b3307321Smrg 13b3307321SmrgPermission to use, copy, modify, distribute, and sell this software and its 14b3307321Smrgdocumentation for any purpose is hereby granted without fee, provided that 15b3307321Smrgthe above copyright notice appear in all copies and that both that 16b3307321Smrgcopyright notice and this permission notice appear in supporting 17b3307321Smrgdocumentation. 18b3307321Smrg 19b3307321SmrgThe above copyright notice and this permission notice shall be included 20b3307321Smrgin all copies or substantial portions of the Software. 21b3307321Smrg 22b3307321SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23b3307321SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24b3307321SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25b3307321SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 26b3307321SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27b3307321SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28b3307321SmrgOTHER DEALINGS IN THE SOFTWARE. 29b3307321Smrg 30b3307321SmrgExcept as contained in this notice, the name of The Open Group shall 31b3307321Smrgnot be used in advertising or otherwise to promote the sale, use or 32b3307321Smrgother dealings in this Software without prior written authorization 33b3307321Smrgfrom The Open Group. 34b3307321Smrg 35b3307321Smrg ------------------------------------------------------------------------ **/ 36b3307321Smrg 3774b97a6cSmrg#include <stdio.h> 38b3307321Smrg#include <stdlib.h> 3974b97a6cSmrg#include <string.h> 40b3307321Smrg#include <X11/Xlib.h> 41b3307321Smrg#include <X11/Xutil.h> 42b3307321Smrg#include <X11/X.h> 43b3307321Smrg#include "list.h" 44b3307321Smrg#include "wsutils.h" 45b3307321Smrg#include "multiVis.h" 46b3307321Smrg/* These structures are copied from X11/region.h. For some reason 47b3307321Smrg * they're invisible from the outside. 48b3307321Smrg */ 49b3307321Smrgtypedef struct { 50b3307321Smrg short x1, x2, y1, y2; 51b3307321Smrg} myBox, myBOX, myBoxRec, *myBoxPtr; 52b3307321Smrg 53b3307321Smrgtypedef struct my_XRegion { 54b3307321Smrg long size; 55b3307321Smrg long numRects; 56b3307321Smrg myBOX *rects; 57b3307321Smrg myBOX extents; 58b3307321Smrg} myREGION; 59b3307321Smrg 60b3307321Smrg/* Items in long list of windows that have some part in the grabbed area */ 61b3307321Smrgtypedef struct { 62b3307321Smrg Window win; 63b3307321Smrg Visual *vis; 64b3307321Smrg Colormap cmap; 6574b97a6cSmrg int x_rootrel, y_rootrel; /* root relative location of window */ 6674b97a6cSmrg int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */ 6774b97a6cSmrg int width, height; /* width and height of visible part */ 6874b97a6cSmrg int border_width; /* border width of the window */ 6974b97a6cSmrg Window parent; /* id of parent (for debugging) */ 70b3307321Smrg} image_win_type; 71b3307321Smrg 7274a3f230Smrg/* Items in short list of regions that tile the grabbed area. May have 73b3307321Smrg multiple windows in the region. 74b3307321Smrg*/ 75b3307321Smrgtypedef struct { 7674b97a6cSmrg Window win; /* lowest window of this visual */ 77b3307321Smrg Visual *vis; 78b3307321Smrg Colormap cmap; 7974b97a6cSmrg int x_rootrel, y_rootrel; /* root relative location of bottom window */ 8074b97a6cSmrg int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */ 8174b97a6cSmrg int width, height; /* w & h of visible rect of bottom window */ 8274b97a6cSmrg int border; /* border width of the window */ 83b3307321Smrg Region visible_region; 84b3307321Smrg} image_region_type; 85b3307321Smrg 86b3307321Smrg/** ------------------------------------------------------------------------ 8774a3f230Smrg Returns TRUE if the two structs pointed to have the same "vis" & 88b3307321Smrg "cmap" fields and s2 lies completely within s1. s1 and s2 can 89b3307321Smrg point to structs of image_win_type or image_region_type. 90b3307321Smrg ------------------------------------------------------------------------ **/ 91b3307321Smrg#define SAME_REGIONS( s1, s2) \ 92b3307321Smrg ((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap && \ 93b3307321Smrg (s1)->x_vis <= (s2)->x_vis && \ 94b3307321Smrg (s1)->y_vis <= (s2)->y_vis && \ 95b3307321Smrg (s1)->x_vis + (s1)->width >= (s2)->x_vis + (s2)->width && \ 96b3307321Smrg (s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height) 97b3307321Smrg 98b3307321Smrg#ifndef MIN 99b3307321Smrg#define MIN( a, b) ((a) < (b) ? a : b) 100b3307321Smrg#define MAX( a, b) ((a) > (b) ? a : b) 101b3307321Smrg#endif 102b3307321Smrg 103b3307321Smrg#define RED_SHIFT 16 104b3307321Smrg#define GREEN_SHIFT 8 105b3307321Smrg#define BLUE_SHIFT 0 106b3307321Smrg 107b3307321Smrg/* Prototype Declarations for Static Functions */ 10874b97a6cSmrgstatic void QueryColorMap(Display *, Colormap, Visual *, 10974b97a6cSmrg XColor **, int *, int *, int *); 11074b97a6cSmrgstatic void TransferImage(Display *, XImage *, int, int, image_region_type *, 11174b97a6cSmrg XImage *, int, int); 11274b97a6cSmrgstatic XImage *ReadRegionsInList(Display *, Visual *, int, int, unsigned int, 11374b97a6cSmrg unsigned int, XRectangle, list_ptr); 11474b97a6cSmrg 11574b97a6cSmrgstatic list_ptr make_region_list(Display *, Window, XRectangle *, 11674b97a6cSmrg int *, int, XVisualInfo **, int *); 11774b97a6cSmrgstatic void destroy_region_list(list_ptr); 11874b97a6cSmrgstatic void subtr_rect_from_image_region(image_region_type *, 11974b97a6cSmrg int, int, int, int); 12074b97a6cSmrgstatic void add_rect_to_image_region(image_region_type *, 12174b97a6cSmrg int, int, int, int); 12274b97a6cSmrgstatic int src_in_region_list(image_win_type *, list_ptr); 12374b97a6cSmrgstatic void add_window_to_list(list_ptr, Window, int, int, 12474b97a6cSmrg int, int, int, int, int, 12574b97a6cSmrg Visual *, Colormap, Window); 12674b97a6cSmrgstatic int src_in_image(image_win_type *, int, XVisualInfo **); 12774b97a6cSmrgstatic int src_in_overlay(image_region_type *, int, OverlayInfo *, int *, 12874b97a6cSmrg int *); 12974b97a6cSmrgstatic void make_src_list(Display *, list_ptr, XRectangle *, Window, int, int, 13074b97a6cSmrg XWindowAttributes *, XRectangle *); 13174b97a6cSmrgstatic void destroy_image_region(image_region_type *); 132b3307321Smrg 133b3307321Smrg/* End of Prototype Declarations */ 134b3307321Smrg 13574b97a6cSmrgvoid 13674b97a6cSmrginitFakeVisual(Visual *Vis) 137b3307321Smrg{ 13874b97a6cSmrg Vis->ext_data = NULL; 13974b97a6cSmrg Vis->class = DirectColor; 14074b97a6cSmrg Vis->red_mask = 0x00FF0000; 14174b97a6cSmrg Vis->green_mask = 0x0000FF00; 14274b97a6cSmrg Vis->blue_mask = 0x000000FF; 14374b97a6cSmrg Vis->map_entries = 256; 14474b97a6cSmrg Vis->bits_per_rgb = 8; 145b3307321Smrg} 146b3307321Smrg 14774a3f230Smrgstatic void 1485e358ecaSmrgQueryColorMap(Display *disp, Colormap src_cmap, Visual *src_vis, 14974b97a6cSmrg XColor **src_colors, int *rShift, int *gShift, int *bShift) 150b3307321Smrg{ 1516728f30eSmrg unsigned int ncolors; 15274b97a6cSmrg XColor *colors; 15374b97a6cSmrg 15474b97a6cSmrg ncolors = (unsigned) src_vis->map_entries; 15574b97a6cSmrg *src_colors = colors = calloc(ncolors, sizeof(XColor)); 15674b97a6cSmrg 15774b97a6cSmrg if (src_vis->class != TrueColor && src_vis->class != DirectColor) { 1586728f30eSmrg for (unsigned int i = 0; i < ncolors; i++) { 15974b97a6cSmrg colors[i].pixel = i; 16074b97a6cSmrg colors[i].pad = 0; 16174b97a6cSmrg colors[i].flags = DoRed | DoGreen | DoBlue; 16274b97a6cSmrg } 16374b97a6cSmrg } 16474b97a6cSmrg else { /** src is decomposed rgb ***/ 1656728f30eSmrg unsigned long redMask, greenMask, blueMask; 1666728f30eSmrg int redShift, greenShift, blueShift; 16774b97a6cSmrg 168b3307321Smrg /* Get the X colormap */ 169b3307321Smrg redMask = src_vis->red_mask; 170b3307321Smrg greenMask = src_vis->green_mask; 171b3307321Smrg blueMask = src_vis->blue_mask; 17274b97a6cSmrg redShift = 0; 17374b97a6cSmrg while (!(redMask & 0x1)) { 17474b97a6cSmrg redShift++; 17574b97a6cSmrg redMask = redMask >> 1; 176b3307321Smrg } 17774b97a6cSmrg greenShift = 0; 17874b97a6cSmrg while (!(greenMask & 0x1)) { 17974b97a6cSmrg greenShift++; 18074b97a6cSmrg greenMask = greenMask >> 1; 181b3307321Smrg } 18274b97a6cSmrg blueShift = 0; 18374b97a6cSmrg while (!(blueMask & 0x1)) { 18474b97a6cSmrg blueShift++; 18574b97a6cSmrg blueMask = blueMask >> 1; 186b3307321Smrg } 18774b97a6cSmrg *rShift = redShift; 18874b97a6cSmrg *gShift = greenShift; 18974b97a6cSmrg *bShift = blueShift; 1906728f30eSmrg for (unsigned int i = 0; i < ncolors; i++) { 19174b97a6cSmrg if (i <= redMask) 19274b97a6cSmrg colors[i].pixel = (i << redShift); 19374b97a6cSmrg if (i <= greenMask) 19474b97a6cSmrg colors[i].pixel |= (i << greenShift); 19574b97a6cSmrg if (i <= blueMask) 19674b97a6cSmrg colors[i].pixel |= (i << blueShift); 19774b97a6cSmrg /***** example: for gecko's 3-3-2 map, blue index should be <= 3. 198b3307321Smrg colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift); 19974b97a6cSmrg *****/ 20074b97a6cSmrg colors[i].pad = 0; 20174b97a6cSmrg colors[i].flags = DoRed | DoGreen | DoBlue; 202b3307321Smrg } 20374b97a6cSmrg } 204b3307321Smrg 20574b97a6cSmrg XQueryColors(disp, src_cmap, colors, (int) ncolors); 206b3307321Smrg} 207b3307321Smrg 208b3307321Smrgint 2095e358ecaSmrgGetMultiVisualRegions(Display *disp, 21074b97a6cSmrg /* root win on which grab was done */ 21174b97a6cSmrg Window srcRootWinid, 21274b97a6cSmrg /* root rel UL corner of bounding box of grab */ 21374b97a6cSmrg int x, int y, 21474b97a6cSmrg /* size of bounding box of grab */ 21574b97a6cSmrg unsigned int width, unsigned int height, 21674b97a6cSmrg int *transparentOverlays, int *numVisuals, 21774b97a6cSmrg XVisualInfo **pVisuals, int *numOverlayVisuals, 21874b97a6cSmrg OverlayInfo **pOverlayVisuals, 21974b97a6cSmrg int *numImageVisuals, XVisualInfo ***pImageVisuals, 22074b97a6cSmrg /* list of regions to read from */ 22174b97a6cSmrg list_ptr *vis_regions, 22274b97a6cSmrg list_ptr *vis_image_regions, int *allImage) 223b3307321Smrg{ 22474b97a6cSmrg int hasNonDefault; 22574b97a6cSmrg XRectangle bbox; /* bounding box of grabbed area */ 226b3307321Smrg 227b3307321Smrg bbox.x = x; /* init X rect for bounding box */ 228b3307321Smrg bbox.y = y; 229b3307321Smrg bbox.width = width; 230b3307321Smrg bbox.height = height; 231b3307321Smrg 23274b97a6cSmrg GetXVisualInfo(disp, DefaultScreen(disp), 23374b97a6cSmrg transparentOverlays, 23474b97a6cSmrg numVisuals, pVisuals, 23574b97a6cSmrg numOverlayVisuals, pOverlayVisuals, 23674b97a6cSmrg numImageVisuals, pImageVisuals); 237b3307321Smrg 23874b97a6cSmrg *vis_regions = *vis_image_regions = NULL; 23974b97a6cSmrg if ((*vis_regions = make_region_list(disp, srcRootWinid, &bbox, 240b3307321Smrg &hasNonDefault, *numImageVisuals, 24174a3f230Smrg *pImageVisuals, allImage)) == NULL) 24274b97a6cSmrg return 0; 24374a3f230Smrg 24474b97a6cSmrg if (*transparentOverlays) { 24574b97a6cSmrg *allImage = 1; /* until proven otherwise, 24674b97a6cSmrg this flags that it to be an image only list */ 247b3307321Smrg *vis_image_regions = 24874b97a6cSmrg make_region_list(disp, srcRootWinid, &bbox, &hasNonDefault, 24974b97a6cSmrg *numImageVisuals, *pImageVisuals, allImage); 250b3307321Smrg } 251b3307321Smrg 25274b97a6cSmrg /* if there is a second region in any of the two lists return 1 */ 25374b97a6cSmrg if ((*vis_regions && (*vis_regions)->next && (*vis_regions)->next->next) || 25474b97a6cSmrg (*vis_image_regions && (*vis_image_regions)->next && 25574b97a6cSmrg (*vis_image_regions)->next->next)) 25674b97a6cSmrg return 1; 25774b97a6cSmrg else 25874b97a6cSmrg return 0; 259b3307321Smrg 260b3307321Smrg} 261b3307321Smrg 26274b97a6cSmrgstatic void 26374b97a6cSmrgTransferImage(Display *disp, XImage *reg_image, 26474b97a6cSmrg int srcw, int srch, 26574b97a6cSmrg image_region_type *reg, XImage *target_image, 26674b97a6cSmrg int dst_x, int dst_y) 267b3307321Smrg{ 268b3307321Smrg XColor *colors; 26974a3f230Smrg int rShift = 0, gShift = 0, bShift = 0; 270b3307321Smrg 27174b97a6cSmrg QueryColorMap(disp, reg->cmap, reg->vis, &colors, 27274b97a6cSmrg &rShift, &gShift, &bShift); 273b3307321Smrg 274b3307321Smrg switch (reg->vis->class) { 27574b97a6cSmrg case TrueColor: 2766728f30eSmrg for (int i = 0; i < srch; i++) { 2776728f30eSmrg for (int j = 0; j < srcw; j++) { 2786728f30eSmrg int old_pixel = XGetPixel(reg_image, j, i); 2796728f30eSmrg int new_pixel; 28074b97a6cSmrg 28174b97a6cSmrg if (reg->vis->map_entries == 16) { 2826728f30eSmrg int red_ind = (old_pixel & reg->vis->red_mask) >> rShift; 2836728f30eSmrg int green_ind = (old_pixel & reg->vis->green_mask) >> gShift; 2846728f30eSmrg int blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift; 28574b97a6cSmrg 28674b97a6cSmrg new_pixel = ( 28774b97a6cSmrg ((colors[red_ind].red >> 8) << RED_SHIFT) | 28874b97a6cSmrg ((colors[green_ind].green >> 8) << GREEN_SHIFT) | 28974b97a6cSmrg ((colors[blue_ind].blue >> 8) << BLUE_SHIFT) 29074b97a6cSmrg ); 29174b97a6cSmrg } 29274b97a6cSmrg else 29374b97a6cSmrg new_pixel = old_pixel; 29474b97a6cSmrg 29574b97a6cSmrg XPutPixel(target_image, dst_x + j, dst_y + i, new_pixel); 29674b97a6cSmrg 29774b97a6cSmrg } 29874b97a6cSmrg } 29974b97a6cSmrg break; 30074b97a6cSmrg case DirectColor: 3016728f30eSmrg for (int i = 0; i < srch; i++) { 30274b97a6cSmrg 3036728f30eSmrg for (int j = 0; j < srcw; j++) { 3046728f30eSmrg int old_pixel = XGetPixel(reg_image, j, i); 3056728f30eSmrg int red_ind = (old_pixel & reg->vis->red_mask) >> rShift; 3066728f30eSmrg int green_ind = (old_pixel & reg->vis->green_mask) >> gShift; 3076728f30eSmrg int blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift; 30874b97a6cSmrg 3096728f30eSmrg int new_pixel = ( 31074b97a6cSmrg ((colors[red_ind].red >> 8) << RED_SHIFT) | 31174b97a6cSmrg ((colors[green_ind].green >> 8) << GREEN_SHIFT) | 31274b97a6cSmrg ((colors[blue_ind].blue >> 8) << BLUE_SHIFT) 31374b97a6cSmrg ); 31474b97a6cSmrg XPutPixel(target_image, dst_x + j, dst_y + i, new_pixel); 31574b97a6cSmrg 31674b97a6cSmrg } 31774b97a6cSmrg } 31874b97a6cSmrg break; 31974b97a6cSmrg default: 3206728f30eSmrg for (int i = 0; i < srch; i++) { 3216728f30eSmrg for (int j = 0; j < srcw; j++) { 3226728f30eSmrg int old_pixel = XGetPixel(reg_image, j, i); 32374b97a6cSmrg 3246728f30eSmrg int new_pixel = ( 32574b97a6cSmrg ((colors[old_pixel].red >> 8) << RED_SHIFT) | 32674b97a6cSmrg ((colors[old_pixel].green >> 8) << GREEN_SHIFT) | 32774b97a6cSmrg ((colors[old_pixel].blue >> 8) << BLUE_SHIFT) 32874b97a6cSmrg ); 32974b97a6cSmrg XPutPixel(target_image, dst_x + j, dst_y + i, new_pixel); 33074b97a6cSmrg 33174b97a6cSmrg } 33274b97a6cSmrg } 33374b97a6cSmrg break; 334b3307321Smrg } 335b3307321Smrg} 336b3307321Smrg 337b3307321Smrgstatic XImage * 3385e358ecaSmrgReadRegionsInList(Display *disp, Visual *fakeVis, int depth, int format, 33974b97a6cSmrg unsigned int width, unsigned int height, 34074b97a6cSmrg XRectangle bbox, /* bounding box of grabbed area */ 34174b97a6cSmrg list_ptr regions) /* list of regions to read from */ 342b3307321Smrg{ 3436728f30eSmrg int datalen; 344b3307321Smrg 34574b97a6cSmrg XImage *reg_image, *ximage; 34674b97a6cSmrg int bytes_per_line; 34774a3f230Smrg 34874b97a6cSmrg ximage = XCreateImage(disp, fakeVis, depth, format, 0, NULL, width, height, 34974b97a6cSmrg 8, 0); 350b3307321Smrg bytes_per_line = ximage->bytes_per_line; 351b3307321Smrg 35274b97a6cSmrg datalen = height * bytes_per_line; 35374b97a6cSmrg if (format != ZPixmap) 35474b97a6cSmrg datalen *= depth; 35574b97a6cSmrg ximage->data = malloc(datalen); 35674b97a6cSmrg memset(ximage->data, 0, datalen); 357b3307321Smrg 358b3307321Smrg ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/ 35974a3f230Smrg 3606728f30eSmrg for (image_region_type *reg = (image_region_type *) first_in_list(regions); 3616728f30eSmrg reg; reg = (image_region_type *) next_in_list(regions)) { 3626728f30eSmrg 3636728f30eSmrg struct my_XRegion *vis_reg = (struct my_XRegion *) (reg->visible_region); 36474b97a6cSmrg 3656728f30eSmrg for (int rect = 0; rect < vis_reg->numRects; rect++) { 36674b97a6cSmrg/** ------------------------------------------------------------------------ 36774b97a6cSmrg Intersect bbox with visible part of region giving src rect & output 36874b97a6cSmrg location. Width is the min right side minus the max left side. 36974b97a6cSmrg Similar for height. Offset src rect so x,y are relative to 37074b97a6cSmrg origin of win, not the root-relative visible rect of win. 37174b97a6cSmrg ------------------------------------------------------------------------ **/ 3726728f30eSmrg int srcRect_width = 37374b97a6cSmrg MIN(vis_reg->rects[rect].x2, bbox.width + bbox.x) - 37474b97a6cSmrg MAX(vis_reg->rects[rect].x1, bbox.x); 3756728f30eSmrg int srcRect_height = 37674b97a6cSmrg MIN(vis_reg->rects[rect].y2, bbox.height + bbox.y) - 37774b97a6cSmrg MAX(vis_reg->rects[rect].y1, bbox.y); 3786728f30eSmrg int srcRect_x, srcRect_y; 3796728f30eSmrg int dst_x, dst_y; /* where in pixmap to write (UL) */ 38074b97a6cSmrg 3816728f30eSmrg int diff = bbox.x - vis_reg->rects[rect].x1; 38274b97a6cSmrg srcRect_x = MAX(0,diff) + 38374b97a6cSmrg (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border); 38474b97a6cSmrg dst_x = MAX(0, -diff); 38574b97a6cSmrg 38674b97a6cSmrg diff = bbox.y - vis_reg->rects[rect].y1; 38774b97a6cSmrg srcRect_y = MAX(0, diff) + 38874b97a6cSmrg (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border); 38974b97a6cSmrg dst_y = MAX(0, -diff); 39074b97a6cSmrg 39174b97a6cSmrg reg_image = XGetImage(disp, reg->win, srcRect_x, srcRect_y, 39274b97a6cSmrg srcRect_width, srcRect_height, AllPlanes, 39374b97a6cSmrg format); 39474b97a6cSmrg TransferImage(disp, reg_image, srcRect_width, srcRect_height, reg, 39574b97a6cSmrg ximage, dst_x, dst_y); 39674b97a6cSmrg } 397b3307321Smrg } 39874b97a6cSmrg return ximage; 399b3307321Smrg} 400b3307321Smrg 401b3307321Smrg 402b3307321Smrg/** ------------------------------------------------------------------------ 403b3307321Smrg ------------------------------------------------------------------------ **/ 404b3307321Smrg 40574b97a6cSmrgXImage * 40674b97a6cSmrgReadAreaToImage(Display *disp, 40774b97a6cSmrg /* root win on which grab was done */ 40874b97a6cSmrg Window srcRootWinid, 40974b97a6cSmrg /* root rel UL corner of bounding box of grab */ 41074b97a6cSmrg int x, int y, 41174b97a6cSmrg /* size of bounding box of grab */ 41274b97a6cSmrg unsigned int width, unsigned int height, 41374b97a6cSmrg int numVisuals, XVisualInfo *pVisuals, 41474b97a6cSmrg int numOverlayVisuals, OverlayInfo *pOverlayVisuals, 41574b97a6cSmrg int numImageVisuals, XVisualInfo **pImageVisuals, 41674b97a6cSmrg /* list of regions to read from */ 41774b97a6cSmrg list_ptr vis_regions, 41874b97a6cSmrg /* list of regions to read from */ 41974b97a6cSmrg list_ptr vis_image_regions, 42074b97a6cSmrg int format, int allImage) 421b3307321Smrg{ 42274b97a6cSmrg image_region_type *reg; 42374b97a6cSmrg XRectangle bbox; /* bounding box of grabbed area */ 42474b97a6cSmrg int depth; 42574b97a6cSmrg XImage *ximage, *ximage_ipm = NULL; 42674b97a6cSmrg Visual fakeVis; 42774b97a6cSmrg XImage *image; 42874b97a6cSmrg 429b3307321Smrg#if 0 43074b97a6cSmrg unsigned char *pmData, *ipmData; 431b3307321Smrg#endif 43274b97a6cSmrg int transparentColor, transparentType; 433b3307321Smrg 43474b97a6cSmrg bbox.x = x; /* init X rect for bounding box */ 435b3307321Smrg bbox.y = y; 436b3307321Smrg bbox.width = width; 437b3307321Smrg bbox.height = height; 438b3307321Smrg 43974b97a6cSmrg initFakeVisual(&fakeVis); 440b3307321Smrg 44174b97a6cSmrg depth = 24; 44274b97a6cSmrg ximage = ReadRegionsInList(disp, &fakeVis, depth, format, width, height, 44374b97a6cSmrg bbox, vis_regions); 444b3307321Smrg#if 0 44574b97a6cSmrg pmData = (unsigned char *) ximage->data; 446b3307321Smrg#endif 447b3307321Smrg 448b3307321Smrg/* if transparency possible do it again, but this time for image planes only */ 44974b97a6cSmrg if (vis_image_regions && (vis_image_regions->next) && !allImage) { 45074b97a6cSmrg ximage_ipm = 45174b97a6cSmrg ReadRegionsInList(disp, &fakeVis, depth, format, width, height, 45274b97a6cSmrg bbox, vis_image_regions); 453b3307321Smrg#if 0 45474b97a6cSmrg ipmData = (unsigned char *) ximage_ipm->data; 455b3307321Smrg#endif 456b3307321Smrg } 457b3307321Smrg/* Now tranverse the overlay visual windows and test for transparency index. */ 4586728f30eSmrg/* If you find one, substitute the value from the matching image plane pixmap. */ 459b3307321Smrg 46074b97a6cSmrg for (reg = (image_region_type *) first_in_list(vis_regions); reg; 46174b97a6cSmrg reg = (image_region_type *) next_in_list(vis_regions)) { 46274b97a6cSmrg 46374b97a6cSmrg if (src_in_overlay(reg, numOverlayVisuals, pOverlayVisuals, 46474b97a6cSmrg &transparentColor, &transparentType)) { 4656728f30eSmrg int srcRect_x, srcRect_y, srcRect_width, srcRect_height; 4666728f30eSmrg int diff; 4676728f30eSmrg int dst_x, dst_y; /* where in pixmap to write (UL) */ 46874b97a6cSmrg int test = 0; 46974b97a6cSmrg 47074b97a6cSmrg srcRect_width = 47174b97a6cSmrg MIN(reg->width + reg->x_vis, bbox.width + bbox.x) 47274b97a6cSmrg - MAX(reg->x_vis, bbox.x); 47374b97a6cSmrg srcRect_height = 47474b97a6cSmrg MIN(reg->height + reg->y_vis, bbox.height + bbox.y) 47574b97a6cSmrg - MAX(reg->y_vis, bbox.y); 47674b97a6cSmrg diff = bbox.x - reg->x_vis; 47774b97a6cSmrg srcRect_x = 47874b97a6cSmrg MAX(0, diff) + (reg->x_vis - reg->x_rootrel - reg->border); 47974b97a6cSmrg dst_x = MAX(0, -diff); 48074b97a6cSmrg diff = bbox.y - reg->y_vis; 48174b97a6cSmrg srcRect_y = 48274b97a6cSmrg MAX(0, diff) + (reg->y_vis - reg->y_rootrel - reg->border); 48374b97a6cSmrg dst_y = MAX(0, -diff); 48474b97a6cSmrg /* let's test some pixels for transparency */ 48574b97a6cSmrg image = XGetImage(disp, reg->win, srcRect_x, srcRect_y, 48674b97a6cSmrg srcRect_width, srcRect_height, 0xffffffff, 48774b97a6cSmrg ZPixmap); 48874b97a6cSmrg 48974b97a6cSmrg /* let's assume byte per pixel for overlay image for now */ 49074b97a6cSmrg if ((image->depth == 8) && (transparentType == TransparentPixel)) { 49174b97a6cSmrg unsigned char *pixel_ptr; 49274b97a6cSmrg unsigned char *start_of_line = (unsigned char *) image->data; 49374b97a6cSmrg 4946728f30eSmrg for (int y1 = 0; y1 < srcRect_height; y1++) { 49574b97a6cSmrg pixel_ptr = start_of_line; 4966728f30eSmrg for (int x1 = 0; x1 < srcRect_width; x1++) { 49774b97a6cSmrg if (*pixel_ptr++ == transparentColor) { 4986728f30eSmrg int pixel; 499b3307321Smrg#if 0 50074b97a6cSmrg *pmData++ = *ipmData++; 50174b97a6cSmrg *pmData++ = *ipmData++; 50274b97a6cSmrg *pmData++ = *ipmData++; 503b3307321Smrg#endif 50474b97a6cSmrg pixel = 50574b97a6cSmrg XGetPixel(ximage_ipm, dst_x + x1, dst_y + y1); 50674b97a6cSmrg XPutPixel(ximage, dst_x + x1, dst_y + y1, pixel); 50774b97a6cSmrg 50874b97a6cSmrg if (!test) { 50974b97a6cSmrg test = 1; 51074b97a6cSmrg } 51174b97a6cSmrg } 512b3307321Smrg#if 0 51374b97a6cSmrg else { 51474b97a6cSmrg pmData += 3; 51574b97a6cSmrg ipmData += 3; 51674b97a6cSmrg } 517b3307321Smrg#endif 51874b97a6cSmrg } 51974b97a6cSmrg start_of_line += image->bytes_per_line; 52074b97a6cSmrg } 52174b97a6cSmrg } 52274b97a6cSmrg else { 52374b97a6cSmrg if (transparentType == TransparentPixel) { 5246728f30eSmrg for (int y1 = 0; y1 < srcRect_height; y1++) { 5256728f30eSmrg for (int x1 = 0; x1 < srcRect_width; x1++) { 52674b97a6cSmrg int pixel_value = XGetPixel(image, x1, y1); 52774b97a6cSmrg 52874b97a6cSmrg if (pixel_value == transparentColor) { 5296728f30eSmrg int pixel; 530b3307321Smrg#if 0 53174b97a6cSmrg *pmData++ = *ipmData++; 53274b97a6cSmrg *pmData++ = *ipmData++; 53374b97a6cSmrg *pmData++ = *ipmData++; 534b3307321Smrg#endif 53574b97a6cSmrg pixel = 53674b97a6cSmrg XGetPixel(ximage_ipm, dst_x + x1, 53774b97a6cSmrg dst_y + y1); 53874b97a6cSmrg XPutPixel(ximage, dst_x + x1, dst_y + y1, 53974b97a6cSmrg pixel); 54074b97a6cSmrg if (!test) { 54174b97a6cSmrg test = 1; 54274b97a6cSmrg } 54374b97a6cSmrg } 544b3307321Smrg#if 0 54574b97a6cSmrg else { 54674b97a6cSmrg pmData += 3; 54774b97a6cSmrg ipmData += 3; 54874b97a6cSmrg } 549b3307321Smrg#endif 55074b97a6cSmrg } 55174b97a6cSmrg } 55274b97a6cSmrg } 55374b97a6cSmrg else { 5546728f30eSmrg for (int y1 = 0; y1 < srcRect_height; y1++) { 5556728f30eSmrg for (int x1 = 0; x1 < srcRect_width; x1++) { 55674b97a6cSmrg int pixel_value = XGetPixel(image, x1, y1); 55774b97a6cSmrg 55874b97a6cSmrg if (pixel_value & transparentColor) { 5596728f30eSmrg int pixel; 560b3307321Smrg#if 0 56174b97a6cSmrg *pmData++ = *ipmData++; 56274b97a6cSmrg *pmData++ = *ipmData++; 56374b97a6cSmrg *pmData++ = *ipmData++; 564b3307321Smrg#endif 56574b97a6cSmrg pixel = 56674b97a6cSmrg XGetPixel(ximage_ipm, dst_x + x1, 56774b97a6cSmrg dst_y + y1); 56874b97a6cSmrg XPutPixel(ximage, dst_x + x1, dst_y + y1, 56974b97a6cSmrg pixel); 57074b97a6cSmrg if (!test) { 57174b97a6cSmrg test = 1; 57274b97a6cSmrg } 57374b97a6cSmrg } 574b3307321Smrg#if 0 57574b97a6cSmrg else { 57674b97a6cSmrg pmData += 3; 57774b97a6cSmrg ipmData += 3; 57874b97a6cSmrg } 579b3307321Smrg#endif 58074b97a6cSmrg } 58174b97a6cSmrg } 58274b97a6cSmrg } 58374b97a6cSmrg } 58474b97a6cSmrg XDestroyImage(image); 58574b97a6cSmrg } /* end of src_in_overlay */ 586b3307321Smrg } /** end transparency **/ 58774b97a6cSmrg destroy_region_list(vis_regions); 58874b97a6cSmrg if (vis_image_regions) 58974b97a6cSmrg destroy_region_list(vis_image_regions); 590b3307321Smrg FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals); 591b3307321Smrg XSync(disp, 0); 592b3307321Smrg 593b3307321Smrg return ximage; 594b3307321Smrg} 595b3307321Smrg 596b3307321Smrg/** ------------------------------------------------------------------------ 597b3307321Smrg Creates a list of the subwindows of a given window which have a 598b3307321Smrg different visual than their parents. The function is recursive. 599b3307321Smrg This list is used in make_region_list(), which coalesces the 600b3307321Smrg windows with the same visual into a region. 601b3307321Smrg image_wins must point to an existing list struct that's already 602b3307321Smrg been zeroed (zero_list()). 603b3307321Smrg ------------------------------------------------------------------------ **/ 60474b97a6cSmrgstatic void 60574b97a6cSmrgmake_src_list(Display *disp, list_ptr image_wins, 60674b97a6cSmrg /* bnding box of area we want */ 60774b97a6cSmrg XRectangle *bbox, 60874b97a6cSmrg Window curr, 60974b97a6cSmrg /* pos of curr WRT root */ 61074b97a6cSmrg int x_rootrel, int y_rootrel, 61174b97a6cSmrg XWindowAttributes *curr_attrs, 61274b97a6cSmrg /* visible part of curr, not obscurred by ancestors */ 61374b97a6cSmrg XRectangle *pclip) 614b3307321Smrg{ 615b3307321Smrg XWindowAttributes child_attrs; 61674b97a6cSmrg Window root, parent, *child; /* variables for XQueryTree() */ 61774b97a6cSmrg unsigned int nchild; /* variables for XQueryTree() */ 61874b97a6cSmrg XRectangle child_clip; /* vis part of child */ 619b3307321Smrg 620b3307321Smrg /* check that win is mapped & not outside bounding box */ 621b3307321Smrg if (curr_attrs->map_state == IsViewable && 62274b97a6cSmrg curr_attrs->class == InputOutput && 62374b97a6cSmrg !(pclip->x >= (int) (bbox->x + bbox->width) || 62474b97a6cSmrg pclip->y >= (int) (bbox->y + bbox->height) || 62574b97a6cSmrg (int) (pclip->x + pclip->width) <= bbox->x || 62674b97a6cSmrg (int) (pclip->y + pclip->height) <= bbox->y)) { 62774b97a6cSmrg 6286728f30eSmrg Window *save_child_list; 6296728f30eSmrg int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt; 6306728f30eSmrg 63174b97a6cSmrg XQueryTree(disp, curr, &root, &parent, &child, &nchild); 63274b97a6cSmrg save_child_list = child; /* so we can free list when we're done */ 63374b97a6cSmrg add_window_to_list(image_wins, curr, x_rootrel, y_rootrel, 63474b97a6cSmrg pclip->x, pclip->y, 63574b97a6cSmrg pclip->width, pclip->height, 63674b97a6cSmrg curr_attrs->border_width, curr_attrs->visual, 63774b97a6cSmrg curr_attrs->colormap, parent); 63874a3f230Smrg 639b3307321Smrg/** ------------------------------------------------------------------------ 640b3307321Smrg set RR coords of right (Rt), left (X), bottom (Bt) and top (Y) 641b3307321Smrg of rect we clip all children by. This is our own clip rect (pclip) 642b3307321Smrg inflicted on us by our parent plus our own borders. Within the 643b3307321Smrg child loop, we figure the clip rect for each child by adding in 644b3307321Smrg it's rectangle (not taking into account the child's borders). 645b3307321Smrg ------------------------------------------------------------------------ **/ 64674b97a6cSmrg curr_clipX = MAX(pclip->x, x_rootrel + (int) curr_attrs->border_width); 64774b97a6cSmrg curr_clipY = MAX(pclip->y, y_rootrel + (int) curr_attrs->border_width); 64874b97a6cSmrg curr_clipRt = MIN(pclip->x + (int) pclip->width, 64974b97a6cSmrg x_rootrel + (int) curr_attrs->width + 65074b97a6cSmrg 2 * (int) curr_attrs->border_width); 65174b97a6cSmrg curr_clipBt = MIN(pclip->y + (int) pclip->height, 65274b97a6cSmrg y_rootrel + (int) curr_attrs->height + 65374b97a6cSmrg 2 * (int) curr_attrs->border_width); 65474b97a6cSmrg 65574b97a6cSmrg while (nchild--) { 65674b97a6cSmrg int new_width, new_height; 65774b97a6cSmrg int child_xrr, child_yrr; /* root relative x & y of child */ 65874b97a6cSmrg 65974b97a6cSmrg XGetWindowAttributes(disp, *child, &child_attrs); 66074b97a6cSmrg 66174b97a6cSmrg /* intersect parent & child clip rects */ 66274b97a6cSmrg child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width; 66374b97a6cSmrg child_clip.x = MAX(curr_clipX, child_xrr); 66474b97a6cSmrg new_width = MIN(curr_clipRt, child_xrr + (int) child_attrs.width 66574b97a6cSmrg + 2 * child_attrs.border_width) 66674b97a6cSmrg - child_clip.x; 66774b97a6cSmrg if (new_width >= 0) { 66874b97a6cSmrg child_clip.width = new_width; 66974b97a6cSmrg 67074b97a6cSmrg child_yrr = y_rootrel + child_attrs.y + 67174b97a6cSmrg curr_attrs->border_width; 67274b97a6cSmrg child_clip.y = MAX(curr_clipY, child_yrr); 67374b97a6cSmrg new_height = MIN(curr_clipBt, 67474b97a6cSmrg child_yrr + (int) child_attrs.height + 67574b97a6cSmrg 2 * child_attrs.border_width) 67674b97a6cSmrg - child_clip.y; 67774b97a6cSmrg if (new_height >= 0) { 67874b97a6cSmrg child_clip.height = new_height; 67974b97a6cSmrg make_src_list(disp, image_wins, bbox, *child, 68074b97a6cSmrg child_xrr, child_yrr, 68174b97a6cSmrg &child_attrs, &child_clip); 68274b97a6cSmrg } 68374b97a6cSmrg } 68474b97a6cSmrg child++; 68574b97a6cSmrg } 68674b97a6cSmrg XFree(save_child_list); 687b3307321Smrg } 688b3307321Smrg} 689b3307321Smrg 690b3307321Smrg 691b3307321Smrg/** ------------------------------------------------------------------------ 692b3307321Smrg This function creates a list of regions which tile a specified 693b3307321Smrg window. Each region contains all visible portions of the window 694b3307321Smrg which are drawn with the same visual. For example, if the 695b3307321Smrg window consists of subwindows of two different visual types, 69674a3f230Smrg there will be two regions in the list. 697b3307321Smrg Returns a pointer to the list. 698b3307321Smrg ------------------------------------------------------------------------ **/ 69974b97a6cSmrgstatic list_ptr 70074b97a6cSmrgmake_region_list(Display *disp, Window win, XRectangle *bbox, 70174b97a6cSmrg int *hasNonDefault, int numImageVisuals, 70274b97a6cSmrg XVisualInfo **pImageVisuals, int *allImage) 703b3307321Smrg{ 70474b97a6cSmrg XWindowAttributes win_attrs; 70574b97a6cSmrg list image_wins; 70674b97a6cSmrg list_ptr image_regions; 70774b97a6cSmrg list_ptr srcs_left; 70874b97a6cSmrg image_region_type *new_reg; 70974b97a6cSmrg image_win_type *base_src, *src; 71074b97a6cSmrg Region bbox_region = XCreateRegion(); 71174b97a6cSmrg XRectangle clip; 71274b97a6cSmrg int image_only; 71374b97a6cSmrg int count = 0; 71474a3f230Smrg 715b3307321Smrg *hasNonDefault = False; 71674b97a6cSmrg XUnionRectWithRegion(bbox, bbox_region, bbox_region); 71774b97a6cSmrg XGetWindowAttributes(disp, win, &win_attrs); 718b3307321Smrg 71974b97a6cSmrg zero_list(&image_wins); 720b3307321Smrg clip.x = 0; 721b3307321Smrg clip.y = 0; 72274b97a6cSmrg clip.width = win_attrs.width; 723b3307321Smrg clip.height = win_attrs.height; 72474b97a6cSmrg make_src_list(disp, &image_wins, bbox, win, 72574b97a6cSmrg 0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip); 726b3307321Smrg 727b3307321Smrg image_regions = new_list(); 72874b97a6cSmrg image_only = (*allImage) ? True : False; 72974b97a6cSmrg 73074b97a6cSmrg for (base_src = (image_win_type *) first_in_list(&image_wins); base_src; 73174b97a6cSmrg base_src = (image_win_type *) next_in_list(&image_wins)) { 73274b97a6cSmrg /* test for image visual */ 73374b97a6cSmrg if (!image_only || 73474b97a6cSmrg src_in_image(base_src, numImageVisuals, pImageVisuals)) { 73574b97a6cSmrg /* find a window whose visual hasn't been put in list yet */ 73674b97a6cSmrg if (!src_in_region_list(base_src, image_regions)) { 7376728f30eSmrg if (!(new_reg = malloc(sizeof(image_region_type)))) { 73874b97a6cSmrg return (list_ptr) NULL; 73974b97a6cSmrg } 74074b97a6cSmrg count++; 74174b97a6cSmrg 74274b97a6cSmrg new_reg->visible_region = XCreateRegion(); 74374b97a6cSmrg new_reg->win = base_src->win; 74474b97a6cSmrg new_reg->vis = base_src->vis; 74574b97a6cSmrg new_reg->cmap = base_src->cmap; 74674b97a6cSmrg new_reg->x_rootrel = base_src->x_rootrel; 74774b97a6cSmrg new_reg->y_rootrel = base_src->y_rootrel; 74874b97a6cSmrg new_reg->x_vis = base_src->x_vis; 74974b97a6cSmrg new_reg->y_vis = base_src->y_vis; 75074b97a6cSmrg new_reg->width = base_src->width; 75174b97a6cSmrg new_reg->height = base_src->height; 75274b97a6cSmrg new_reg->border = base_src->border_width; 75374b97a6cSmrg 75474b97a6cSmrg srcs_left = 75574b97a6cSmrg (list_ptr) dup_list_head(&image_wins, START_AT_CURR); 75674b97a6cSmrg for (src = (image_win_type *) first_in_list(srcs_left); src; 75774b97a6cSmrg src = (image_win_type *) next_in_list(srcs_left)) { 75874b97a6cSmrg if (SAME_REGIONS(base_src, src)) { 75974b97a6cSmrg add_rect_to_image_region(new_reg, 76074b97a6cSmrg src->x_vis, src->y_vis, 76174b97a6cSmrg src->width, src->height); 76274b97a6cSmrg } 76374b97a6cSmrg else { 76474b97a6cSmrg if (!image_only || 76574b97a6cSmrg src_in_image(src, numImageVisuals, pImageVisuals)) 76674b97a6cSmrg { 76774b97a6cSmrg subtr_rect_from_image_region(new_reg, src->x_vis, 76874b97a6cSmrg src->y_vis, src->width, 76974b97a6cSmrg src->height); 77074b97a6cSmrg } 77174b97a6cSmrg } 77274b97a6cSmrg } 77374b97a6cSmrg XIntersectRegion(bbox_region, new_reg->visible_region, 77474b97a6cSmrg new_reg->visible_region); 77574b97a6cSmrg if (!XEmptyRegion(new_reg->visible_region)) { 77674b97a6cSmrg add_to_list(image_regions, new_reg); 77774b97a6cSmrg if (new_reg->vis != DefaultVisualOfScreen(win_attrs.screen) 77874b97a6cSmrg || new_reg->cmap != 77974b97a6cSmrg DefaultColormapOfScreen(win_attrs.screen)) { 78074b97a6cSmrg *hasNonDefault = True; 78174b97a6cSmrg } 78274b97a6cSmrg } 78374b97a6cSmrg else { 78474b97a6cSmrg XDestroyRegion(new_reg->visible_region); 7856728f30eSmrg free(new_reg); 78674b97a6cSmrg } 78774b97a6cSmrg } 78874b97a6cSmrg } 78974b97a6cSmrg else 79074b97a6cSmrg *allImage = 0; 791b3307321Smrg } 79274b97a6cSmrg delete_list(&image_wins, True); 79374b97a6cSmrg XDestroyRegion(bbox_region); 794b3307321Smrg return image_regions; 795b3307321Smrg} 79674b97a6cSmrg 797b3307321Smrg/** ------------------------------------------------------------------------ 798b3307321Smrg Destructor called from destroy_region_list(). 799b3307321Smrg ------------------------------------------------------------------------ **/ 80074b97a6cSmrgstatic void 80174b97a6cSmrgdestroy_image_region(image_region_type *image_region) 802b3307321Smrg{ 80374b97a6cSmrg XDestroyRegion(image_region->visible_region); 8046728f30eSmrg free(image_region); 805b3307321Smrg} 806b3307321Smrg 807b3307321Smrg/** ------------------------------------------------------------------------ 808b3307321Smrg Destroys the region list, destroying all the regions contained in it. 809b3307321Smrg ------------------------------------------------------------------------ **/ 81074b97a6cSmrgstatic void 81174b97a6cSmrgdestroy_region_list(list_ptr rlist) 812b3307321Smrg{ 81374b97a6cSmrg delete_list_destroying(rlist, (DESTRUCT_FUNC_PTR) destroy_image_region); 814b3307321Smrg} 815b3307321Smrg 816b3307321Smrg/** ------------------------------------------------------------------------ 817b3307321Smrg Subtracts the specified rectangle from the region in image_region. 818b3307321Smrg First converts the rectangle to a region of its own, since X 819b3307321Smrg only provides a way to subtract one region from another, not a 820b3307321Smrg rectangle from a region. 821b3307321Smrg ------------------------------------------------------------------------ **/ 82274b97a6cSmrgstatic void 82374b97a6cSmrgsubtr_rect_from_image_region(image_region_type *image_region, 82474b97a6cSmrg int x, int y, int width, int height) 825b3307321Smrg{ 826b3307321Smrg XRectangle rect; 827b3307321Smrg Region rect_region; 828b3307321Smrg 829b3307321Smrg rect_region = XCreateRegion(); 830b3307321Smrg rect.x = x; 831b3307321Smrg rect.y = y; 832b3307321Smrg rect.width = width; 833b3307321Smrg rect.height = height; 83474b97a6cSmrg XUnionRectWithRegion(&rect, rect_region, rect_region); 83574b97a6cSmrg XSubtractRegion(image_region->visible_region, rect_region, 83674b97a6cSmrg image_region->visible_region); 83774b97a6cSmrg XDestroyRegion(rect_region); 838b3307321Smrg} 839b3307321Smrg 840b3307321Smrg/** ------------------------------------------------------------------------ 841b3307321Smrg Adds the specified rectangle to the region in image_region. 842b3307321Smrg ------------------------------------------------------------------------ **/ 84374b97a6cSmrgstatic void 84474b97a6cSmrgadd_rect_to_image_region(image_region_type *image_region, 84574b97a6cSmrg int x, int y, int width, int height) 846b3307321Smrg{ 847b3307321Smrg XRectangle rect; 848b3307321Smrg 849b3307321Smrg rect.x = x; 850b3307321Smrg rect.y = y; 851b3307321Smrg rect.width = width; 852b3307321Smrg rect.height = height; 85374b97a6cSmrg XUnionRectWithRegion(&rect, image_region->visible_region, 85474b97a6cSmrg image_region->visible_region); 855b3307321Smrg} 856b3307321Smrg 857b3307321Smrg/** ------------------------------------------------------------------------ 858b3307321Smrg Returns TRUE if the given src's visual is already represented in 859b3307321Smrg the image_regions list, FALSE otherwise. 860b3307321Smrg ------------------------------------------------------------------------ **/ 86174b97a6cSmrgstatic int 86274b97a6cSmrgsrc_in_region_list(image_win_type *src, list_ptr image_regions) 863b3307321Smrg{ 86474b97a6cSmrg image_region_type *ir; 865b3307321Smrg 86674b97a6cSmrg for (ir = (image_region_type *) first_in_list(image_regions); ir; 86774b97a6cSmrg ir = (image_region_type *) next_in_list(image_regions)) { 86874b97a6cSmrg if (SAME_REGIONS(ir, src)) { 869b3307321Smrg 87074b97a6cSmrg return 1; 87174b97a6cSmrg } 872b3307321Smrg } 873b3307321Smrg 874b3307321Smrg return 0; 875b3307321Smrg} 876b3307321Smrg 877b3307321Smrg/** ------------------------------------------------------------------------ 878b3307321Smrg Makes a new entry in image_wins with the given fields filled in. 879b3307321Smrg ------------------------------------------------------------------------ **/ 88074b97a6cSmrgstatic void 88174b97a6cSmrgadd_window_to_list(list_ptr image_wins, Window w, 88274b97a6cSmrg int xrr, int yrr, int x_vis, int y_vis, 88374b97a6cSmrg int width, int height, int border_width, 88474b97a6cSmrg Visual *vis, Colormap cmap, Window parent) 885b3307321Smrg{ 88674b97a6cSmrg image_win_type *new_src; 887b3307321Smrg 8886728f30eSmrg if ((new_src = malloc(sizeof(image_win_type))) == NULL) 88974b97a6cSmrg return; 890b3307321Smrg 891b3307321Smrg new_src->win = w; 892b3307321Smrg new_src->x_rootrel = xrr; 893b3307321Smrg new_src->y_rootrel = yrr; 894b3307321Smrg new_src->x_vis = x_vis; 895b3307321Smrg new_src->y_vis = y_vis; 896b3307321Smrg new_src->width = width; 897b3307321Smrg new_src->height = height; 898b3307321Smrg new_src->border_width = border_width; 899b3307321Smrg new_src->vis = vis; 900b3307321Smrg new_src->cmap = cmap; 901b3307321Smrg new_src->parent = parent; 90274b97a6cSmrg add_to_list(image_wins, new_src); 903b3307321Smrg} 904b3307321Smrg 905b3307321Smrg/** ------------------------------------------------------------------------ 906b3307321Smrg Returns TRUE if the given src's visual is in the image planes, 907b3307321Smrg FALSE otherwise. 908b3307321Smrg ------------------------------------------------------------------------ **/ 90974b97a6cSmrgstatic int 91074b97a6cSmrgsrc_in_image(image_win_type *src, int numImageVisuals, 91174b97a6cSmrg XVisualInfo **pImageVisuals) 912b3307321Smrg{ 91374b97a6cSmrg int i; 914b3307321Smrg 91574b97a6cSmrg for (i = 0; i < numImageVisuals; i++) { 91674b97a6cSmrg if (pImageVisuals[i]->visual == src->vis) 91774b97a6cSmrg return 1; 918b3307321Smrg } 919b3307321Smrg return 0; 920b3307321Smrg} 921b3307321Smrg 922b3307321Smrg 923b3307321Smrg/** ------------------------------------------------------------------------ 924b3307321Smrg Returns TRUE if the given src's visual is in the overlay planes 925b3307321Smrg and transparency is possible, FALSE otherwise. 926b3307321Smrg ------------------------------------------------------------------------ **/ 92774b97a6cSmrgstatic int 92874b97a6cSmrgsrc_in_overlay(image_region_type *src, int numOverlayVisuals, 92974b97a6cSmrg OverlayInfo *pOverlayVisuals, 93074b97a6cSmrg int *transparentColor, int *transparentType) 931b3307321Smrg{ 93274b97a6cSmrg int i; 93374b97a6cSmrg 93474b97a6cSmrg for (i = 0; i < numOverlayVisuals; i++) { 93574b97a6cSmrg if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis) 93674b97a6cSmrg && (pOverlayVisuals[i].transparentType != None)) { 93774b97a6cSmrg *transparentColor = pOverlayVisuals[i].value; 93874b97a6cSmrg *transparentType = pOverlayVisuals[i].transparentType; 93974b97a6cSmrg return 1; 94074b97a6cSmrg } 941b3307321Smrg } 942b3307321Smrg return 0; 943b3307321Smrg} 944b3307321Smrg 945b3307321Smrg 946b3307321Smrg/********************** from wsutils.c ******************************/ 947b3307321Smrg 948b3307321Smrg/****************************************************************************** 949b3307321Smrg * 950b3307321Smrg * This file contains a set of example utility procedures; procedures that can 951b3307321Smrg * help a "window-smart" Starbase or PHIGS program determine information about 952b3307321Smrg * a device, and create image and overlay plane windows. To use these 953b3307321Smrg * utilities, #include "wsutils.h" and compile this file and link the results 954b3307321Smrg * with your program. 955b3307321Smrg * 956b3307321Smrg ******************************************************************************/ 957b3307321Smrg 958b3307321Smrg 95974b97a6cSmrgstatic int weCreateServerOverlayVisualsProperty = False; 960b3307321Smrg 961b3307321Smrg 962b3307321Smrg/****************************************************************************** 963b3307321Smrg * 964b3307321Smrg * GetXVisualInfo() 965b3307321Smrg * 966b3307321Smrg * This routine takes an X11 Display, screen number, and returns whether the 967b3307321Smrg * screen supports transparent overlays and three arrays: 968b3307321Smrg * 969b3307321Smrg * 1) All of the XVisualInfo struct's for the screen. 970b3307321Smrg * 2) All of the OverlayInfo struct's for the screen. 971b3307321Smrg * 3) An array of pointers to the screen's image plane XVisualInfo 972b3307321Smrg * structs. 973b3307321Smrg * 974b3307321Smrg * The code below obtains the array of all the screen's visuals, and obtains 975b3307321Smrg * the array of all the screen's overlay visual information. It then processes 976b3307321Smrg * the array of the screen's visuals, determining whether the visual is an 977b3307321Smrg * overlay or image visual. 978b3307321Smrg * 9796728f30eSmrg * If the routine successfully obtained the visual information, it returns zero. 980b3307321Smrg * If the routine didn't obtain the visual information, it returns non-zero. 981b3307321Smrg * 982b3307321Smrg ******************************************************************************/ 983b3307321Smrg 98474b97a6cSmrgint 98574b97a6cSmrgGetXVisualInfo( /* Which X server (aka "display"). */ 98674b97a6cSmrg Display *display, 98774b97a6cSmrg /* Which screen of the "display". */ 98874b97a6cSmrg int screen, 98974b97a6cSmrg /* Non-zero if there's at least one overlay visual and 99074b97a6cSmrg * if at least one of those supports a transparent pixel. */ 99174b97a6cSmrg int *transparentOverlays, 99274b97a6cSmrg /* Number of XVisualInfo struct's pointed to by pVisuals. */ 99374b97a6cSmrg int *numVisuals, 99474b97a6cSmrg /* All of the device's visuals. */ 99574b97a6cSmrg XVisualInfo **pVisuals, 99674b97a6cSmrg /* Number of OverlayInfo's pointed to by pOverlayVisuals. 99774b97a6cSmrg * If this number is zero, the device does not have 99874b97a6cSmrg * overlay planes. */ 99974b97a6cSmrg int *numOverlayVisuals, 100074b97a6cSmrg /* The device's overlay plane visual information. */ 100174b97a6cSmrg OverlayInfo **pOverlayVisuals, 100274b97a6cSmrg /* Number of XVisualInfo's pointed to by pImageVisuals. */ 100374b97a6cSmrg int *numImageVisuals, 100474b97a6cSmrg /* The device's image visuals. */ 100574b97a6cSmrg XVisualInfo ***pImageVisuals) 1006b3307321Smrg{ 100774b97a6cSmrg XVisualInfo getVisInfo; /* Parameters of XGetVisualInfo */ 100874b97a6cSmrg int mask; 100974b97a6cSmrg XVisualInfo *pVis, **pIVis; /* Faster, local copies */ 101074b97a6cSmrg OverlayVisualPropertyRec *pOOldVis; 10116728f30eSmrg int nVisuals; 101274b97a6cSmrg Atom overlayVisualsAtom; /* Parameters for XGetWindowProperty */ 101374b97a6cSmrg Atom actualType; 1014b3307321Smrg unsigned long numLongs, bytesAfter; 101574b97a6cSmrg int actualFormat; 101674b97a6cSmrg int nImageVisualsAlloced; /* Values to process the XVisualInfo */ 1017b3307321Smrg 1018b3307321Smrg /* First, get the list of visuals for this screen. */ 1019b3307321Smrg getVisInfo.screen = screen; 102074a3f230Smrg mask = VisualScreenMask; 1021b3307321Smrg 1022b3307321Smrg *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals); 102374b97a6cSmrg if ((nVisuals = *numVisuals) <= 0) { 10246728f30eSmrg /* Return that the information wasn't successfully obtained: */ 102574b97a6cSmrg return (1); 1026b3307321Smrg } 1027b3307321Smrg pVis = *pVisuals; 1028b3307321Smrg 1029b3307321Smrg /* Now, get the overlay visual information for this screen. To obtain 1030b3307321Smrg * this information, get the SERVER_OVERLAY_VISUALS property. 1031b3307321Smrg */ 1032b3307321Smrg overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True); 103374b97a6cSmrg if (overlayVisualsAtom != None) { 103474b97a6cSmrg /* Since the Atom exists, we can request the property's contents. The 103574b97a6cSmrg * do-while loop makes sure we get the entire list from the X server. 103674b97a6cSmrg */ 103774b97a6cSmrg bytesAfter = 0; 103874b97a6cSmrg numLongs = sizeof(OverlayVisualPropertyRec) / sizeof(long); 103974b97a6cSmrg do { 104074b97a6cSmrg numLongs += bytesAfter * sizeof(long); 104174b97a6cSmrg XGetWindowProperty(display, RootWindow(display, screen), 104274b97a6cSmrg overlayVisualsAtom, 0, numLongs, False, 104374b97a6cSmrg overlayVisualsAtom, &actualType, &actualFormat, 104474b97a6cSmrg &numLongs, &bytesAfter, 104574b97a6cSmrg (unsigned char **) pOverlayVisuals); 104674b97a6cSmrg } while (bytesAfter > 0); 104774b97a6cSmrg 104874b97a6cSmrg /* Calculate the number of overlay visuals in the list. */ 104974b97a6cSmrg *numOverlayVisuals = 105074b97a6cSmrg numLongs / (sizeof(OverlayVisualPropertyRec) / sizeof(long)); 1051b3307321Smrg } 105274b97a6cSmrg else { 105374b97a6cSmrg /* This screen doesn't have overlay planes. */ 105474b97a6cSmrg *numOverlayVisuals = 0; 105574b97a6cSmrg *pOverlayVisuals = NULL; 105674b97a6cSmrg *transparentOverlays = 0; 1057b3307321Smrg } 1058b3307321Smrg 1059b3307321Smrg /* Process the pVisuals array. */ 1060b3307321Smrg *numImageVisuals = 0; 1061b3307321Smrg nImageVisualsAlloced = 1; 10626728f30eSmrg pIVis = *pImageVisuals = malloc(sizeof(XVisualInfo *)); 106374b97a6cSmrg while (--nVisuals >= 0) { 10646728f30eSmrg int nOVisuals = *numOverlayVisuals; 10656728f30eSmrg OverlayInfo *pOVis = *pOverlayVisuals; 10666728f30eSmrg int imageVisual = True; 10676728f30eSmrg 106874b97a6cSmrg while (--nOVisuals >= 0) { 106974b97a6cSmrg pOOldVis = (OverlayVisualPropertyRec *) pOVis; 107074b97a6cSmrg if (pVis->visualid == pOOldVis->visualID) { 107174b97a6cSmrg imageVisual = False; 107274b97a6cSmrg pOVis->pOverlayVisualInfo = pVis; 107374b97a6cSmrg if (pOVis->transparentType == TransparentPixel) 107474b97a6cSmrg *transparentOverlays = 1; 107574b97a6cSmrg } 107674b97a6cSmrg pOVis++; 107774b97a6cSmrg } 107874b97a6cSmrg if (imageVisual) { 107974b97a6cSmrg if ((*numImageVisuals += 1) > nImageVisualsAlloced) { 108074b97a6cSmrg nImageVisualsAlloced++; 108174b97a6cSmrg *pImageVisuals = (XVisualInfo **) 108274b97a6cSmrg realloc(*pImageVisuals, 108374b97a6cSmrg (nImageVisualsAlloced * sizeof(XVisualInfo *))); 108474b97a6cSmrg pIVis = *pImageVisuals + (*numImageVisuals - 1); 108574b97a6cSmrg } 108674b97a6cSmrg *pIVis++ = pVis; 108774b97a6cSmrg } 108874b97a6cSmrg pVis++; 1089b3307321Smrg } 1090b3307321Smrg 10916728f30eSmrg /* Return that the information was successfully obtained: */ 109274b97a6cSmrg return (0); 1093b3307321Smrg 109474b97a6cSmrg} /* GetXVisualInfo() */ 1095b3307321Smrg 1096b3307321Smrg/****************************************************************************** 1097b3307321Smrg * 1098b3307321Smrg * FreeXVisualInfo() 1099b3307321Smrg * 1100b3307321Smrg * This routine frees the data that was allocated by GetXVisualInfo(). 1101b3307321Smrg * 1102b3307321Smrg ******************************************************************************/ 1103b3307321Smrg 110474b97a6cSmrgvoid 110574b97a6cSmrgFreeXVisualInfo(XVisualInfo *pVisuals, OverlayInfo *pOverlayVisuals, 110674b97a6cSmrg XVisualInfo **pImageVisuals) 1107b3307321Smrg{ 1108b3307321Smrg XFree(pVisuals); 1109b3307321Smrg if (weCreateServerOverlayVisualsProperty) 111074b97a6cSmrg free(pOverlayVisuals); 1111b3307321Smrg else 111274b97a6cSmrg XFree(pOverlayVisuals); 1113b3307321Smrg free(pImageVisuals); 1114b3307321Smrg 111574b97a6cSmrg} /* FreeXVisualInfo() */ 1116