multiVis.c revision 5e358eca
1b3307321Smrg/* $Xorg: multiVis.c,v 1.5 2001/02/09 02:06:03 xorgcvs Exp $ */ 2b3307321Smrg/** ------------------------------------------------------------------------ 3b3307321Smrg This file contains functions to create a list of regions which 4b3307321Smrg tile a specified window. Each region contains all visible 5b3307321Smrg portions of the window which are drawn with the same visual. 6b3307321Smrg If the window consists of subwindows of two different visual types, 7b3307321Smrg there will be two regions in the list. The list can be traversed 8b3307321Smrg to correctly pull an image of the window using XGetImage or the 9b3307321Smrg Image Library. 10b3307321Smrg 11b3307321SmrgCopyright 1994 Hewlett-Packard Co. 12b3307321SmrgCopyright 1996, 1998 The Open Group 13b3307321Smrg 14b3307321SmrgPermission to use, copy, modify, distribute, and sell this software and its 15b3307321Smrgdocumentation for any purpose is hereby granted without fee, provided that 16b3307321Smrgthe above copyright notice appear in all copies and that both that 17b3307321Smrgcopyright notice and this permission notice appear in supporting 18b3307321Smrgdocumentation. 19b3307321Smrg 20b3307321SmrgThe above copyright notice and this permission notice shall be included 21b3307321Smrgin all copies or substantial portions of the Software. 22b3307321Smrg 23b3307321SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24b3307321SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25b3307321SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26b3307321SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 27b3307321SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 28b3307321SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 29b3307321SmrgOTHER DEALINGS IN THE SOFTWARE. 30b3307321Smrg 31b3307321SmrgExcept as contained in this notice, the name of The Open Group shall 32b3307321Smrgnot be used in advertising or otherwise to promote the sale, use or 33b3307321Smrgother dealings in this Software without prior written authorization 34b3307321Smrgfrom The Open Group. 35b3307321Smrg 36b3307321Smrg ------------------------------------------------------------------------ **/ 37b3307321Smrg/* $XFree86: xc/programs/xwd/multiVis.c,v 1.9 2003/05/27 22:27:14 tsi Exp $ */ 38b3307321Smrg 39b3307321Smrg#include <stdlib.h> 40b3307321Smrg#include <X11/Xlib.h> 41b3307321Smrg#include <X11/Xutil.h> 42b3307321Smrg#include <X11/X.h> 43b3307321Smrg#include <stdio.h> 44b3307321Smrg#include "list.h" 45b3307321Smrg#include "wsutils.h" 46b3307321Smrg#include "multiVis.h" 47b3307321Smrg/* These structures are copied from X11/region.h. For some reason 48b3307321Smrg * they're invisible from the outside. 49b3307321Smrg */ 50b3307321Smrgtypedef struct { 51b3307321Smrg short x1, x2, y1, y2; 52b3307321Smrg} myBox, myBOX, myBoxRec, *myBoxPtr; 53b3307321Smrg 54b3307321Smrgtypedef struct my_XRegion { 55b3307321Smrg long size; 56b3307321Smrg long numRects; 57b3307321Smrg myBOX *rects; 58b3307321Smrg myBOX extents; 59b3307321Smrg} myREGION; 60b3307321Smrg 61b3307321Smrg/* Items in long list of windows that have some part in the grabbed area */ 62b3307321Smrgtypedef struct { 63b3307321Smrg Window win; 64b3307321Smrg Visual *vis; 65b3307321Smrg Colormap cmap; 66b3307321Smrg int x_rootrel, y_rootrel; /* root relative location of window */ 67b3307321Smrg int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */ 68b3307321Smrg int width, height; /* width and height of visible part */ 69b3307321Smrg int border_width; /* border width of the window */ 70b3307321Smrg Window parent; /* id of parent (for debugging) */ 71b3307321Smrg} image_win_type; 72b3307321Smrg 73b3307321Smrg/* Items in short list of regions that tile the grabbed area. May have 74b3307321Smrg multiple windows in the region. 75b3307321Smrg*/ 76b3307321Smrgtypedef struct { 77b3307321Smrg Window win; /* lowest window of this visual */ 78b3307321Smrg Visual *vis; 79b3307321Smrg Colormap cmap; 80b3307321Smrg int x_rootrel, y_rootrel; /* root relative location of bottom window */ 81b3307321Smrg int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */ 82b3307321Smrg int width, height; /* w & h of visible rect of bottom window */ 83b3307321Smrg int border; /* border width of the window */ 84b3307321Smrg Region visible_region; 85b3307321Smrg} image_region_type; 86b3307321Smrg 87b3307321Smrg/** ------------------------------------------------------------------------ 88b3307321Smrg Returns TRUE if the two structs pointed to have the same "vis" & 89b3307321Smrg "cmap" fields and s2 lies completely within s1. s1 and s2 can 90b3307321Smrg point to structs of image_win_type or image_region_type. 91b3307321Smrg ------------------------------------------------------------------------ **/ 92b3307321Smrg#define SAME_REGIONS( s1, s2) \ 93b3307321Smrg ((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap && \ 94b3307321Smrg (s1)->x_vis <= (s2)->x_vis && \ 95b3307321Smrg (s1)->y_vis <= (s2)->y_vis && \ 96b3307321Smrg (s1)->x_vis + (s1)->width >= (s2)->x_vis + (s2)->width && \ 97b3307321Smrg (s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height) 98b3307321Smrg 99b3307321Smrg#ifndef MIN 100b3307321Smrg#define MIN( a, b) ((a) < (b) ? a : b) 101b3307321Smrg#define MAX( a, b) ((a) > (b) ? a : b) 102b3307321Smrg#endif 103b3307321Smrg 104b3307321Smrg#define RED_SHIFT 16 105b3307321Smrg#define GREEN_SHIFT 8 106b3307321Smrg#define BLUE_SHIFT 0 107b3307321Smrg 108b3307321Smrg/* 109b3307321Smrgextern list_ptr new_list(); 110b3307321Smrgextern list_ptr dup_list_head(); 111b3307321Smrgextern void * first_in_list(); 112b3307321Smrgextern void * next_in_list(); 113b3307321Smrgextern int add_to_list(); 114b3307321Smrgextern void zero_list(); 115b3307321Smrgextern void delete_list(); 116b3307321Smrgextern void delete_list_destroying(); 117b3307321Smrgextern unsigned int list_length(); 118b3307321Smrg*/ 119b3307321Smrg 120b3307321Smrg/* Prototype Declarations for Static Functions */ 121b3307321Smrgstatic int QueryColorMap( 122b3307321Smrg Display *, Colormap , Visual *, 123b3307321Smrg XColor **, int *, int *, int * 124b3307321Smrg ); 125b3307321Smrgstatic void TransferImage( 126b3307321Smrg Display *, XImage *,int, int , image_region_type*, 127b3307321Smrg XImage *,int ,int 128b3307321Smrg ); 129b3307321Smrgstatic XImage * ReadRegionsInList( 130b3307321Smrg Display *, Visual *, int ,int ,int , 131b3307321Smrg int , XRectangle, list_ptr 132b3307321Smrg ); 133b3307321Smrg 134b3307321Smrgstatic list_ptr make_region_list( 135b3307321Smrg Display*, Window, XRectangle*, 136b3307321Smrg int*, int, XVisualInfo**, int * 137b3307321Smrg ); 138b3307321Smrg 139b3307321Smrgstatic void destroy_region_list( 140b3307321Smrg list_ptr 141b3307321Smrg ) ; 142b3307321Smrgstatic void subtr_rect_from_image_region( 143b3307321Smrg image_region_type *, int , int , int , int 144b3307321Smrg ); 145b3307321Smrgstatic void add_rect_to_image_region( 146b3307321Smrg image_region_type *, 147b3307321Smrg int , int , int , int 148b3307321Smrg ); 149b3307321Smrgstatic int src_in_region_list( 150b3307321Smrg image_win_type *, list_ptr 151b3307321Smrg ); 152b3307321Smrgstatic void add_window_to_list( 153b3307321Smrg list_ptr, Window, int, int , 154b3307321Smrg int , int , int , int, int, 155b3307321Smrg Visual*, Colormap, Window 156b3307321Smrg ); 157b3307321Smrgstatic int src_in_image( 158b3307321Smrg image_win_type *, int , XVisualInfo** 159b3307321Smrg ); 160b3307321Smrgstatic int src_in_overlay( 161b3307321Smrg image_region_type *, int, OverlayInfo *, int*, int* 162b3307321Smrg ); 163b3307321Smrgstatic void make_src_list( 164b3307321Smrg Display *, list_ptr, XRectangle *, Window, 165b3307321Smrg int, int, XWindowAttributes *, XRectangle * 166b3307321Smrg); 167b3307321Smrgstatic void destroy_image_region( 168b3307321Smrg image_region_type * 169b3307321Smrg); 170b3307321Smrg 171b3307321Smrg/* End of Prototype Declarations */ 172b3307321Smrg 1735e358ecaSmrgvoid initFakeVisual(Visual *Vis) 174b3307321Smrg{ 175b3307321Smrg Vis->ext_data=NULL; 176b3307321Smrg Vis->class = DirectColor ; 177b3307321Smrg Vis->red_mask = 0x00FF0000; 178b3307321Smrg Vis->green_mask = 0x0000FF00 ; 179b3307321Smrg Vis->blue_mask = 0x000000FF ; 180b3307321Smrg Vis->map_entries = 256 ; 181b3307321Smrg Vis->bits_per_rgb = 8 ; 182b3307321Smrg} 183b3307321Smrg 184b3307321Smrgstatic int 1855e358ecaSmrgQueryColorMap(Display *disp, Colormap src_cmap, Visual *src_vis, 1865e358ecaSmrg XColor **src_colors, int *rShift, int *gShift, int *bShift) 187b3307321Smrg{ 188b3307321Smrg int ncolors,i ; 189b3307321Smrg unsigned long redMask, greenMask, blueMask; 190b3307321Smrg int redShift, greenShift, blueShift; 191b3307321Smrg XColor *colors ; 192b3307321Smrg 193b3307321Smrg ncolors = src_vis->map_entries ; 194b3307321Smrg *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ; 195b3307321Smrg 196b3307321Smrg if(src_vis->class != TrueColor && src_vis->class != DirectColor) 197b3307321Smrg { 198b3307321Smrg for(i=0 ; i < ncolors ; i++) 199b3307321Smrg { 200b3307321Smrg colors[i].pixel = i ; 201b3307321Smrg colors[i].pad = 0; 202b3307321Smrg colors[i].flags = DoRed|DoGreen|DoBlue; 203b3307321Smrg } 204b3307321Smrg } 205b3307321Smrg else /** src is decomposed rgb ***/ 206b3307321Smrg { 207b3307321Smrg /* Get the X colormap */ 208b3307321Smrg redMask = src_vis->red_mask; 209b3307321Smrg greenMask = src_vis->green_mask; 210b3307321Smrg blueMask = src_vis->blue_mask; 211b3307321Smrg redShift = 0; while (!(redMask&0x1)) { 212b3307321Smrg redShift++; 213b3307321Smrg redMask = redMask>>1; 214b3307321Smrg } 215b3307321Smrg greenShift = 0; while (!(greenMask&0x1)) { 216b3307321Smrg greenShift++; 217b3307321Smrg greenMask = greenMask>>1; 218b3307321Smrg } 219b3307321Smrg blueShift = 0; while (!(blueMask&0x1)) { 220b3307321Smrg blueShift++; 221b3307321Smrg blueMask = blueMask>>1; 222b3307321Smrg } 223b3307321Smrg *rShift = redShift ; 224b3307321Smrg *gShift = greenShift ; 225b3307321Smrg *bShift = blueShift ; 226b3307321Smrg for (i=0; i<ncolors; i++) { 227b3307321Smrg if( i <= redMask)colors[i].pixel = (i<<redShift) ; 228b3307321Smrg if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ; 229b3307321Smrg if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ; 230b3307321Smrg /***** example :for gecko's 3-3-2 map, blue index should be <= 3. 231b3307321Smrg colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift); 232b3307321Smrg *****/ 233b3307321Smrg colors[i].pad = 0; 234b3307321Smrg colors[i].flags = DoRed|DoGreen|DoBlue; 235b3307321Smrg } 236b3307321Smrg } 237b3307321Smrg 238b3307321Smrg 239b3307321Smrg XQueryColors(disp, src_cmap, colors, ncolors); 240b3307321Smrg return ncolors ; 241b3307321Smrg} 242b3307321Smrg 243b3307321Smrgint 2445e358ecaSmrgGetMultiVisualRegions(Display *disp, 2455e358ecaSmrg /* root win on which grab was done */ 2465e358ecaSmrg Window srcRootWinid, 2475e358ecaSmrg /* root rel UL corner of bounding box of grab */ 2485e358ecaSmrg int x, int y, 2495e358ecaSmrg /* size of bounding box of grab */ 2505e358ecaSmrg unsigned int width, unsigned int height, 2515e358ecaSmrg int *transparentOverlays, int *numVisuals, 2525e358ecaSmrg XVisualInfo **pVisuals, int *numOverlayVisuals, 2535e358ecaSmrg OverlayInfo **pOverlayVisuals, 2545e358ecaSmrg int *numImageVisuals, XVisualInfo ***pImageVisuals, 2555e358ecaSmrg /* list of regions to read from */ 2565e358ecaSmrg list_ptr *vis_regions, 2575e358ecaSmrg list_ptr *vis_image_regions, int *allImage) 258b3307321Smrg{ 259b3307321Smrg int hasNonDefault; 260b3307321Smrg XRectangle bbox; /* bounding box of grabbed area */ 261b3307321Smrg 262b3307321Smrg 263b3307321Smrg bbox.x = x; /* init X rect for bounding box */ 264b3307321Smrg bbox.y = y; 265b3307321Smrg bbox.width = width; 266b3307321Smrg bbox.height = height; 267b3307321Smrg 268b3307321Smrg GetXVisualInfo(disp,DefaultScreen(disp), 269b3307321Smrg transparentOverlays, 270b3307321Smrg numVisuals, pVisuals, 271b3307321Smrg numOverlayVisuals, pOverlayVisuals, 272b3307321Smrg numImageVisuals, pImageVisuals); 273b3307321Smrg 274b3307321Smrg *vis_regions = *vis_image_regions = NULL ; 275b3307321Smrg if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox, 276b3307321Smrg &hasNonDefault, *numImageVisuals, 277b3307321Smrg *pImageVisuals, allImage)) == NULL) 278b3307321Smrg return 0 ; 279b3307321Smrg 280b3307321Smrg if (*transparentOverlays) 281b3307321Smrg { 282b3307321Smrg *allImage = 1; /* until proven otherwise, 283b3307321Smrg this flags that it to be an image only list */ 284b3307321Smrg *vis_image_regions = 285b3307321Smrg make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault, 286b3307321Smrg *numImageVisuals, *pImageVisuals, allImage); 287b3307321Smrg } 288b3307321Smrg 289b3307321Smrg /* if there is a second region in any of the two lists return 1 **/ 290b3307321Smrg if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) || 291b3307321Smrg ( *vis_image_regions && (*vis_image_regions)->next && 292b3307321Smrg (*vis_image_regions)->next->next ) ) return 1 ; 293b3307321Smrg else return 0 ; 294b3307321Smrg 295b3307321Smrg} 296b3307321Smrg 2975e358ecaSmrgstatic void TransferImage(Display *disp, XImage *reg_image, 2985e358ecaSmrg int srcw, int srch, 2995e358ecaSmrg image_region_type *reg, XImage *target_image, 3005e358ecaSmrg int dst_x, int dst_y) 301b3307321Smrg{ 302b3307321Smrg int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ; 303b3307321Smrg XColor *colors; 304b3307321Smrg int rShift,gShift,bShift; 305b3307321Smrg 306b3307321Smrg (void) QueryColorMap(disp,reg->cmap,reg->vis,&colors, 307b3307321Smrg &rShift,&gShift,&bShift) ; 308b3307321Smrg 309b3307321Smrg switch (reg->vis->class) { 310b3307321Smrg case TrueColor : 311b3307321Smrg for(i=0 ; i < srch ; i++) 312b3307321Smrg { 313b3307321Smrg for(j=0 ; j < srcw ; j++) 314b3307321Smrg { 315b3307321Smrg old_pixel = XGetPixel(reg_image,j,i) ; 316b3307321Smrg 317b3307321Smrg if( reg->vis->map_entries == 16) { 318b3307321Smrg 319b3307321Smrg red_ind = (old_pixel & reg->vis->red_mask) >> rShift ; 320b3307321Smrg green_ind = (old_pixel & reg->vis->green_mask) >> gShift ; 321b3307321Smrg blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ; 322b3307321Smrg 323b3307321Smrg new_pixel = ( 324b3307321Smrg ((colors[red_ind].red >> 8) << RED_SHIFT) 325b3307321Smrg |((colors[green_ind].green >> 8) << GREEN_SHIFT) 326b3307321Smrg |((colors[blue_ind].blue >> 8) << BLUE_SHIFT) 327b3307321Smrg ); 328b3307321Smrg } 329b3307321Smrg else 330b3307321Smrg new_pixel = old_pixel; 331b3307321Smrg 332b3307321Smrg XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel); 333b3307321Smrg 334b3307321Smrg } 335b3307321Smrg } 336b3307321Smrg break; 337b3307321Smrg case DirectColor : 338b3307321Smrg for(i=0 ; i < srch ; i++) 339b3307321Smrg { 340b3307321Smrg 341b3307321Smrg for(j=0 ; j < srcw ; j++) 342b3307321Smrg { 343b3307321Smrg old_pixel = XGetPixel(reg_image,j,i) ; 344b3307321Smrg red_ind = (old_pixel & reg->vis->red_mask) >> rShift ; 345b3307321Smrg green_ind = (old_pixel & reg->vis->green_mask) >> gShift ; 346b3307321Smrg blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ; 347b3307321Smrg 348b3307321Smrg new_pixel = ( 349b3307321Smrg ((colors[red_ind].red >> 8) << RED_SHIFT) 350b3307321Smrg |((colors[green_ind].green >> 8) << GREEN_SHIFT) 351b3307321Smrg |((colors[blue_ind].blue >> 8) << BLUE_SHIFT) 352b3307321Smrg ); 353b3307321Smrg XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel); 354b3307321Smrg 355b3307321Smrg } 356b3307321Smrg } 357b3307321Smrg break; 358b3307321Smrg default : 359b3307321Smrg for(i=0 ; i < srch ; i++) 360b3307321Smrg { 361b3307321Smrg for(j=0 ; j < srcw ; j++) 362b3307321Smrg { 363b3307321Smrg old_pixel = XGetPixel(reg_image,j,i) ; 364b3307321Smrg 365b3307321Smrg new_pixel = ( 366b3307321Smrg ((colors[old_pixel].red >> 8) << RED_SHIFT) 367b3307321Smrg |((colors[old_pixel].green >> 8) << GREEN_SHIFT) 368b3307321Smrg |((colors[old_pixel].blue >> 8) << BLUE_SHIFT) 369b3307321Smrg ); 370b3307321Smrg XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel); 371b3307321Smrg 372b3307321Smrg } 373b3307321Smrg } 374b3307321Smrg break; 375b3307321Smrg } 376b3307321Smrg} 377b3307321Smrg 378b3307321Smrgstatic XImage * 3795e358ecaSmrgReadRegionsInList(Display *disp, Visual *fakeVis, int depth, int format, 3805e358ecaSmrg int width,int height, 3815e358ecaSmrg XRectangle bbox, /* bounding box of grabbed area */ 3825e358ecaSmrg list_ptr regions) /* list of regions to read from */ 383b3307321Smrg{ 384b3307321Smrg image_region_type *reg; 385b3307321Smrg int dst_x, dst_y; /* where in pixmap to write (UL) */ 386b3307321Smrg int diff; 387b3307321Smrg 388b3307321Smrg XImage *reg_image,*ximage ; 389b3307321Smrg int srcRect_x,srcRect_y,srcRect_width,srcRect_height ; 390b3307321Smrg int rem ; 391b3307321Smrg int bytes_per_line; 392b3307321Smrg int bitmap_unit; 393b3307321Smrg 394b3307321Smrg bitmap_unit = sizeof (long); 395b3307321Smrg if (format == ZPixmap) 396b3307321Smrg bytes_per_line = width*depth/8; 397b3307321Smrg else 398b3307321Smrg bytes_per_line = width/8; 399b3307321Smrg 400b3307321Smrg 401b3307321Smrg /* Find out how many more bytes are required for padding so that 402b3307321Smrg ** bytes per scan line will be multiples of bitmap_unit bits */ 403b3307321Smrg if (format == ZPixmap) { 404b3307321Smrg rem = (bytes_per_line*8)%bitmap_unit; 405b3307321Smrg if (rem) 406b3307321Smrg bytes_per_line += (rem/8 + 1); 407b3307321Smrg } 408b3307321Smrg 409b3307321Smrg ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height, 410b3307321Smrg 8,0) ; 411b3307321Smrg bytes_per_line = ximage->bytes_per_line; 412b3307321Smrg 413b3307321Smrg if (format == ZPixmap) 414b3307321Smrg ximage->data = malloc(height*bytes_per_line); 415b3307321Smrg else 416b3307321Smrg ximage->data = malloc(height*bytes_per_line*depth); 417b3307321Smrg 418b3307321Smrg ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/ 419b3307321Smrg 420b3307321Smrg for (reg = (image_region_type *) first_in_list( regions); reg; 421b3307321Smrg reg = (image_region_type *) next_in_list( regions)) 422b3307321Smrg { 423b3307321Smrg int rect; 424b3307321Smrg struct my_XRegion *vis_reg; 425b3307321Smrg vis_reg = (struct my_XRegion *)(reg->visible_region); 426b3307321Smrg for (rect = 0; 427b3307321Smrg rect < vis_reg->numRects; 428b3307321Smrg rect++) 429b3307321Smrg { 430b3307321Smrg /** ------------------------------------------------------------------------ 431b3307321Smrg Intersect bbox with visible part of region giving src rect & output 432b3307321Smrg location. Width is the min right side minus the max left side. 433b3307321Smrg Similar for height. Offset src rect so x,y are relative to 434b3307321Smrg origin of win, not the root-relative visible rect of win. 435b3307321Smrg ------------------------------------------------------------------------ **/ 436b3307321Smrg srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) - 437b3307321Smrg MAX( vis_reg->rects[rect].x1, bbox.x); 438b3307321Smrg srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) - 439b3307321Smrg MAX( vis_reg->rects[rect].y1, bbox.y); 440b3307321Smrg diff = bbox.x - vis_reg->rects[rect].x1; 441b3307321Smrg srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border); 442b3307321Smrg dst_x = MAX( 0, -diff) ; 443b3307321Smrg diff = bbox.y - vis_reg->rects[rect].y1; 444b3307321Smrg srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border); 445b3307321Smrg dst_y = MAX( 0, -diff) ; 446b3307321Smrg reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y, 447b3307321Smrg srcRect_width,srcRect_height,AllPlanes,format) ; 448b3307321Smrg TransferImage(disp,reg_image,srcRect_width, 449b3307321Smrg srcRect_height,reg,ximage,dst_x,dst_y) ; 450b3307321Smrg } 451b3307321Smrg } 452b3307321Smrg return ximage ; 453b3307321Smrg} 454b3307321Smrg 455b3307321Smrg 456b3307321Smrg/** ------------------------------------------------------------------------ 457b3307321Smrg ------------------------------------------------------------------------ **/ 458b3307321Smrg 4595e358ecaSmrgXImage *ReadAreaToImage(Display *disp, 4605e358ecaSmrg /* root win on which grab was done */ 4615e358ecaSmrg Window srcRootWinid, 4625e358ecaSmrg /* root rel UL corner of bounding box of grab */ 4635e358ecaSmrg int x, int y, 4645e358ecaSmrg /* size of bounding box of grab */ 4655e358ecaSmrg unsigned int width, unsigned int height, 4665e358ecaSmrg int numVisuals, XVisualInfo *pVisuals, 4675e358ecaSmrg int numOverlayVisuals, OverlayInfo *pOverlayVisuals, 4685e358ecaSmrg int numImageVisuals, XVisualInfo **pImageVisuals, 4695e358ecaSmrg /* list of regions to read from */ 4705e358ecaSmrg list_ptr vis_regions, 4715e358ecaSmrg /* list of regions to read from */ 4725e358ecaSmrg list_ptr vis_image_regions, 4735e358ecaSmrg int format, int allImage) 474b3307321Smrg{ 475b3307321Smrg image_region_type *reg; 476b3307321Smrg XRectangle bbox; /* bounding box of grabbed area */ 477b3307321Smrg int depth ; 478b3307321Smrg XImage *ximage, *ximage_ipm = NULL; 479b3307321Smrg Visual fakeVis ; 480b3307321Smrg int x1, y1; 481b3307321Smrg XImage *image; 482b3307321Smrg#if 0 483b3307321Smrg unsigned char *pmData , *ipmData ; 484b3307321Smrg#endif 485b3307321Smrg int transparentColor, transparentType; 486b3307321Smrg int srcRect_x,srcRect_y,srcRect_width,srcRect_height ; 487b3307321Smrg int diff ; 488b3307321Smrg int dst_x, dst_y; /* where in pixmap to write (UL) */ 489b3307321Smrg int pixel; 490b3307321Smrg 491b3307321Smrg bbox.x = x; /* init X rect for bounding box */ 492b3307321Smrg bbox.y = y; 493b3307321Smrg bbox.width = width; 494b3307321Smrg bbox.height = height; 495b3307321Smrg 496b3307321Smrg 497b3307321Smrg initFakeVisual(&fakeVis) ; 498b3307321Smrg 499b3307321Smrg depth = 24 ; 500b3307321Smrg ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height, 501b3307321Smrg bbox,vis_regions) ; 502b3307321Smrg#if 0 503b3307321Smrg pmData = (unsigned char *)ximage -> data ; 504b3307321Smrg#endif 505b3307321Smrg 506b3307321Smrg/* if transparency possible do it again, but this time for image planes only */ 507b3307321Smrg if (vis_image_regions && (vis_image_regions->next) && !allImage) 508b3307321Smrg { 509b3307321Smrg ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height, 510b3307321Smrg bbox,vis_image_regions) ; 511b3307321Smrg#if 0 512b3307321Smrg ipmData = (unsigned char *)ximage_ipm -> data ; 513b3307321Smrg#endif 514b3307321Smrg } 515b3307321Smrg/* Now tranverse the overlay visual windows and test for transparency index. */ 516b3307321Smrg/* If you find one, subsitute the value from the matching image plane pixmap. */ 517b3307321Smrg 518b3307321Smrg for (reg = (image_region_type *) first_in_list( vis_regions); reg; 519b3307321Smrg reg = (image_region_type *) next_in_list( vis_regions)) 520b3307321Smrg { 521b3307321Smrg 522b3307321Smrg if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals, 523b3307321Smrg &transparentColor, &transparentType)) 524b3307321Smrg { 525b3307321Smrg int test = 0 ; 526b3307321Smrg srcRect_width = MIN( reg->width + reg->x_vis, bbox.width + bbox.x) 527b3307321Smrg - MAX( reg->x_vis, bbox.x); 528b3307321Smrg srcRect_height = MIN( reg->height + reg->y_vis, bbox.height 529b3307321Smrg + bbox.y) - MAX( reg->y_vis, bbox.y); 530b3307321Smrg diff = bbox.x - reg->x_vis; 531b3307321Smrg srcRect_x = MAX( 0, diff) + (reg->x_vis - reg->x_rootrel - reg->border); 532b3307321Smrg dst_x = MAX( 0, -diff) ; 533b3307321Smrg diff = bbox.y - reg->y_vis; 534b3307321Smrg srcRect_y = MAX( 0, diff) + (reg->y_vis - reg->y_rootrel - reg->border); 535b3307321Smrg dst_y = MAX( 0, -diff) ; 536b3307321Smrg /* let's test some pixels for transparency */ 537b3307321Smrg image = XGetImage(disp, reg->win, srcRect_x, srcRect_y, 538b3307321Smrg srcRect_width, srcRect_height, 0xffffffff, ZPixmap); 539b3307321Smrg 540b3307321Smrg /* let's assume byte per pixel for overlay image for now */ 541b3307321Smrg if ((image->depth == 8) && (transparentType == TransparentPixel)) 542b3307321Smrg { 543b3307321Smrg unsigned char *pixel_ptr; 544b3307321Smrg unsigned char *start_of_line = (unsigned char *) image->data; 545b3307321Smrg 546b3307321Smrg for (y1 = 0; y1 < srcRect_height; y1++) { 547b3307321Smrg pixel_ptr = start_of_line; 548b3307321Smrg for (x1 = 0; x1 < srcRect_width; x1++) 549b3307321Smrg { 550b3307321Smrg if (*pixel_ptr++ == transparentColor) 551b3307321Smrg { 552b3307321Smrg#if 0 553b3307321Smrg *pmData++ = *ipmData++; 554b3307321Smrg *pmData++ = *ipmData++; 555b3307321Smrg *pmData++ = *ipmData++; 556b3307321Smrg#endif 557b3307321Smrg pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ; 558b3307321Smrg XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel); 559b3307321Smrg 560b3307321Smrg if(!test){ 561b3307321Smrg test = 1 ; 562b3307321Smrg } 563b3307321Smrg } 564b3307321Smrg#if 0 565b3307321Smrg else { 566b3307321Smrg pmData +=3; 567b3307321Smrg ipmData +=3; 568b3307321Smrg } 569b3307321Smrg#endif 570b3307321Smrg } 571b3307321Smrg start_of_line += image->bytes_per_line; 572b3307321Smrg } 573b3307321Smrg } else { 574b3307321Smrg if (transparentType == TransparentPixel) { 575b3307321Smrg for (y1 = 0; y1 < srcRect_height; y1++) { 576b3307321Smrg for (x1 = 0; x1 < srcRect_width; x1++) 577b3307321Smrg { 578b3307321Smrg int pixel_value = XGetPixel(image, x1, y1); 579b3307321Smrg if (pixel_value == transparentColor) 580b3307321Smrg { 581b3307321Smrg#if 0 582b3307321Smrg *pmData++ = *ipmData++; 583b3307321Smrg *pmData++ = *ipmData++; 584b3307321Smrg *pmData++ = *ipmData++; 585b3307321Smrg#endif 586b3307321Smrg pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ; 587b3307321Smrg XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel); 588b3307321Smrg if(!test){ 589b3307321Smrg test = 1 ; 590b3307321Smrg } 591b3307321Smrg } 592b3307321Smrg#if 0 593b3307321Smrg else { 594b3307321Smrg pmData +=3; 595b3307321Smrg ipmData +=3; 596b3307321Smrg } 597b3307321Smrg#endif 598b3307321Smrg } 599b3307321Smrg } 600b3307321Smrg } else { 601b3307321Smrg for (y1 = 0; y1 < srcRect_height; y1++) { 602b3307321Smrg for (x1 = 0; x1 < srcRect_width; x1++) 603b3307321Smrg { 604b3307321Smrg int pixel_value = XGetPixel(image, x1, y1); 605b3307321Smrg if (pixel_value & transparentColor) 606b3307321Smrg { 607b3307321Smrg#if 0 608b3307321Smrg *pmData++ = *ipmData++; 609b3307321Smrg *pmData++ = *ipmData++; 610b3307321Smrg *pmData++ = *ipmData++; 611b3307321Smrg#endif 612b3307321Smrg pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ; 613b3307321Smrg XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel); 614b3307321Smrg if(!test){ 615b3307321Smrg test = 1 ; 616b3307321Smrg } 617b3307321Smrg } 618b3307321Smrg#if 0 619b3307321Smrg else { 620b3307321Smrg pmData +=3; 621b3307321Smrg ipmData +=3; 622b3307321Smrg } 623b3307321Smrg#endif 624b3307321Smrg } 625b3307321Smrg } 626b3307321Smrg } 627b3307321Smrg } 628b3307321Smrg XDestroyImage (image); 629b3307321Smrg } /* end of src_in_overlay */ 630b3307321Smrg } /** end transparency **/ 631b3307321Smrg destroy_region_list( vis_regions); 632b3307321Smrg if (vis_image_regions) destroy_region_list( vis_image_regions ); 633b3307321Smrg FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals); 634b3307321Smrg XSync(disp, 0); 635b3307321Smrg 636b3307321Smrg return ximage; 637b3307321Smrg} 638b3307321Smrg 639b3307321Smrg/** ------------------------------------------------------------------------ 640b3307321Smrg Creates a list of the subwindows of a given window which have a 641b3307321Smrg different visual than their parents. The function is recursive. 642b3307321Smrg This list is used in make_region_list(), which coalesces the 643b3307321Smrg windows with the same visual into a region. 644b3307321Smrg image_wins must point to an existing list struct that's already 645b3307321Smrg been zeroed (zero_list()). 646b3307321Smrg ------------------------------------------------------------------------ **/ 6475e358ecaSmrgstatic void make_src_list(Display *disp, list_ptr image_wins, 6485e358ecaSmrg /* bnding box of area we want */ 6495e358ecaSmrg XRectangle *bbox, 6505e358ecaSmrg Window curr, 6515e358ecaSmrg /* pos of curr WRT root */ 6525e358ecaSmrg int x_rootrel, int y_rootrel, 6535e358ecaSmrg XWindowAttributes *curr_attrs, 6545e358ecaSmrg /* visible part of curr, not obscurred by ancestors */ 6555e358ecaSmrg XRectangle *pclip) 656b3307321Smrg{ 657b3307321Smrg XWindowAttributes child_attrs; 658b3307321Smrg Window root, parent, *child; /* variables for XQueryTree() */ 659b3307321Smrg Window *save_child_list; /* variables for XQueryTree() */ 660b3307321Smrg unsigned int nchild; /* variables for XQueryTree() */ 661b3307321Smrg XRectangle child_clip; /* vis part of child */ 662b3307321Smrg int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt; 663b3307321Smrg 664b3307321Smrg /* check that win is mapped & not outside bounding box */ 665b3307321Smrg if (curr_attrs->map_state == IsViewable && 666b3307321Smrg curr_attrs->class == InputOutput && 667b3307321Smrg !( pclip->x >= (int) (bbox->x + bbox->width) || 668b3307321Smrg pclip->y >= (int) (bbox->y + bbox->height) || 669b3307321Smrg (int) (pclip->x + pclip->width) <= bbox->x || 670b3307321Smrg (int) (pclip->y + pclip->height) <= bbox->y)) { 671b3307321Smrg 672b3307321Smrg XQueryTree( disp, curr, &root, &parent, &child, &nchild ); 673b3307321Smrg save_child_list = child; /* so we can free list when we're done */ 674b3307321Smrg add_window_to_list( image_wins, curr, x_rootrel, y_rootrel, 675b3307321Smrg pclip->x, pclip->y, 676b3307321Smrg pclip->width, pclip->height, 677b3307321Smrg curr_attrs->border_width,curr_attrs->visual, 678b3307321Smrg curr_attrs->colormap, parent); 679b3307321Smrg 680b3307321Smrg 681b3307321Smrg/** ------------------------------------------------------------------------ 682b3307321Smrg set RR coords of right (Rt), left (X), bottom (Bt) and top (Y) 683b3307321Smrg of rect we clip all children by. This is our own clip rect (pclip) 684b3307321Smrg inflicted on us by our parent plus our own borders. Within the 685b3307321Smrg child loop, we figure the clip rect for each child by adding in 686b3307321Smrg it's rectangle (not taking into account the child's borders). 687b3307321Smrg ------------------------------------------------------------------------ **/ 688b3307321Smrg curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width); 689b3307321Smrg curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width); 690b3307321Smrg curr_clipRt = MIN( pclip->x + (int) pclip->width, 691b3307321Smrg x_rootrel + (int) curr_attrs->width + 692b3307321Smrg 2 * (int) curr_attrs->border_width); 693b3307321Smrg curr_clipBt = MIN( pclip->y + (int) pclip->height, 694b3307321Smrg y_rootrel + (int) curr_attrs->height + 695b3307321Smrg 2 * (int) curr_attrs->border_width); 696b3307321Smrg 697b3307321Smrg while (nchild--) { 698b3307321Smrg int new_width, new_height; 699b3307321Smrg int child_xrr, child_yrr; /* root relative x & y of child */ 700b3307321Smrg 701b3307321Smrg XGetWindowAttributes( disp, *child, &child_attrs); 702b3307321Smrg 703b3307321Smrg /* intersect parent & child clip rects */ 704b3307321Smrg child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width; 705b3307321Smrg child_clip.x = MAX( curr_clipX, child_xrr); 706b3307321Smrg new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width 707b3307321Smrg + 2 * child_attrs.border_width) 708b3307321Smrg - child_clip.x; 709b3307321Smrg if (new_width >= 0) { 710b3307321Smrg child_clip.width = new_width; 711b3307321Smrg 712b3307321Smrg child_yrr = y_rootrel + child_attrs.y + 713b3307321Smrg curr_attrs->border_width; 714b3307321Smrg child_clip.y = MAX( curr_clipY, child_yrr); 715b3307321Smrg new_height = MIN( curr_clipBt, 716b3307321Smrg child_yrr + (int) child_attrs.height + 717b3307321Smrg 2 * child_attrs.border_width) 718b3307321Smrg - child_clip.y; 719b3307321Smrg if (new_height >= 0) { 720b3307321Smrg child_clip.height = new_height; 721b3307321Smrg make_src_list( disp, image_wins, bbox, *child, 722b3307321Smrg child_xrr, child_yrr, 723b3307321Smrg &child_attrs, &child_clip); 724b3307321Smrg } 725b3307321Smrg } 726b3307321Smrg child++; 727b3307321Smrg } 728b3307321Smrg XFree( save_child_list); 729b3307321Smrg } 730b3307321Smrg} 731b3307321Smrg 732b3307321Smrg 733b3307321Smrg/** ------------------------------------------------------------------------ 734b3307321Smrg This function creates a list of regions which tile a specified 735b3307321Smrg window. Each region contains all visible portions of the window 736b3307321Smrg which are drawn with the same visual. For example, if the 737b3307321Smrg window consists of subwindows of two different visual types, 738b3307321Smrg there will be two regions in the list. 739b3307321Smrg Returns a pointer to the list. 740b3307321Smrg ------------------------------------------------------------------------ **/ 7415e358ecaSmrgstatic list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox, 7425e358ecaSmrg int *hasNonDefault, int numImageVisuals, 7435e358ecaSmrg XVisualInfo **pImageVisuals, int *allImage) 744b3307321Smrg{ 745b3307321Smrg XWindowAttributes win_attrs; 746b3307321Smrg list image_wins; 747b3307321Smrg list_ptr image_regions; 748b3307321Smrg list_ptr srcs_left; 749b3307321Smrg image_region_type *new_reg; 750b3307321Smrg image_win_type *base_src, *src; 751b3307321Smrg Region bbox_region = XCreateRegion(); 752b3307321Smrg XRectangle clip; 753b3307321Smrg int image_only; 754b3307321Smrg 755b3307321Smrg int count=0 ; 756b3307321Smrg 757b3307321Smrg *hasNonDefault = False; 758b3307321Smrg XUnionRectWithRegion( bbox, bbox_region, bbox_region); 759b3307321Smrg XGetWindowAttributes( disp, win, &win_attrs); 760b3307321Smrg 761b3307321Smrg zero_list( &image_wins); 762b3307321Smrg clip.x = 0; 763b3307321Smrg clip.y = 0; 764b3307321Smrg clip.width = win_attrs.width; 765b3307321Smrg clip.height = win_attrs.height; 766b3307321Smrg make_src_list( disp, &image_wins, bbox, win, 767b3307321Smrg 0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip); 768b3307321Smrg 769b3307321Smrg image_regions = new_list(); 770b3307321Smrg image_only = (*allImage) ? True:False; 771b3307321Smrg 772b3307321Smrg for (base_src = (image_win_type *) first_in_list( &image_wins); base_src; 773b3307321Smrg base_src = (image_win_type *) next_in_list( &image_wins)) 774b3307321Smrg { 775b3307321Smrg /* test for image visual */ 776b3307321Smrg if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals)) 777b3307321Smrg { 778b3307321Smrg /* find a window whose visual hasn't been put in list yet */ 779b3307321Smrg if (!src_in_region_list( base_src, image_regions)) 780b3307321Smrg { 781b3307321Smrg if (! (new_reg = (image_region_type *) 782b3307321Smrg malloc( sizeof( image_region_type)))) { 783b3307321Smrg return (list_ptr) NULL; 784b3307321Smrg } 785b3307321Smrg count++; 786b3307321Smrg 787b3307321Smrg new_reg->visible_region = XCreateRegion(); 788b3307321Smrg new_reg->win = base_src->win; 789b3307321Smrg new_reg->vis = base_src->vis; 790b3307321Smrg new_reg->cmap = base_src->cmap; 791b3307321Smrg new_reg->x_rootrel = base_src->x_rootrel; 792b3307321Smrg new_reg->y_rootrel = base_src->y_rootrel; 793b3307321Smrg new_reg->x_vis = base_src->x_vis; 794b3307321Smrg new_reg->y_vis = base_src->y_vis; 795b3307321Smrg new_reg->width = base_src->width; 796b3307321Smrg new_reg->height = base_src->height; 797b3307321Smrg new_reg->border = base_src->border_width; 798b3307321Smrg 799b3307321Smrg srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR); 800b3307321Smrg for (src = (image_win_type *) first_in_list( srcs_left); src; 801b3307321Smrg src = (image_win_type *) next_in_list( srcs_left)) { 802b3307321Smrg if (SAME_REGIONS( base_src, src)) { 803b3307321Smrg add_rect_to_image_region( new_reg, src->x_vis, src->y_vis, 804b3307321Smrg src->width, src->height); 805b3307321Smrg } 806b3307321Smrg else { 807b3307321Smrg if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals)) 808b3307321Smrg { 809b3307321Smrg subtr_rect_from_image_region( new_reg, src->x_vis, 810b3307321Smrg src->y_vis, src->width, src->height); 811b3307321Smrg } 812b3307321Smrg } 813b3307321Smrg } 814b3307321Smrg XIntersectRegion( bbox_region, new_reg->visible_region, 815b3307321Smrg new_reg->visible_region); 816b3307321Smrg if (! XEmptyRegion( new_reg->visible_region)) { 817b3307321Smrg add_to_list( image_regions, new_reg); 818b3307321Smrg if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) || 819b3307321Smrg new_reg->cmap != DefaultColormapOfScreen( 820b3307321Smrg win_attrs.screen)) { 821b3307321Smrg *hasNonDefault = True; 822b3307321Smrg } 823b3307321Smrg } 824b3307321Smrg else { 825b3307321Smrg XDestroyRegion( new_reg->visible_region); 826b3307321Smrg free( (void *) new_reg); 827b3307321Smrg } 828b3307321Smrg } 829b3307321Smrg } else *allImage = 0; 830b3307321Smrg } 831b3307321Smrg delete_list( &image_wins, True); 832b3307321Smrg XDestroyRegion( bbox_region); 833b3307321Smrg return image_regions; 834b3307321Smrg} 835b3307321Smrg/** ------------------------------------------------------------------------ 836b3307321Smrg Destructor called from destroy_region_list(). 837b3307321Smrg ------------------------------------------------------------------------ **/ 8385e358ecaSmrgstatic void destroy_image_region(image_region_type *image_region) 839b3307321Smrg{ 840b3307321Smrg XDestroyRegion( image_region->visible_region); 841b3307321Smrg free( (void *) image_region); 842b3307321Smrg} 843b3307321Smrg 844b3307321Smrg/** ------------------------------------------------------------------------ 845b3307321Smrg Destroys the region list, destroying all the regions contained in it. 846b3307321Smrg ------------------------------------------------------------------------ **/ 8475e358ecaSmrgstatic void destroy_region_list(list_ptr rlist) 848b3307321Smrg{ 849b3307321Smrg delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region); 850b3307321Smrg} 851b3307321Smrg 852b3307321Smrg 853b3307321Smrg/** ------------------------------------------------------------------------ 854b3307321Smrg Subtracts the specified rectangle from the region in image_region. 855b3307321Smrg First converts the rectangle to a region of its own, since X 856b3307321Smrg only provides a way to subtract one region from another, not a 857b3307321Smrg rectangle from a region. 858b3307321Smrg ------------------------------------------------------------------------ **/ 8595e358ecaSmrgstatic void subtr_rect_from_image_region(image_region_type *image_region, 8605e358ecaSmrg int x, int y, int width, int height) 861b3307321Smrg{ 862b3307321Smrg XRectangle rect; 863b3307321Smrg Region rect_region; 864b3307321Smrg 865b3307321Smrg rect_region = XCreateRegion(); 866b3307321Smrg rect.x = x; 867b3307321Smrg rect.y = y; 868b3307321Smrg rect.width = width; 869b3307321Smrg rect.height = height; 870b3307321Smrg XUnionRectWithRegion( &rect, rect_region, rect_region); 871b3307321Smrg XSubtractRegion( image_region->visible_region, rect_region, 872b3307321Smrg image_region->visible_region); 873b3307321Smrg XDestroyRegion( rect_region); 874b3307321Smrg} 875b3307321Smrg 876b3307321Smrg 877b3307321Smrg/** ------------------------------------------------------------------------ 878b3307321Smrg Adds the specified rectangle to the region in image_region. 879b3307321Smrg ------------------------------------------------------------------------ **/ 8805e358ecaSmrgstatic void add_rect_to_image_region(image_region_type *image_region, 8815e358ecaSmrg int x, int y, int width, int height) 882b3307321Smrg{ 883b3307321Smrg XRectangle rect; 884b3307321Smrg 885b3307321Smrg rect.x = x; 886b3307321Smrg rect.y = y; 887b3307321Smrg rect.width = width; 888b3307321Smrg rect.height = height; 889b3307321Smrg XUnionRectWithRegion( &rect, image_region->visible_region, 890b3307321Smrg image_region->visible_region); 891b3307321Smrg} 892b3307321Smrg 893b3307321Smrg 894b3307321Smrg/** ------------------------------------------------------------------------ 895b3307321Smrg Returns TRUE if the given src's visual is already represented in 896b3307321Smrg the image_regions list, FALSE otherwise. 897b3307321Smrg ------------------------------------------------------------------------ **/ 8985e358ecaSmrgstatic int src_in_region_list(image_win_type *src, list_ptr image_regions) 899b3307321Smrg{ 900b3307321Smrg image_region_type *ir; 901b3307321Smrg 902b3307321Smrg for (ir = (image_region_type *) first_in_list( image_regions); ir; 903b3307321Smrg ir = (image_region_type *) next_in_list( image_regions)) { 904b3307321Smrg if (SAME_REGIONS( ir, src)) { 905b3307321Smrg 906b3307321Smrg return 1; 907b3307321Smrg } 908b3307321Smrg } 909b3307321Smrg 910b3307321Smrg return 0; 911b3307321Smrg} 912b3307321Smrg 913b3307321Smrg 914b3307321Smrg/** ------------------------------------------------------------------------ 915b3307321Smrg Makes a new entry in image_wins with the given fields filled in. 916b3307321Smrg ------------------------------------------------------------------------ **/ 9175e358ecaSmrgstatic void add_window_to_list(list_ptr image_wins, Window w, 9185e358ecaSmrg int xrr, int yrr, int x_vis, int y_vis, 9195e358ecaSmrg int width, int height, int border_width, 9205e358ecaSmrg Visual *vis, Colormap cmap, Window parent) 921b3307321Smrg{ 922b3307321Smrg image_win_type *new_src; 923b3307321Smrg 924b3307321Smrg if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL) 925b3307321Smrg 926b3307321Smrg return; 927b3307321Smrg 928b3307321Smrg new_src->win = w; 929b3307321Smrg new_src->x_rootrel = xrr; 930b3307321Smrg new_src->y_rootrel = yrr; 931b3307321Smrg new_src->x_vis = x_vis; 932b3307321Smrg new_src->y_vis = y_vis; 933b3307321Smrg new_src->width = width; 934b3307321Smrg new_src->height = height; 935b3307321Smrg new_src->border_width = border_width; 936b3307321Smrg new_src->vis = vis; 937b3307321Smrg new_src->cmap = cmap; 938b3307321Smrg new_src->parent = parent; 939b3307321Smrg add_to_list( image_wins, new_src); 940b3307321Smrg} 941b3307321Smrg 942b3307321Smrg/** ------------------------------------------------------------------------ 943b3307321Smrg Returns TRUE if the given src's visual is in the image planes, 944b3307321Smrg FALSE otherwise. 945b3307321Smrg ------------------------------------------------------------------------ **/ 9465e358ecaSmrgstatic int src_in_image(image_win_type *src, int numImageVisuals, 9475e358ecaSmrg XVisualInfo **pImageVisuals) 948b3307321Smrg{ 949b3307321Smrg int i; 950b3307321Smrg 951b3307321Smrg for (i = 0 ; i < numImageVisuals ; i++) 952b3307321Smrg { 953b3307321Smrg if (pImageVisuals[i]->visual == src->vis) 954b3307321Smrg return 1; 955b3307321Smrg } 956b3307321Smrg return 0; 957b3307321Smrg} 958b3307321Smrg 959b3307321Smrg 960b3307321Smrg/** ------------------------------------------------------------------------ 961b3307321Smrg Returns TRUE if the given src's visual is in the overlay planes 962b3307321Smrg and transparency is possible, FALSE otherwise. 963b3307321Smrg ------------------------------------------------------------------------ **/ 9645e358ecaSmrgstatic int src_in_overlay(image_region_type *src, int numOverlayVisuals, 9655e358ecaSmrg OverlayInfo *pOverlayVisuals, 9665e358ecaSmrg int *transparentColor, int *transparentType) 967b3307321Smrg{ 968b3307321Smrg int i; 969b3307321Smrg 970b3307321Smrg for (i = 0 ; i < numOverlayVisuals ; i++) 971b3307321Smrg { 972b3307321Smrg if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis) 973b3307321Smrg && (pOverlayVisuals[i].transparentType != None)) 974b3307321Smrg { 975b3307321Smrg *transparentColor = pOverlayVisuals[i].value; 976b3307321Smrg *transparentType = pOverlayVisuals[i].transparentType; 977b3307321Smrg return 1; 978b3307321Smrg } 979b3307321Smrg 980b3307321Smrg else { 981b3307321Smrg } 982b3307321Smrg 983b3307321Smrg } 984b3307321Smrg return 0; 985b3307321Smrg} 986b3307321Smrg 987b3307321Smrg 988b3307321Smrg/********************** from wsutils.c ******************************/ 989b3307321Smrg 990b3307321Smrg/****************************************************************************** 991b3307321Smrg * 992b3307321Smrg * This file contains a set of example utility procedures; procedures that can 993b3307321Smrg * help a "window-smart" Starbase or PHIGS program determine information about 994b3307321Smrg * a device, and create image and overlay plane windows. To use these 995b3307321Smrg * utilities, #include "wsutils.h" and compile this file and link the results 996b3307321Smrg * with your program. 997b3307321Smrg * 998b3307321Smrg ******************************************************************************/ 999b3307321Smrg 1000b3307321Smrg 1001b3307321Smrg 1002b3307321Smrg#define STATIC_GRAY 0x01 1003b3307321Smrg#define GRAY_SCALE 0x02 1004b3307321Smrg#define PSEUDO_COLOR 0x04 1005b3307321Smrg#define TRUE_COLOR 0x10 1006b3307321Smrg#define DIRECT_COLOR 0x11 1007b3307321Smrg 1008b3307321Smrg 1009b3307321Smrgstatic int weCreateServerOverlayVisualsProperty = False; 1010b3307321Smrg 1011b3307321Smrg 1012b3307321Smrg/****************************************************************************** 1013b3307321Smrg * 1014b3307321Smrg * GetXVisualInfo() 1015b3307321Smrg * 1016b3307321Smrg * This routine takes an X11 Display, screen number, and returns whether the 1017b3307321Smrg * screen supports transparent overlays and three arrays: 1018b3307321Smrg * 1019b3307321Smrg * 1) All of the XVisualInfo struct's for the screen. 1020b3307321Smrg * 2) All of the OverlayInfo struct's for the screen. 1021b3307321Smrg * 3) An array of pointers to the screen's image plane XVisualInfo 1022b3307321Smrg * structs. 1023b3307321Smrg * 1024b3307321Smrg * The code below obtains the array of all the screen's visuals, and obtains 1025b3307321Smrg * the array of all the screen's overlay visual information. It then processes 1026b3307321Smrg * the array of the screen's visuals, determining whether the visual is an 1027b3307321Smrg * overlay or image visual. 1028b3307321Smrg * 1029b3307321Smrg * If the routine sucessfully obtained the visual information, it returns zero. 1030b3307321Smrg * If the routine didn't obtain the visual information, it returns non-zero. 1031b3307321Smrg * 1032b3307321Smrg ******************************************************************************/ 1033b3307321Smrg 10345e358ecaSmrgint GetXVisualInfo(/* Which X server (aka "display"). */ 10355e358ecaSmrg Display *display, 10365e358ecaSmrg /* Which screen of the "display". */ 10375e358ecaSmrg int screen, 10385e358ecaSmrg /* Non-zero if there's at least one overlay visual and 10395e358ecaSmrg * if at least one of those supports a transparent pixel. */ 10405e358ecaSmrg int *transparentOverlays, 10415e358ecaSmrg /* Number of XVisualInfo struct's pointed to by pVisuals. */ 10425e358ecaSmrg int *numVisuals, 10435e358ecaSmrg /* All of the device's visuals. */ 10445e358ecaSmrg XVisualInfo **pVisuals, 10455e358ecaSmrg /* Number of OverlayInfo's pointed to by pOverlayVisuals. 10465e358ecaSmrg * If this number is zero, the device does not have 10475e358ecaSmrg * overlay planes. */ 10485e358ecaSmrg int *numOverlayVisuals, 10495e358ecaSmrg /* The device's overlay plane visual information. */ 10505e358ecaSmrg OverlayInfo **pOverlayVisuals, 10515e358ecaSmrg /* Number of XVisualInfo's pointed to by pImageVisuals. */ 10525e358ecaSmrg int *numImageVisuals, 10535e358ecaSmrg /* The device's image visuals. */ 10545e358ecaSmrg XVisualInfo ***pImageVisuals) 1055b3307321Smrg{ 1056b3307321Smrg XVisualInfo getVisInfo; /* Paramters of XGetVisualInfo */ 1057b3307321Smrg int mask; 1058b3307321Smrg XVisualInfo *pVis, **pIVis; /* Faster, local copies */ 1059b3307321Smrg OverlayInfo *pOVis; 1060b3307321Smrg OverlayVisualPropertyRec *pOOldVis; 1061b3307321Smrg int nVisuals, nOVisuals; 1062b3307321Smrg Atom overlayVisualsAtom; /* Parameters for XGetWindowProperty */ 1063b3307321Smrg Atom actualType; 1064b3307321Smrg unsigned long numLongs, bytesAfter; 1065b3307321Smrg int actualFormat; 1066b3307321Smrg int nImageVisualsAlloced; /* Values to process the XVisualInfo */ 1067b3307321Smrg int imageVisual; /* array */ 1068b3307321Smrg 1069b3307321Smrg 1070b3307321Smrg /* First, get the list of visuals for this screen. */ 1071b3307321Smrg getVisInfo.screen = screen; 1072b3307321Smrg mask = VisualScreenMask; 1073b3307321Smrg 1074b3307321Smrg *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals); 1075b3307321Smrg if ((nVisuals = *numVisuals) <= 0) 1076b3307321Smrg { 1077b3307321Smrg /* Return that the information wasn't sucessfully obtained: */ 1078b3307321Smrg return(1); 1079b3307321Smrg } 1080b3307321Smrg pVis = *pVisuals; 1081b3307321Smrg 1082b3307321Smrg 1083b3307321Smrg /* Now, get the overlay visual information for this screen. To obtain 1084b3307321Smrg * this information, get the SERVER_OVERLAY_VISUALS property. 1085b3307321Smrg */ 1086b3307321Smrg overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True); 1087b3307321Smrg if (overlayVisualsAtom != None) 1088b3307321Smrg { 1089b3307321Smrg /* Since the Atom exists, we can request the property's contents. The 1090b3307321Smrg * do-while loop makes sure we get the entire list from the X server. 1091b3307321Smrg */ 1092b3307321Smrg bytesAfter = 0; 1093b3307321Smrg numLongs = sizeof(OverlayVisualPropertyRec) / 4; 1094b3307321Smrg do 1095b3307321Smrg { 1096b3307321Smrg numLongs += bytesAfter * 4; 1097b3307321Smrg XGetWindowProperty(display, RootWindow(display, screen), 1098b3307321Smrg overlayVisualsAtom, 0, numLongs, False, 1099b3307321Smrg overlayVisualsAtom, &actualType, &actualFormat, 1100b3307321Smrg &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals); 1101b3307321Smrg } while (bytesAfter > 0); 1102b3307321Smrg 1103b3307321Smrg 1104b3307321Smrg /* Calculate the number of overlay visuals in the list. */ 1105b3307321Smrg *numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4); 1106b3307321Smrg } 1107b3307321Smrg else 1108b3307321Smrg { 1109b3307321Smrg /* This screen doesn't have overlay planes. */ 1110b3307321Smrg *numOverlayVisuals = 0; 1111b3307321Smrg *pOverlayVisuals = NULL; 1112b3307321Smrg *transparentOverlays = 0; 1113b3307321Smrg } 1114b3307321Smrg 1115b3307321Smrg 1116b3307321Smrg /* Process the pVisuals array. */ 1117b3307321Smrg *numImageVisuals = 0; 1118b3307321Smrg nImageVisualsAlloced = 1; 1119b3307321Smrg pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *)); 1120b3307321Smrg while (--nVisuals >= 0) 1121b3307321Smrg { 1122b3307321Smrg nOVisuals = *numOverlayVisuals; 1123b3307321Smrg pOVis = *pOverlayVisuals; 1124b3307321Smrg imageVisual = True; 1125b3307321Smrg while (--nOVisuals >= 0) 1126b3307321Smrg { 1127b3307321Smrg pOOldVis = (OverlayVisualPropertyRec *) pOVis; 1128b3307321Smrg if (pVis->visualid == pOOldVis->visualID) 1129b3307321Smrg { 1130b3307321Smrg imageVisual = False; 1131b3307321Smrg pOVis->pOverlayVisualInfo = pVis; 1132b3307321Smrg if (pOVis->transparentType == TransparentPixel) 1133b3307321Smrg *transparentOverlays = 1; 1134b3307321Smrg } 1135b3307321Smrg pOVis++; 1136b3307321Smrg } 1137b3307321Smrg if (imageVisual) 1138b3307321Smrg { 1139b3307321Smrg if ((*numImageVisuals += 1) > nImageVisualsAlloced) 1140b3307321Smrg { 1141b3307321Smrg nImageVisualsAlloced++; 1142b3307321Smrg *pImageVisuals = (XVisualInfo **) 1143b3307321Smrg realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *))); 1144b3307321Smrg pIVis = *pImageVisuals + (*numImageVisuals - 1); 1145b3307321Smrg } 1146b3307321Smrg *pIVis++ = pVis; 1147b3307321Smrg } 1148b3307321Smrg pVis++; 1149b3307321Smrg } 1150b3307321Smrg 1151b3307321Smrg 1152b3307321Smrg /* Return that the information was sucessfully obtained: */ 1153b3307321Smrg return(0); 1154b3307321Smrg 1155b3307321Smrg} /* GetXVisualInfo() */ 1156b3307321Smrg 1157b3307321Smrg 1158b3307321Smrg/****************************************************************************** 1159b3307321Smrg * 1160b3307321Smrg * FreeXVisualInfo() 1161b3307321Smrg * 1162b3307321Smrg * This routine frees the data that was allocated by GetXVisualInfo(). 1163b3307321Smrg * 1164b3307321Smrg ******************************************************************************/ 1165b3307321Smrg 11665e358ecaSmrgvoid FreeXVisualInfo(XVisualInfo *pVisuals, OverlayInfo *pOverlayVisuals, 11675e358ecaSmrg XVisualInfo **pImageVisuals) 1168b3307321Smrg{ 1169b3307321Smrg XFree(pVisuals); 1170b3307321Smrg if (weCreateServerOverlayVisualsProperty) 1171b3307321Smrg free(pOverlayVisuals); 1172b3307321Smrg else 1173b3307321Smrg XFree(pOverlayVisuals); 1174b3307321Smrg free(pImageVisuals); 1175b3307321Smrg 1176b3307321Smrg} /* FreeXVisualInfo() */ 1177