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