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
11
Copyright 1994 Hewlett-Packard Co.
12
Copyright 1996, 1998 The Open Group
14
Permission to use, copy, modify, distribute, and sell this software and its
15
documentation for any purpose is hereby granted without fee, provided that
16
the above copyright notice appear in all copies and that both that
17
copyright notice and this permission notice appear in supporting
20
The above copyright notice and this permission notice shall be included
21
in all copies or substantial portions of the Software.
23
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
27
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29
OTHER DEALINGS IN THE SOFTWARE.
31
Except as contained in this notice, the name of The Open Group shall
32
not be used in advertising or otherwise to promote the sale, use or
33
other dealings in this Software without prior written authorization
36
------------------------------------------------------------------------ **/
37
/* $XFree86: xc/programs/xwd/multiVis.c,v 1.8 2002/12/10 22:38:50 tsi Exp $ */
41
#include <X11/Xutil.h>
47
/* These structures are copied from X11/region.h. For some reason
48
* they're invisible from the outside.
52
} myBox, myBOX, myBoxRec, *myBoxPtr;
54
typedef struct my_XRegion {
61
/* Items in long list of windows that have some part in the grabbed area */
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) */
73
/* Items in short list of regions that tile the grabbed area. May have
74
multiple windows in the region.
77
Window win; /* lowest window of this visual */
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;
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)
100
#define MIN( a, b) ((a) < (b) ? a : b)
101
#define MAX( a, b) ((a) > (b) ? a : b)
105
#define GREEN_SHIFT 8
109
extern list_ptr new_list();
110
extern list_ptr dup_list_head();
111
extern void * first_in_list();
112
extern void * next_in_list();
113
extern int add_to_list();
114
extern void zero_list();
115
extern void delete_list();
116
extern void delete_list_destroying();
117
extern unsigned int list_length();
120
/* Prototype Declarations for Static Functions */
121
static int QueryColorMap(
122
#if NeedFunctionPrototypes
123
Display *, Colormap , Visual *,
124
XColor **, int *, int *, int *
127
static void TransferImage(
128
#if NeedFunctionPrototypes
129
Display *, XImage *,int, int , image_region_type*,
133
static XImage * ReadRegionsInList(
134
#if NeedFunctionPrototypes
135
Display *, Visual *, int ,int ,int ,
136
int , XRectangle, list_ptr
140
static list_ptr make_region_list(
141
#if NeedFunctionPrototypes
142
Display*, Window, XRectangle*,
143
int*, int, XVisualInfo**, int *
147
static void destroy_region_list(
148
#if NeedFunctionPrototypes
152
static void subtr_rect_from_image_region(
153
#if NeedFunctionPrototypes
154
image_region_type *, int , int , int , int
157
static void add_rect_to_image_region(
158
#if NeedFunctionPrototypes
160
int , int , int , int
163
static int src_in_region_list(
164
#if NeedFunctionPrototypes
165
image_win_type *, list_ptr
168
static void add_window_to_list(
169
#if NeedFunctionPrototypes
170
list_ptr, Window, int, int ,
171
int , int , int , int, int,
172
Visual*, Colormap, Window
175
static int src_in_image(
176
#if NeedFunctionPrototypes
177
image_win_type *, int , XVisualInfo**
180
static int src_in_overlay(
181
#if NeedFunctionPrototypes
182
image_region_type *, int, OverlayInfo *, int*, int*
185
static void make_src_list(
186
#if NeedFunctionPrototypes
187
Display *, list_ptr, XRectangle *, Window,
188
int, int, XWindowAttributes *, XRectangle *
191
static void destroy_image_region(
192
#if NeedFunctionPrototypes
197
/* End of Prototype Declarations */
199
void initFakeVisual(Vis)
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 ;
212
QueryColorMap(disp,src_cmap,src_vis,src_colors,rShift,gShift,bShift)
216
XColor **src_colors ;
217
int *rShift, *gShift, *bShift;
220
unsigned long redMask, greenMask, blueMask;
221
int redShift, greenShift, blueShift;
224
ncolors = src_vis->map_entries ;
225
*src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;
227
if(src_vis->class != TrueColor && src_vis->class != DirectColor)
229
for(i=0 ; i < ncolors ; i++)
231
colors[i].pixel = i ;
233
colors[i].flags = DoRed|DoGreen|DoBlue;
236
else /** src is decomposed rgb ***/
238
/* Get the X colormap */
239
redMask = src_vis->red_mask;
240
greenMask = src_vis->green_mask;
241
blueMask = src_vis->blue_mask;
242
redShift = 0; while (!(redMask&0x1)) {
244
redMask = redMask>>1;
246
greenShift = 0; while (!(greenMask&0x1)) {
248
greenMask = greenMask>>1;
250
blueShift = 0; while (!(blueMask&0x1)) {
252
blueMask = blueMask>>1;
255
*gShift = greenShift ;
256
*bShift = blueShift ;
257
for (i=0; i<ncolors; i++) {
258
if( i <= redMask)colors[i].pixel = (i<<redShift) ;
259
if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;
260
if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;
261
/***** example :for gecko's 3-3-2 map, blue index should be <= 3.
262
colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);
265
colors[i].flags = DoRed|DoGreen|DoBlue;
270
XQueryColors(disp, src_cmap, colors, ncolors);
275
GetMultiVisualRegions(disp,srcRootWinid, x, y, width, height,
276
transparentOverlays,numVisuals, pVisuals,numOverlayVisuals, pOverlayVisuals,
277
numImageVisuals, pImageVisuals,vis_regions,vis_image_regions,allImage)
279
Window srcRootWinid; /* root win on which grab was done */
280
int x; /* root rel UL corner of bounding box of grab */
282
unsigned int width; /* size of bounding box of grab */
284
int *transparentOverlays ;
286
XVisualInfo **pVisuals;
287
int *numOverlayVisuals;
288
OverlayInfo **pOverlayVisuals;
289
int *numImageVisuals;
290
XVisualInfo ***pImageVisuals;
291
list_ptr *vis_regions; /* list of regions to read from */
292
list_ptr *vis_image_regions ;
296
XRectangle bbox; /* bounding box of grabbed area */
299
bbox.x = x; /* init X rect for bounding box */
302
bbox.height = height;
304
GetXVisualInfo(disp,DefaultScreen(disp),
306
numVisuals, pVisuals,
307
numOverlayVisuals, pOverlayVisuals,
308
numImageVisuals, pImageVisuals);
310
*vis_regions = *vis_image_regions = NULL ;
311
if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,
312
&hasNonDefault, *numImageVisuals,
313
*pImageVisuals, allImage)) == NULL)
316
if (*transparentOverlays)
318
*allImage = 1; /* until proven otherwise,
319
this flags that it to be an image only list */
321
make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,
322
*numImageVisuals, *pImageVisuals, allImage);
325
/* if there is a second region in any of the two lists return 1 **/
326
if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||
327
( *vis_image_regions && (*vis_image_regions)->next &&
328
(*vis_image_regions)->next->next ) ) return 1 ;
333
static void TransferImage(disp,reg_image,srcw,srch,reg,
334
target_image,dst_x,dst_y)
336
XImage *reg_image,*target_image ;
337
image_region_type *reg;
338
int srcw,srch,dst_x , dst_y ;
341
int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;
343
int rShift,gShift,bShift;
344
int targetBytesPerLine ;
346
ncolors = QueryColorMap(disp,reg->cmap,reg->vis,&colors,
347
&rShift,&gShift,&bShift) ;
349
targetBytesPerLine = target_image->bytes_per_line;
351
switch (reg->vis->class) {
353
for(i=0 ; i < srch ; i++)
355
for(j=0 ; j < srcw ; j++)
357
old_pixel = XGetPixel(reg_image,j,i) ;
359
if( reg->vis->map_entries == 16) {
361
red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
362
green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
363
blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
366
((colors[red_ind].red >> 8) << RED_SHIFT)
367
|((colors[green_ind].green >> 8) << GREEN_SHIFT)
368
|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
372
new_pixel = old_pixel;
374
XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
380
for(i=0 ; i < srch ; i++)
383
for(j=0 ; j < srcw ; j++)
385
old_pixel = XGetPixel(reg_image,j,i) ;
386
red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
387
green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
388
blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
391
((colors[red_ind].red >> 8) << RED_SHIFT)
392
|((colors[green_ind].green >> 8) << GREEN_SHIFT)
393
|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
395
XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
401
for(i=0 ; i < srch ; i++)
403
for(j=0 ; j < srcw ; j++)
405
old_pixel = XGetPixel(reg_image,j,i) ;
408
((colors[old_pixel].red >> 8) << RED_SHIFT)
409
|((colors[old_pixel].green >> 8) << GREEN_SHIFT)
410
|((colors[old_pixel].blue >> 8) << BLUE_SHIFT)
412
XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
421
ReadRegionsInList(disp,fakeVis,depth,format,width,height,bbox,regions)
424
int depth , width , height ;
426
XRectangle bbox; /* bounding box of grabbed area */
427
list_ptr regions;/* list of regions to read from */
429
image_region_type *reg;
430
int dst_x, dst_y; /* where in pixmap to write (UL) */
433
XImage *reg_image,*ximage ;
434
int srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
439
bitmap_unit = sizeof (long);
440
if (format == ZPixmap)
441
bytes_per_line = width*depth/8;
443
bytes_per_line = width/8;
446
/* Find out how many more bytes are required for padding so that
447
** bytes per scan line will be multiples of bitmap_unit bits */
448
if (format == ZPixmap) {
449
rem = (bytes_per_line*8)%bitmap_unit;
451
bytes_per_line += (rem/8 + 1);
454
ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,
456
bytes_per_line = ximage->bytes_per_line;
458
if (format == ZPixmap)
459
ximage->data = malloc(height*bytes_per_line);
461
ximage->data = malloc(height*bytes_per_line*depth);
463
ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
465
for (reg = (image_region_type *) first_in_list( regions); reg;
466
reg = (image_region_type *) next_in_list( regions))
469
struct my_XRegion *vis_reg;
470
vis_reg = (struct my_XRegion *)(reg->visible_region);
472
rect < vis_reg->numRects;
475
/** ------------------------------------------------------------------------
476
Intersect bbox with visible part of region giving src rect & output
477
location. Width is the min right side minus the max left side.
478
Similar for height. Offset src rect so x,y are relative to
479
origin of win, not the root-relative visible rect of win.
480
------------------------------------------------------------------------ **/
481
srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -
482
MAX( vis_reg->rects[rect].x1, bbox.x);
483
srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -
484
MAX( vis_reg->rects[rect].y1, bbox.y);
485
diff = bbox.x - vis_reg->rects[rect].x1;
486
srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
487
dst_x = MAX( 0, -diff) ;
488
diff = bbox.y - vis_reg->rects[rect].y1;
489
srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
490
dst_y = MAX( 0, -diff) ;
491
reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
492
srcRect_width,srcRect_height,AllPlanes,format) ;
493
TransferImage(disp,reg_image,srcRect_width,
494
srcRect_height,reg,ximage,dst_x,dst_y) ;
501
/** ------------------------------------------------------------------------
502
------------------------------------------------------------------------ **/
504
XImage *ReadAreaToImage(disp, srcRootWinid, x, y, width, height,
505
numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,
506
pImageVisuals,vis_regions,vis_image_regions,format,allImage)
508
Window srcRootWinid; /* root win on which grab was done */
509
int x; /* root rel UL corner of bounding box of grab */
511
unsigned int width; /* size of bounding box of grab */
513
/** int transparentOverlays; ***/
515
XVisualInfo *pVisuals;
516
int numOverlayVisuals;
517
OverlayInfo *pOverlayVisuals;
519
XVisualInfo **pImageVisuals;
520
list_ptr vis_regions; /* list of regions to read from */
521
list_ptr vis_image_regions ;/* list of regions to read from */
525
image_region_type *reg;
526
XRectangle bbox; /* bounding box of grabbed area */
528
XImage *ximage, *ximage_ipm = NULL;
532
unsigned char *pmData , *ipmData ;
533
int transparentColor, transparentType;
534
int srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
536
int dst_x, dst_y; /* where in pixmap to write (UL) */
539
bbox.x = x; /* init X rect for bounding box */
542
bbox.height = height;
545
initFakeVisual(&fakeVis) ;
548
ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
550
pmData = (unsigned char *)ximage -> data ;
552
/* if transparency possible do it again, but this time for image planes only */
553
if (vis_image_regions && (vis_image_regions->next) && !allImage)
555
ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
556
bbox,vis_image_regions) ;
557
ipmData = (unsigned char *)ximage_ipm -> data ;
559
/* Now tranverse the overlay visual windows and test for transparency index. */
560
/* If you find one, subsitute the value from the matching image plane pixmap. */
562
for (reg = (image_region_type *) first_in_list( vis_regions); reg;
563
reg = (image_region_type *) next_in_list( vis_regions))
566
if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
567
&transparentColor, &transparentType))
570
srcRect_width = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
571
- MAX( reg->x_vis, bbox.x);
572
srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
573
+ bbox.y) - MAX( reg->y_vis, bbox.y);
574
diff = bbox.x - reg->x_vis;
575
srcRect_x = MAX( 0, diff) + (reg->x_vis - reg->x_rootrel - reg->border);
576
dst_x = MAX( 0, -diff) ;
577
diff = bbox.y - reg->y_vis;
578
srcRect_y = MAX( 0, diff) + (reg->y_vis - reg->y_rootrel - reg->border);
579
dst_y = MAX( 0, -diff) ;
580
/* let's test some pixels for transparency */
581
image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
582
srcRect_width, srcRect_height, 0xffffffff, ZPixmap);
584
/* let's assume byte per pixel for overlay image for now */
585
if ((image->depth == 8) && (transparentType == TransparentPixel))
587
unsigned char *pixel_ptr;
588
unsigned char *start_of_line = (unsigned char *) image->data;
590
for (y1 = 0; y1 < srcRect_height; y1++) {
591
pixel_ptr = start_of_line;
592
for (x1 = 0; x1 < srcRect_width; x1++)
594
if (*pixel_ptr++ == transparentColor)
597
*pmData++ = *ipmData++;
598
*pmData++ = *ipmData++;
599
*pmData++ = *ipmData++;
601
pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
602
XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
615
start_of_line += image->bytes_per_line;
618
if (transparentType == TransparentPixel) {
619
for (y1 = 0; y1 < srcRect_height; y1++) {
620
for (x1 = 0; x1 < srcRect_width; x1++)
622
int pixel_value = XGetPixel(image, x1, y1);
623
if (pixel_value == transparentColor)
626
*pmData++ = *ipmData++;
627
*pmData++ = *ipmData++;
628
*pmData++ = *ipmData++;
630
pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
631
XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
645
for (y1 = 0; y1 < srcRect_height; y1++) {
646
for (x1 = 0; x1 < srcRect_width; x1++)
648
int pixel_value = XGetPixel(image, x1, y1);
649
if (pixel_value & transparentColor)
652
*pmData++ = *ipmData++;
653
*pmData++ = *ipmData++;
654
*pmData++ = *ipmData++;
656
pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
657
XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
672
XDestroyImage (image);
673
} /* end of src_in_overlay */
674
} /** end transparency **/
675
destroy_region_list( vis_regions);
676
if (vis_image_regions) destroy_region_list( vis_image_regions );
677
FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
683
/** ------------------------------------------------------------------------
684
Creates a list of the subwindows of a given window which have a
685
different visual than their parents. The function is recursive.
686
This list is used in make_region_list(), which coalesces the
687
windows with the same visual into a region.
688
image_wins must point to an existing list struct that's already
689
been zeroed (zero_list()).
690
------------------------------------------------------------------------ **/
691
static void make_src_list( disp, image_wins, bbox, curr, x_rootrel, y_rootrel,
695
XRectangle *bbox; /* bnding box of area we want */
697
int x_rootrel; /* pos of curr WRT root */
699
XWindowAttributes *curr_attrs;
700
XRectangle *pclip; /* visible part of curr, not */
701
/* obscurred by ancestors */
703
XWindowAttributes child_attrs;
704
Window root, parent, *child; /* variables for XQueryTree() */
705
Window *save_child_list; /* variables for XQueryTree() */
706
unsigned int nchild; /* variables for XQueryTree() */
707
XRectangle child_clip; /* vis part of child */
708
int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
710
/* check that win is mapped & not outside bounding box */
711
if (curr_attrs->map_state == IsViewable &&
712
curr_attrs->class == InputOutput &&
713
!( pclip->x >= (int) (bbox->x + bbox->width) ||
714
pclip->y >= (int) (bbox->y + bbox->height) ||
715
(int) (pclip->x + pclip->width) <= bbox->x ||
716
(int) (pclip->y + pclip->height) <= bbox->y)) {
718
XQueryTree( disp, curr, &root, &parent, &child, &nchild );
719
save_child_list = child; /* so we can free list when we're done */
720
add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
722
pclip->width, pclip->height,
723
curr_attrs->border_width,curr_attrs->visual,
724
curr_attrs->colormap, parent);
727
/** ------------------------------------------------------------------------
728
set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
729
of rect we clip all children by. This is our own clip rect (pclip)
730
inflicted on us by our parent plus our own borders. Within the
731
child loop, we figure the clip rect for each child by adding in
732
it's rectangle (not taking into account the child's borders).
733
------------------------------------------------------------------------ **/
734
curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);
735
curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);
736
curr_clipRt = MIN( pclip->x + (int) pclip->width,
737
x_rootrel + (int) curr_attrs->width +
738
2 * (int) curr_attrs->border_width);
739
curr_clipBt = MIN( pclip->y + (int) pclip->height,
740
y_rootrel + (int) curr_attrs->height +
741
2 * (int) curr_attrs->border_width);
744
int new_width, new_height;
745
int child_xrr, child_yrr; /* root relative x & y of child */
747
XGetWindowAttributes( disp, *child, &child_attrs);
749
/* intersect parent & child clip rects */
750
child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
751
child_clip.x = MAX( curr_clipX, child_xrr);
752
new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width
753
+ 2 * child_attrs.border_width)
755
if (new_width >= 0) {
756
child_clip.width = new_width;
758
child_yrr = y_rootrel + child_attrs.y +
759
curr_attrs->border_width;
760
child_clip.y = MAX( curr_clipY, child_yrr);
761
new_height = MIN( curr_clipBt,
762
child_yrr + (int) child_attrs.height +
763
2 * child_attrs.border_width)
765
if (new_height >= 0) {
766
child_clip.height = new_height;
767
make_src_list( disp, image_wins, bbox, *child,
768
child_xrr, child_yrr,
769
&child_attrs, &child_clip);
774
XFree( save_child_list);
779
/** ------------------------------------------------------------------------
780
This function creates a list of regions which tile a specified
781
window. Each region contains all visible portions of the window
782
which are drawn with the same visual. For example, if the
783
window consists of subwindows of two different visual types,
784
there will be two regions in the list.
785
Returns a pointer to the list.
786
------------------------------------------------------------------------ **/
787
static list_ptr make_region_list( disp, win, bbox, hasNonDefault,
788
numImageVisuals, pImageVisuals, allImage)
794
XVisualInfo **pImageVisuals;
797
XWindowAttributes win_attrs;
799
list_ptr image_regions;
801
image_region_type *new_reg;
802
image_win_type *base_src, *src;
803
Region bbox_region = XCreateRegion();
809
*hasNonDefault = False;
810
XUnionRectWithRegion( bbox, bbox_region, bbox_region);
811
XGetWindowAttributes( disp, win, &win_attrs);
813
zero_list( &image_wins);
816
clip.width = win_attrs.width;
817
clip.height = win_attrs.height;
818
make_src_list( disp, &image_wins, bbox, win,
819
0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
821
image_regions = new_list();
822
image_only = (*allImage) ? True:False;
824
for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
825
base_src = (image_win_type *) next_in_list( &image_wins))
827
/* test for image visual */
828
if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
830
/* find a window whose visual hasn't been put in list yet */
831
if (!src_in_region_list( base_src, image_regions))
833
if (! (new_reg = (image_region_type *)
834
malloc( sizeof( image_region_type)))) {
835
return (list_ptr) NULL;
839
new_reg->visible_region = XCreateRegion();
840
new_reg->win = base_src->win;
841
new_reg->vis = base_src->vis;
842
new_reg->cmap = base_src->cmap;
843
new_reg->x_rootrel = base_src->x_rootrel;
844
new_reg->y_rootrel = base_src->y_rootrel;
845
new_reg->x_vis = base_src->x_vis;
846
new_reg->y_vis = base_src->y_vis;
847
new_reg->width = base_src->width;
848
new_reg->height = base_src->height;
849
new_reg->border = base_src->border_width;
851
srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
852
for (src = (image_win_type *) first_in_list( srcs_left); src;
853
src = (image_win_type *) next_in_list( srcs_left)) {
854
if (SAME_REGIONS( base_src, src)) {
855
add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
856
src->width, src->height);
859
if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
861
subtr_rect_from_image_region( new_reg, src->x_vis,
862
src->y_vis, src->width, src->height);
866
XIntersectRegion( bbox_region, new_reg->visible_region,
867
new_reg->visible_region);
868
if (! XEmptyRegion( new_reg->visible_region)) {
869
add_to_list( image_regions, new_reg);
870
if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
871
new_reg->cmap != DefaultColormapOfScreen(
873
*hasNonDefault = True;
877
XDestroyRegion( new_reg->visible_region);
878
free( (void *) new_reg);
881
} else *allImage = 0;
883
delete_list( &image_wins, True);
884
XDestroyRegion( bbox_region);
885
return image_regions;
887
/** ------------------------------------------------------------------------
888
Destructor called from destroy_region_list().
889
------------------------------------------------------------------------ **/
890
static void destroy_image_region(image_region)
891
image_region_type *image_region;
893
XDestroyRegion( image_region->visible_region);
894
free( (void *) image_region);
897
/** ------------------------------------------------------------------------
898
Destroys the region list, destroying all the regions contained in it.
899
------------------------------------------------------------------------ **/
900
static void destroy_region_list( rlist)
903
delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
907
/** ------------------------------------------------------------------------
908
Subtracts the specified rectangle from the region in image_region.
909
First converts the rectangle to a region of its own, since X
910
only provides a way to subtract one region from another, not a
911
rectangle from a region.
912
------------------------------------------------------------------------ **/
913
static void subtr_rect_from_image_region( image_region, x, y, width, height)
914
image_region_type *image_region;
923
rect_region = XCreateRegion();
927
rect.height = height;
928
XUnionRectWithRegion( &rect, rect_region, rect_region);
929
XSubtractRegion( image_region->visible_region, rect_region,
930
image_region->visible_region);
931
XDestroyRegion( rect_region);
935
/** ------------------------------------------------------------------------
936
Adds the specified rectangle to the region in image_region.
937
------------------------------------------------------------------------ **/
938
static void add_rect_to_image_region( image_region, x, y, width, height)
939
image_region_type *image_region;
950
rect.height = height;
951
XUnionRectWithRegion( &rect, image_region->visible_region,
952
image_region->visible_region);
956
/** ------------------------------------------------------------------------
957
Returns TRUE if the given src's visual is already represented in
958
the image_regions list, FALSE otherwise.
959
------------------------------------------------------------------------ **/
960
static int src_in_region_list( src, image_regions)
962
list_ptr image_regions;
964
image_region_type *ir;
966
for (ir = (image_region_type *) first_in_list( image_regions); ir;
967
ir = (image_region_type *) next_in_list( image_regions)) {
968
if (SAME_REGIONS( ir, src)) {
978
/** ------------------------------------------------------------------------
979
Makes a new entry in image_wins with the given fields filled in.
980
------------------------------------------------------------------------ **/
981
static void add_window_to_list( image_wins, w, xrr, yrr, x_vis, y_vis,
982
width, height, border_width,vis, cmap, parent)
996
image_win_type *new_src;
998
if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
1003
new_src->x_rootrel = xrr;
1004
new_src->y_rootrel = yrr;
1005
new_src->x_vis = x_vis;
1006
new_src->y_vis = y_vis;
1007
new_src->width = width;
1008
new_src->height = height;
1009
new_src->border_width = border_width;
1011
new_src->cmap = cmap;
1012
new_src->parent = parent;
1013
add_to_list( image_wins, new_src);
1016
/** ------------------------------------------------------------------------
1017
Returns TRUE if the given src's visual is in the image planes,
1019
------------------------------------------------------------------------ **/
1020
static int src_in_image( src, numImageVisuals, pImageVisuals)
1021
image_win_type *src;
1022
int numImageVisuals;
1023
XVisualInfo **pImageVisuals;
1027
for (i = 0 ; i < numImageVisuals ; i++)
1029
if (pImageVisuals[i]->visual == src->vis)
1036
/** ------------------------------------------------------------------------
1037
Returns TRUE if the given src's visual is in the overlay planes
1038
and transparency is possible, FALSE otherwise.
1039
------------------------------------------------------------------------ **/
1040
static int src_in_overlay( src, numOverlayVisuals, pOverlayVisuals,
1041
transparentColor, transparentType)
1042
image_region_type *src;
1043
int numOverlayVisuals;
1044
OverlayInfo *pOverlayVisuals;
1045
int *transparentColor;
1046
int *transparentType;
1050
for (i = 0 ; i < numOverlayVisuals ; i++)
1052
if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
1053
&& (pOverlayVisuals[i].transparentType != None))
1055
*transparentColor = pOverlayVisuals[i].value;
1056
*transparentType = pOverlayVisuals[i].transparentType;
1068
/********************** from wsutils.c ******************************/
1070
/******************************************************************************
1072
* This file contains a set of example utility procedures; procedures that can
1073
* help a "window-smart" Starbase or PHIGS program determine information about
1074
* a device, and create image and overlay plane windows. To use these
1075
* utilities, #include "wsutils.h" and compile this file and link the results
1076
* with your program.
1078
******************************************************************************/
1082
#define STATIC_GRAY 0x01
1083
#define GRAY_SCALE 0x02
1084
#define PSEUDO_COLOR 0x04
1085
#define TRUE_COLOR 0x10
1086
#define DIRECT_COLOR 0x11
1089
static int weCreateServerOverlayVisualsProperty = False;
1092
/******************************************************************************
1096
* This routine takes an X11 Display, screen number, and returns whether the
1097
* screen supports transparent overlays and three arrays:
1099
* 1) All of the XVisualInfo struct's for the screen.
1100
* 2) All of the OverlayInfo struct's for the screen.
1101
* 3) An array of pointers to the screen's image plane XVisualInfo
1104
* The code below obtains the array of all the screen's visuals, and obtains
1105
* the array of all the screen's overlay visual information. It then processes
1106
* the array of the screen's visuals, determining whether the visual is an
1107
* overlay or image visual.
1109
* If the routine sucessfully obtained the visual information, it returns zero.
1110
* If the routine didn't obtain the visual information, it returns non-zero.
1112
******************************************************************************/
1114
int GetXVisualInfo(display, screen, transparentOverlays,
1115
numVisuals, pVisuals,
1116
numOverlayVisuals, pOverlayVisuals,
1117
numImageVisuals, pImageVisuals)
1119
Display *display; /* Which X server (aka "display"). */
1120
int screen; /* Which screen of the "display". */
1121
int *transparentOverlays; /* Non-zero if there's at least one
1122
* overlay visual and if at least one
1123
* of those supports a transparent
1125
int *numVisuals; /* Number of XVisualInfo struct's
1126
* pointed to to by pVisuals. */
1127
XVisualInfo **pVisuals; /* All of the device's visuals. */
1128
int *numOverlayVisuals; /* Number of OverlayInfo's pointed
1129
* to by pOverlayVisuals. If this
1130
* number is zero, the device does
1131
* not have overlay planes. */
1132
OverlayInfo **pOverlayVisuals; /* The device's overlay plane visual
1134
int *numImageVisuals; /* Number of XVisualInfo's pointed
1135
* to by pImageVisuals. */
1136
XVisualInfo ***pImageVisuals; /* The device's image visuals. */
1138
XVisualInfo getVisInfo; /* Paramters of XGetVisualInfo */
1140
XVisualInfo *pVis, **pIVis; /* Faster, local copies */
1142
OverlayVisualPropertyRec *pOOldVis;
1143
int nVisuals, nOVisuals;
1144
Atom overlayVisualsAtom; /* Parameters for XGetWindowProperty */
1146
unsigned long numLongs, bytesAfter;
1148
int nImageVisualsAlloced; /* Values to process the XVisualInfo */
1149
int imageVisual; /* array */
1152
/* First, get the list of visuals for this screen. */
1153
getVisInfo.screen = screen;
1154
mask = VisualScreenMask;
1156
*pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1157
if ((nVisuals = *numVisuals) <= 0)
1159
/* Return that the information wasn't sucessfully obtained: */
1165
/* Now, get the overlay visual information for this screen. To obtain
1166
* this information, get the SERVER_OVERLAY_VISUALS property.
1168
overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1169
if (overlayVisualsAtom != None)
1171
/* Since the Atom exists, we can request the property's contents. The
1172
* do-while loop makes sure we get the entire list from the X server.
1175
numLongs = sizeof(OverlayVisualPropertyRec) / 4;
1178
numLongs += bytesAfter * 4;
1179
XGetWindowProperty(display, RootWindow(display, screen),
1180
overlayVisualsAtom, 0, numLongs, False,
1181
overlayVisualsAtom, &actualType, &actualFormat,
1182
&numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1183
} while (bytesAfter > 0);
1186
/* Calculate the number of overlay visuals in the list. */
1187
*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4);
1191
/* This screen doesn't have overlay planes. */
1192
*numOverlayVisuals = 0;
1193
*pOverlayVisuals = NULL;
1194
*transparentOverlays = 0;
1198
/* Process the pVisuals array. */
1199
*numImageVisuals = 0;
1200
nImageVisualsAlloced = 1;
1201
pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1202
while (--nVisuals >= 0)
1204
nOVisuals = *numOverlayVisuals;
1205
pOVis = *pOverlayVisuals;
1207
while (--nOVisuals >= 0)
1209
pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1210
if (pVis->visualid == pOOldVis->visualID)
1212
imageVisual = False;
1213
pOVis->pOverlayVisualInfo = pVis;
1214
if (pOVis->transparentType == TransparentPixel)
1215
*transparentOverlays = 1;
1221
if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1223
nImageVisualsAlloced++;
1224
*pImageVisuals = (XVisualInfo **)
1225
realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1226
pIVis = *pImageVisuals + (*numImageVisuals - 1);
1234
/* Return that the information was sucessfully obtained: */
1237
} /* GetXVisualInfo() */
1240
/******************************************************************************
1244
* This routine frees the data that was allocated by GetXVisualInfo().
1246
******************************************************************************/
1248
void FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals)
1250
XVisualInfo *pVisuals;
1251
OverlayInfo *pOverlayVisuals;
1252
XVisualInfo **pImageVisuals;
1255
if (weCreateServerOverlayVisualsProperty)
1256
free(pOverlayVisuals);
1258
XFree(pOverlayVisuals);
1259
free(pImageVisuals);
1261
} /* FreeXVisualInfo() */