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