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