Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / x_util.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23
24 /*
25  *      $XConsortium: x_util.c /main/3 1995/11/06 17:57:42 rswiston $
26  *
27  * @(#)x_util.c 1.21 21 Nov 1994      cde_app_builder/src/ab
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement between
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
35  *      Sun's specific written approval.  This document and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  */
42
43
44 /*
45  ***********************************************************************
46  * x_util.c - X11 & Xt support functions
47  *      
48  *
49  ***********************************************************************
50  */
51
52 #include <stdio.h>
53 #include <X11/Intrinsic.h>
54 #include <X11/Shell.h>
55 #include <ab_private/util.h>
56 #include <ab_private/x_util.h>
57 #include <ab_private/ab.h>
58 #include "bitmaps/copy_cursor.xbm"
59 #include "bitmaps/move_cursor.xbm"
60
61
62 /*************************************************************************
63 **                                                                      **
64 **       Private Function Declarations                                  **
65 **                                                                      **
66 **************************************************************************/
67 static void     box_gc_init(
68                     Widget w, 
69                     Display *display, 
70                     Drawable drawable
71                 );
72 static void     fullscreen_gc_init(
73                     Widget w, 
74                     Display *display, 
75                     Drawable drawable
76                 );
77 static Bool     expose_count_predicate(
78                     Display *display, 
79                     XEvent *event, 
80                     XPointer arg
81                 );
82
83 /*************************************************************************
84 **                                                                      **
85 **       Private Data                                                   **
86 **                                                                      **
87 **************************************************************************/
88 static GC      box_gc;
89 static GC      fullscreen_gc;
90 static GC      grid_gc;
91
92
93 /*************************************************************************
94 **                                                                      **
95 **       Public Data                                                    **
96 **                                                                      **
97 **************************************************************************/
98 Pixmap           AB_cp_cursor_pixmap, AB_mv_cursor_pixmap;
99 unsigned short   AB_cp_cursor_height, AB_cp_cursor_width;
100 unsigned short   AB_mv_cursor_height, AB_mv_cursor_width;
101
102
103 /*************************************************************************
104 **                                                                      **
105 **       Function Definitions                                           **
106 **                                                                      **
107 **************************************************************************/
108
109 /*
110  * Load all bitmaps to be used for cursors
111  */
112 int
113 x_load_cursor_bitmaps(
114     Widget widget
115 )
116 {
117
118     if (!XtIsRealized(widget))
119     {
120         if (util_get_verbosity() > 0)
121             fprintf(stderr,"x_load_cursor_bitmaps: widget must be realized\n");
122         return ERROR;
123     }
124  
125     AB_cp_cursor_height = copy_cursor_bm_height;
126     AB_cp_cursor_width  = copy_cursor_bm_width;
127     AB_cp_cursor_pixmap = XCreatePixmapFromBitmapData(XtDisplay(widget),
128                                 XtWindow(widget),
129                                 (char*)copy_cursor_bm_bits,
130                                 AB_cp_cursor_width,
131                                 AB_cp_cursor_height,
132                                 BlackPixelOfScreen(XtScreen(widget)),
133                                 WhitePixelOfScreen(XtScreen(widget)),
134                                 1);
135
136     AB_mv_cursor_height = move_cursor_bm_height; 
137     AB_mv_cursor_width  = move_cursor_bm_width;
138     AB_mv_cursor_pixmap = XCreatePixmapFromBitmapData(XtDisplay(widget), 
139                                 XtWindow(widget), 
140                                 (char*)move_cursor_bm_bits,
141                                 AB_mv_cursor_width,
142                                 AB_mv_cursor_height,
143                                 BlackPixelOfScreen(XtScreen(widget)),
144                                 WhitePixelOfScreen(XtScreen(widget)),
145                                 1); 
146
147     return OK;
148
149
150 }
151
152 /*
153  * return a cursor which is the image of the passed-in pixmap with
154  * a stencil around it
155  */
156 Cursor
157 x_create_stencil_cursor(
158     Widget widget, 
159     Pixmap pixmap, 
160     unsigned short width, 
161     unsigned short height,
162     unsigned int xhot, 
163     unsigned int yhot
164 )
165 {
166     Display             *dpy;
167     Window              win;
168     Cursor              cursor;
169     Pixmap              cursor_pixmap, mask_pixmap;
170     unsigned short      c_width, c_height;
171     unsigned int        c_xhot, c_yhot;
172     unsigned int        max_width, max_height;
173     static GC           c_gc = NULL;
174     static XColor       fg_color, bg_color;
175     int                 i, j;
176
177     if (!XtIsRealized(widget))
178     {
179         if (util_get_verbosity() > 0)
180             fprintf(stderr,"x_create_stencil_cursor: widget must be realized\n");
181         return NULL;
182     }
183
184     dpy     = XtDisplay(widget);
185     win     = XtWindow(widget);
186
187     c_width  = width + 2;
188     c_height = height+ 2;
189     c_xhot   = xhot;
190     c_yhot   = yhot;
191
192     XQueryBestCursor(dpy, win, c_width, c_height, &max_width, &max_height);
193
194     if ( max_width < c_width)
195         c_width  = max_width - 2;
196     if ( max_height < c_height)
197         c_height = max_height - 2;
198
199     if ((max_width - 2) < c_xhot)
200         c_xhot = max_width - 2;
201     if ((max_height - 2) < c_yhot)
202         c_yhot = max_height - 2;
203
204     cursor_pixmap = XCreatePixmap(dpy, win, c_width, c_height, 1);
205     mask_pixmap   = XCreatePixmap(dpy, win, c_width, c_height, 1);
206
207     if (!c_gc)
208     {
209         XGCValues       values;
210         XrmValue        src, dst;
211         Pixel          fg_pixel, bg_pixel;
212
213         /* For the mask, we set foreground to 1 directly */
214         values.foreground = 1;
215         values.background = 0;
216         c_gc = XCreateGC(dpy, cursor_pixmap, GCForeground|GCBackground, &values);
217
218         fg_pixel = BlackPixelOfScreen(XtScreen(widget));
219         bg_pixel = WhitePixelOfScreen(XtScreen(widget));
220
221         src.size = sizeof(Pixel);
222         src.addr = (XPointer)(&fg_pixel);
223         dst.size = sizeof(XColor);
224         dst.addr = (XPointer)&fg_color;
225         XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
226
227         src.addr = (XPointer)&bg_pixel;
228         dst.addr = (XPointer)&bg_color;
229         XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
230     }
231
232     XSetFunction(dpy, c_gc, GXclear);
233     XFillRectangle(dpy, mask_pixmap,   c_gc, 0, 0, c_width, c_height);
234     XFillRectangle(dpy, cursor_pixmap, c_gc, 0, 0, c_width, c_height);
235
236     XSetFunction(dpy, c_gc, GXcopy);
237     XCopyArea(dpy, pixmap, cursor_pixmap, c_gc, 0, 0, c_width, c_height, 1, 1);
238
239     XSetFunction(dpy, c_gc, GXor);
240     /* Build a cursor mask_pixmap that is a stencil around the image */
241     for (i = -1; i <= 1; i++)
242     {
243         for (j = -1; j <= 1; j++)
244         {
245             x_graphics_op(dpy, mask_pixmap, c_gc, i, j,
246                                         c_width, c_height,
247                                         cursor_pixmap);
248         }
249     }
250  
251     cursor = XCreatePixmapCursor(dpy, cursor_pixmap, mask_pixmap,
252                         &fg_color, &bg_color, c_xhot, c_yhot);
253
254     XFreePixmap(dpy, mask_pixmap);
255     XFreePixmap(dpy, cursor_pixmap);
256
257     return(cursor);
258
259 }
260
261 void
262 x_graphics_op(
263     Display *dpy, 
264     Drawable dest, 
265     GC gc, 
266     int x, 
267     int y,
268     int width, 
269     int height, 
270     Pixmap src 
271 )
272 {
273     XGCValues       orig, changes;
274     unsigned long   changes_mask =  GCTileStipXOrigin |
275                     GCTileStipYOrigin |
276                     GCFillStyle;
277
278     /* Save original GC state */
279     XGetGCValues(dpy, gc, changes_mask, &orig);
280
281     changes.ts_x_origin = x;
282     changes.ts_y_origin = y;
283     changes.stipple = src;
284     changes.fill_style = FillOpaqueStippled;
285  
286     XChangeGC(dpy, gc, changes_mask | GCStipple, &changes);
287     XFillRectangle(dpy, dest, gc, x, y, width, height);
288  
289     /* Restore original GC state (all but stipple) */
290     XChangeGC(dpy, gc, changes_mask, &orig);
291 }
292
293
294 void
295 x_get_widget_rect(
296     Widget widget, 
297     XRectangle *rect
298 )
299 {
300
301     XtVaGetValues(widget,
302             XtNwidth,       (XtArgVal)&(rect->width),
303             XtNheight,      (XtArgVal)&(rect->height),
304             XtNx,           (XtArgVal)&(rect->x),
305             XtNy,           (XtArgVal)&(rect->y),
306             NULL);
307 }
308
309 /*
310  * Figure out the total area occupied by two rects.
311  */
312 void
313 x_get_rect_bounding(XRectangle *r1, XRectangle *r2)
314 {
315     XRectangle     r;
316
317     if (rect_isnull(r1))
318         r = *r2;
319     else if (rect_isnull(r2))
320         r = *r1;
321     else {
322         r.x = min(r1->x, r2->x);
323         r.y = min(r1->y, r2->y);
324         r.width = max(r1->x + (short)r1->width, r2->x + (short)r2->width)
325             - r.x;
326         r.height = max(r1->y + (short)r1->height, r2->y + (short)r2->height)
327             - r.y;
328     }
329     *r1 = r;
330 }
331
332 void
333 x_adjust_rect_margin(
334     XRectangle *r, 
335     int m
336 )            
337 {
338     (r->x)-=m;
339     (r->y)-=m;         
340     (r->width)+=(m+m);
341     (r->height)+=(m+m);
342 }
343
344 /*
345  *  x_box
346  */
347 void
348 x_box(
349     Widget widget, 
350     Drawable drawable, 
351     int x0, 
352     int y0, 
353     int x1, 
354     int y1
355 )
356 {
357     Display     *display;
358     int    tmp;
359
360     /* Get display and drawable */
361     display = (Display *)XtDisplay(widget);
362
363     /* Initialize gc before use */
364     box_gc_init(widget, display, drawable);
365
366     /*
367      * Transpose the coordinates if either the
368      * width or height of the rectangle is negative.
369      */
370     if (x1 - x0 < 0)
371     {
372         tmp = x0;
373         x0 = x1;
374         x1 = tmp;
375     }
376     if (y1 - y0 < 0)
377     {
378         tmp = y0;
379         y0 = y1;
380         y1 = tmp;
381     }
382
383     XDrawRectangle(display, drawable, box_gc, x0, y0, x1-x0, y1-y0);
384 }
385
386 /*
387  *  x_box_r
388  */
389 void
390 x_box_r(
391     Widget widget, 
392     XRectangle *r
393 )
394 {
395     x_box(widget, XtWindow(widget), r->x, r->y, rect_right(r), rect_bottom(r));
396 }
397
398 /*
399  * x_dashed_box_r
400  */
401 void
402 x_dashed_box_r(
403     Widget widget, 
404     Drawable drawable, 
405     XRectangle *r
406 )
407 {
408     Display     *display;
409
410     /* Get display and drawable */
411     display = (Display *)XtDisplay(widget);
412
413     /* Initialize gc before use */
414     box_gc_init(widget, display, drawable);
415
416     /* Modify gc to used dashed lines */
417     XSetLineAttributes(display, box_gc,
418         0, LineOnOffDash, CapButt, JoinMiter);
419
420     XDrawRectangle(display, drawable, box_gc,
421         r->x, r->y, r->width -1, r->height -1);
422
423     /* Restore back to solid lines */
424     XSetLineAttributes(display, box_gc,
425         0, LineSolid, CapButt, JoinMiter);
426 }
427
428 void
429 x_fullscreen_box(
430     Widget    w,
431     Drawable rootwin,
432     int    x0,
433     int    y0,
434     int    x1,
435     int    y1
436 )
437 {
438     Display         *display;
439     int        tmp;
440
441     display = XtDisplay(w);
442     fullscreen_gc_init(w, display, rootwin);
443
444     /*
445      * Transpose the coordinates if either the
446      * width or height of the rectangle is negative.
447      */
448     if (x1 - x0 < 0)
449     {
450         tmp = x0;
451         x0 = x1;
452         x1 = tmp;
453     }
454     if (y1 - y0 < 0)
455     {
456         tmp = y0;
457         y0 = y1;
458         y1 = tmp;
459     }
460
461     XDrawRectangle(display, rootwin, fullscreen_gc,
462         x0, y0, x1 - x0, y1 - y0);
463 }
464
465 void
466 x_fullscreen_preview_box(
467     Widget    w,
468     Drawable rootwin,
469     int    x0,
470     int    y0,
471     int    x1,
472     int    y1
473 )
474 {
475     Display         *display;
476     int        tmp;
477
478     display = XtDisplay(w);
479
480     /*
481      * Transpose the coordinates if either the
482      * width or height of the rectangle is negative.
483      */
484     if (x1 - x0 < 0)
485     {
486         tmp = x0;
487         x0 = x1;
488         x1 = tmp;
489     }
490     if (y1 - y0 < 0)
491     {
492         tmp = y0;
493         y0 = y1;
494         y1 = tmp;
495     }
496
497     XDrawRectangle(display, rootwin, fullscreen_gc,
498         x0 - 1, y0 - 1, x1 - x0 + 2, y1 - y0 + 2);
499 }
500
501
502 /*
503  * Return black or white depending on the intensity of the background
504  * color.  Intensity is calculated as I = 0.3*R + 0.59*G + 0.12*B.
505  */
506 unsigned int 
507 x_contrast_color(
508     Widget widget
509 )
510 {
511     XrmValue    src, dst;
512     float       intensity;
513     unsigned int    bg_pixel;
514     XColor    bg_color;
515
516     XtVaGetValues(widget, XtNbackground, &bg_pixel, NULL);
517
518     src.size = sizeof(Pixel);
519     src.addr = (XPointer)&bg_pixel;
520     dst.size = sizeof(XColor);
521     dst.addr = (XPointer)&bg_color;
522     XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
523
524     intensity = ((float) bg_color.red * 0.3 + (float) bg_color.green * 0.59 +
525         (float) bg_color.blue * 0.12) / 255.0;
526 /*
527 fprintf(stderr,"x_contrast_color: %s : red(%d) green(%d) blue(%d) = intensity(%f)\n",
528 XtName(widget),bg_color.red, bg_color.green, bg_color.blue, intensity);
529 */
530
531     if (intensity >= 90)
532         return BlackPixelOfScreen(XtScreen(widget));
533     else
534         return WhitePixelOfScreen(XtScreen(widget));
535
536 }
537
538 Boolean
539 x_widget_translate_xy(
540     Widget src, 
541     XtPointer dst, 
542     int src_x, 
543     int src_y,
544     int *p_dst_x, 
545     int *p_dst_y
546 )
547 {
548     Window src_win = XtWindow(src);
549     Window dst_win = dst? XtWindow((Widget)dst) : RootWindowOfScreen(XtScreen(src));
550     Window child;
551
552     return(XTranslateCoordinates(XtDisplay(src), src_win, dst_win,
553             src_x, src_y, p_dst_x, p_dst_y, &child));
554 }
555
556 Boolean
557 x_rootxy_inside_widget(
558     Widget w, 
559     int rootx, 
560     int rooty
561 )
562 {
563     Window        root_win = RootWindowOfScreen(XtScreen(w));
564     XRectangle     w_rect;
565     int         w_x, w_y;
566     Window        win_below;
567
568     if (XtIsRealized(w))
569     {
570         x_get_widget_rect(w, &w_rect); 
571   
572         XTranslateCoordinates(XtDisplay(w), XtWindow(w),
573         root_win, 0, 0, &w_x, &w_y, &win_below); 
574
575         w_rect.x = (short)w_x;
576         w_rect.y = (short)w_y;
577         if (rect_includespoint(&w_rect, rootx, rooty))
578             return TRUE;
579     }
580     return FALSE;
581 }
582
583 /*
584  * box_gc_init
585  */
586 static void
587 box_gc_init(
588     Widget widget, 
589     Display *display, 
590     Drawable drawable
591 )
592 {
593     XGCValues       gc_val;
594     unsigned long    cc_pixel = x_contrast_color(widget);
595     unsigned long   bg_pixel;
596
597     XtVaGetValues(widget, XtNbackground, &bg_pixel, NULL);
598
599     /* If gc doesn't exist yet, create it */
600     if (!box_gc) 
601     {
602         gc_val.foreground = bg_pixel ^ cc_pixel; 
603         gc_val.function = GXxor;
604         box_gc = XCreateGC(display, drawable,
605                 (GCFunction | GCForeground), &gc_val);
606     } 
607     else 
608     {
609         XSetForeground(display, box_gc, bg_pixel ^ cc_pixel);
610     }
611 }
612 /*
613  * fullscreen_gc_init
614  */
615 static void
616 fullscreen_gc_init(
617     Widget widget, 
618     Display *display, 
619     Drawable drawable
620 )
621 {
622     XGCValues       gc_val;
623     unsigned long   cc_pixel = x_contrast_color(widget);
624     unsigned long   bg_pixel;
625
626     XtVaGetValues(widget, XtNbackground, &bg_pixel, NULL);
627
628     /* If gc doesn't exist yet, create it */
629     if (!fullscreen_gc) 
630     {
631         gc_val.foreground = bg_pixel ^ cc_pixel; 
632         gc_val.function = GXxor;
633         gc_val.subwindow_mode = IncludeInferiors;
634         fullscreen_gc = XCreateGC(display, drawable,
635             (GCFunction|GCForeground|GCSubwindowMode), &gc_val);
636     } 
637     else 
638     {
639         XSetForeground(display, fullscreen_gc, bg_pixel ^ cc_pixel);
640     }
641 }
642
643 /*
644  * Return the X Window which is directly under the x,y position
645  * on the RootWindow
646  */
647 Window
648 x_xwin_at_rootxy(
649     Widget    widget,
650     int     x,
651     int     y,
652     int     *dstx,
653     int     *dsty
654 )
655 {
656     Display *dpy;
657     Window  child;
658     Window  rootwin, srcwin, dstwin;
659
660     dpy     = XtDisplay(widget);
661     rootwin = RootWindowOfScreen(XtScreen(widget));
662
663     if (XTranslateCoordinates(dpy, rootwin, rootwin, x, y,
664                   dstx, dsty, &child) == 0)
665         return ((Window) 0);
666
667     /*
668      * child is the XID of a child window of rootwin at 
669      * root cordinates (x,y)
670      * If child is NULL, we dropped on the root window
671      */
672     if (!child)
673         return ((Window) rootwin);
674  
675     srcwin = rootwin;
676     x      = *dstx;
677     y      = *dsty;
678     dstwin = child;
679  
680     for (;;)
681     {
682         if (XTranslateCoordinates(dpy, srcwin, dstwin, x, y,
683                   dstx, dsty, &child) == 0)
684             return ((Window) 0);
685
686         if (!child)
687             break;
688         else
689         {
690             srcwin  = dstwin;
691             dstwin  = child;
692             x       = *dstx;
693             y       = *dsty;
694         }
695     }
696
697     return (dstwin);
698
699 }
700
701 void
702 x_conn_fullscreen_init(
703     Widget      w,
704     Drawable    root_win
705 )
706 {
707     Display     *display;
708
709     display = XtDisplay(w);
710     fullscreen_gc_init(w, display, root_win);
711
712     /* Modify gc to used thick lines */
713     XSetLineAttributes(display, fullscreen_gc,
714         2, LineSolid, CapButt, JoinMiter);
715 }
716
717 /*
718  * Draw a line on the root window using fullscreen_gc
719  */
720 void
721 x_conn_fullscreen_chord(
722     Widget    w,
723     Drawable rootwin,
724     int    x0,
725     int    y0,
726     int    x1,
727     int    y1
728 )
729 {
730     Display    *display;
731     int        tmp;
732
733     display = XtDisplay(w);
734     XDrawLine(display, rootwin, fullscreen_gc, x0, y0, x1, y1);
735 }
736
737 void
738 x_conn_fullscreen_cleanup(
739     Widget      w
740 )
741 {
742     /* Restore back to solid lines */
743     XSetLineAttributes(XtDisplay(w), fullscreen_gc,
744             0, LineSolid, CapButt, JoinMiter);
745 }
746
747 Cursor
748 x_create_cursor(
749     Widget              widget,
750     Window              root_win,                
751     unsigned char       bits[],
752     unsigned short      width,
753     unsigned short      height,
754     unsigned int        xhot,
755     unsigned int        yhot
756 )
757 {
758     Pixmap      curs_pix;
759     Cursor      cursor;
760     XColor      fg_color;
761     XColor      bg_color;
762
763     curs_pix = XCreateBitmapFromData(XtDisplay(widget), root_win, (char*)bits,
764                                      width, height);
765     if (curs_pix == None)
766         return(None);
767
768     {
769         XrmValue       src, dst;
770         Pixel          fg_pixel, bg_pixel;
771
772         fg_pixel = BlackPixelOfScreen(XtScreen(widget));
773         bg_pixel = WhitePixelOfScreen(XtScreen(widget));
774
775         src.size = sizeof(Pixel);
776         dst.size = sizeof(XColor);
777
778         src.addr = (XPointer)&fg_pixel;
779         dst.addr = (XPointer)&fg_color;
780         XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
781
782         src.addr = (XPointer)&bg_pixel;
783         dst.addr = (XPointer)&bg_color;
784         XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
785     }
786
787     cursor = XCreatePixmapCursor(XtDisplay(widget), curs_pix, curs_pix,
788                                  &fg_color, &bg_color, xhot, yhot);
789     XFreePixmap(XtDisplay(widget), curs_pix);
790
791     return(cursor);
792
793 }
794
795
796 /*
797  * Counts the number of expose events or events that could cause
798  * exposures currently waiting in the queue.
799  *
800  * note: THIS DOES NOT FLUSH THE OUTPUT QUEUE, SO OTHER EVENTS MAY
801  * BE PENDING ON THE CLIENT SIDE (USE XFlush() TO AVOID THIS)
802  */
803 int             
804 x_get_num_pending_expose_events(Display *display)
805 {
806     int         num_expose_events = 0;
807     XEvent      event;
808
809     XCheckIfEvent(display, &event,
810         expose_count_predicate, (XPointer)&num_expose_events);
811     return num_expose_events;
812 }
813
814
815 /*
816  * If we return True from this predicate function, the event will
817  * be removed from the queue.  We don't want this to happen, so we
818  * will *always* return False, but increment the counter (the arg ptr)
819  * for each expose event.
820  */
821 static Bool             
822 expose_count_predicate(Display *display, XEvent *event, XPointer arg)
823 {
824 #define expose_count (*expose_count_out)
825     int         *expose_count_out = (int *)arg;
826
827     switch (event->type)
828     {
829         case CreateNotify:
830         case DestroyNotify:
831         case Expose:
832         case GraphicsExpose:
833         case MapNotify:
834         case MapRequest:
835         case NoExpose:
836         case UnmapNotify:
837         case VisibilityNotify:
838             ++expose_count;
839         break;
840     }
841
842     return False;
843 #undef expose_count
844 }
845