2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
25 * $XConsortium: x_util.c /main/3 1995/11/06 17:57:42 rswiston $
27 * @(#)x_util.c 1.21 21 Nov 1994 cde_app_builder/src/ab
29 * RESTRICTED CONFIDENTIAL INFORMATION:
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
39 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
45 ***********************************************************************
46 * x_util.c - X11 & Xt support functions
49 ***********************************************************************
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"
62 /*************************************************************************
64 ** Private Function Declarations **
66 **************************************************************************/
67 static void box_gc_init(
72 static void fullscreen_gc_init(
77 static Bool expose_count_predicate(
83 /*************************************************************************
87 **************************************************************************/
89 static GC fullscreen_gc;
93 /*************************************************************************
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;
103 /*************************************************************************
105 ** Function Definitions **
107 **************************************************************************/
110 * Load all bitmaps to be used for cursors
113 x_load_cursor_bitmaps(
118 if (!XtIsRealized(widget))
120 if (util_get_verbosity() > 0)
121 fprintf(stderr,"x_load_cursor_bitmaps: widget must be realized\n");
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),
129 (char*)copy_cursor_bm_bits,
132 BlackPixelOfScreen(XtScreen(widget)),
133 WhitePixelOfScreen(XtScreen(widget)),
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),
140 (char*)move_cursor_bm_bits,
143 BlackPixelOfScreen(XtScreen(widget)),
144 WhitePixelOfScreen(XtScreen(widget)),
153 * return a cursor which is the image of the passed-in pixmap with
154 * a stencil around it
157 x_create_stencil_cursor(
160 unsigned short width,
161 unsigned short height,
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;
177 if (!XtIsRealized(widget))
179 if (util_get_verbosity() > 0)
180 fprintf(stderr,"x_create_stencil_cursor: widget must be realized\n");
184 dpy = XtDisplay(widget);
185 win = XtWindow(widget);
188 c_height = height+ 2;
192 XQueryBestCursor(dpy, win, c_width, c_height, &max_width, &max_height);
194 if ( max_width < c_width)
195 c_width = max_width - 2;
196 if ( max_height < c_height)
197 c_height = max_height - 2;
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;
204 cursor_pixmap = XCreatePixmap(dpy, win, c_width, c_height, 1);
205 mask_pixmap = XCreatePixmap(dpy, win, c_width, c_height, 1);
211 Pixel fg_pixel, bg_pixel;
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);
218 fg_pixel = BlackPixelOfScreen(XtScreen(widget));
219 bg_pixel = WhitePixelOfScreen(XtScreen(widget));
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);
227 src.addr = (XPointer)&bg_pixel;
228 dst.addr = (XPointer)&bg_color;
229 XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
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);
236 XSetFunction(dpy, c_gc, GXcopy);
237 XCopyArea(dpy, pixmap, cursor_pixmap, c_gc, 0, 0, c_width, c_height, 1, 1);
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++)
243 for (j = -1; j <= 1; j++)
245 x_graphics_op(dpy, mask_pixmap, c_gc, i, j,
251 cursor = XCreatePixmapCursor(dpy, cursor_pixmap, mask_pixmap,
252 &fg_color, &bg_color, c_xhot, c_yhot);
254 XFreePixmap(dpy, mask_pixmap);
255 XFreePixmap(dpy, cursor_pixmap);
273 XGCValues orig, changes;
274 unsigned long changes_mask = GCTileStipXOrigin |
278 /* Save original GC state */
279 XGetGCValues(dpy, gc, changes_mask, &orig);
281 changes.ts_x_origin = x;
282 changes.ts_y_origin = y;
283 changes.stipple = src;
284 changes.fill_style = FillOpaqueStippled;
286 XChangeGC(dpy, gc, changes_mask | GCStipple, &changes);
287 XFillRectangle(dpy, dest, gc, x, y, width, height);
289 /* Restore original GC state (all but stipple) */
290 XChangeGC(dpy, gc, changes_mask, &orig);
301 XtVaGetValues(widget,
302 XtNwidth, (XtArgVal)&(rect->width),
303 XtNheight, (XtArgVal)&(rect->height),
304 XtNx, (XtArgVal)&(rect->x),
305 XtNy, (XtArgVal)&(rect->y),
310 * Figure out the total area occupied by two rects.
313 x_get_rect_bounding(XRectangle *r1, XRectangle *r2)
319 else if (rect_isnull(r2))
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)
326 r.height = max(r1->y + (short)r1->height, r2->y + (short)r2->height)
333 x_adjust_rect_margin(
360 /* Get display and drawable */
361 display = (Display *)XtDisplay(widget);
363 /* Initialize gc before use */
364 box_gc_init(widget, display, drawable);
367 * Transpose the coordinates if either the
368 * width or height of the rectangle is negative.
383 XDrawRectangle(display, drawable, box_gc, x0, y0, x1-x0, y1-y0);
395 x_box(widget, XtWindow(widget), r->x, r->y, rect_right(r), rect_bottom(r));
410 /* Get display and drawable */
411 display = (Display *)XtDisplay(widget);
413 /* Initialize gc before use */
414 box_gc_init(widget, display, drawable);
416 /* Modify gc to used dashed lines */
417 XSetLineAttributes(display, box_gc,
418 0, LineOnOffDash, CapButt, JoinMiter);
420 XDrawRectangle(display, drawable, box_gc,
421 r->x, r->y, r->width -1, r->height -1);
423 /* Restore back to solid lines */
424 XSetLineAttributes(display, box_gc,
425 0, LineSolid, CapButt, JoinMiter);
441 display = XtDisplay(w);
442 fullscreen_gc_init(w, display, rootwin);
445 * Transpose the coordinates if either the
446 * width or height of the rectangle is negative.
461 XDrawRectangle(display, rootwin, fullscreen_gc,
462 x0, y0, x1 - x0, y1 - y0);
466 x_fullscreen_preview_box(
478 display = XtDisplay(w);
481 * Transpose the coordinates if either the
482 * width or height of the rectangle is negative.
497 XDrawRectangle(display, rootwin, fullscreen_gc,
498 x0 - 1, y0 - 1, x1 - x0 + 2, y1 - y0 + 2);
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.
513 unsigned int bg_pixel;
516 XtVaGetValues(widget, XtNbackground, &bg_pixel, NULL);
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);
524 intensity = ((float) bg_color.red * 0.3 + (float) bg_color.green * 0.59 +
525 (float) bg_color.blue * 0.12) / 255.0;
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);
532 return BlackPixelOfScreen(XtScreen(widget));
534 return WhitePixelOfScreen(XtScreen(widget));
539 x_widget_translate_xy(
548 Window src_win = XtWindow(src);
549 Window dst_win = dst? XtWindow((Widget)dst) : RootWindowOfScreen(XtScreen(src));
552 return(XTranslateCoordinates(XtDisplay(src), src_win, dst_win,
553 src_x, src_y, p_dst_x, p_dst_y, &child));
557 x_rootxy_inside_widget(
563 Window root_win = RootWindowOfScreen(XtScreen(w));
570 x_get_widget_rect(w, &w_rect);
572 XTranslateCoordinates(XtDisplay(w), XtWindow(w),
573 root_win, 0, 0, &w_x, &w_y, &win_below);
575 w_rect.x = (short)w_x;
576 w_rect.y = (short)w_y;
577 if (rect_includespoint(&w_rect, rootx, rooty))
594 unsigned long cc_pixel = x_contrast_color(widget);
595 unsigned long bg_pixel;
597 XtVaGetValues(widget, XtNbackground, &bg_pixel, NULL);
599 /* If gc doesn't exist yet, create it */
602 gc_val.foreground = bg_pixel ^ cc_pixel;
603 gc_val.function = GXxor;
604 box_gc = XCreateGC(display, drawable,
605 (GCFunction | GCForeground), &gc_val);
609 XSetForeground(display, box_gc, bg_pixel ^ cc_pixel);
623 unsigned long cc_pixel = x_contrast_color(widget);
624 unsigned long bg_pixel;
626 XtVaGetValues(widget, XtNbackground, &bg_pixel, NULL);
628 /* If gc doesn't exist yet, create it */
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);
639 XSetForeground(display, fullscreen_gc, bg_pixel ^ cc_pixel);
644 * Return the X Window which is directly under the x,y position
658 Window rootwin, srcwin, dstwin;
660 dpy = XtDisplay(widget);
661 rootwin = RootWindowOfScreen(XtScreen(widget));
663 if (XTranslateCoordinates(dpy, rootwin, rootwin, x, y,
664 dstx, dsty, &child) == 0)
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
673 return ((Window) rootwin);
682 if (XTranslateCoordinates(dpy, srcwin, dstwin, x, y,
683 dstx, dsty, &child) == 0)
702 x_conn_fullscreen_init(
709 display = XtDisplay(w);
710 fullscreen_gc_init(w, display, root_win);
712 /* Modify gc to used thick lines */
713 XSetLineAttributes(display, fullscreen_gc,
714 2, LineSolid, CapButt, JoinMiter);
718 * Draw a line on the root window using fullscreen_gc
721 x_conn_fullscreen_chord(
733 display = XtDisplay(w);
734 XDrawLine(display, rootwin, fullscreen_gc, x0, y0, x1, y1);
738 x_conn_fullscreen_cleanup(
742 /* Restore back to solid lines */
743 XSetLineAttributes(XtDisplay(w), fullscreen_gc,
744 0, LineSolid, CapButt, JoinMiter);
751 unsigned char bits[],
752 unsigned short width,
753 unsigned short height,
763 curs_pix = XCreateBitmapFromData(XtDisplay(widget), root_win, (char*)bits,
765 if (curs_pix == None)
770 Pixel fg_pixel, bg_pixel;
772 fg_pixel = BlackPixelOfScreen(XtScreen(widget));
773 bg_pixel = WhitePixelOfScreen(XtScreen(widget));
775 src.size = sizeof(Pixel);
776 dst.size = sizeof(XColor);
778 src.addr = (XPointer)&fg_pixel;
779 dst.addr = (XPointer)&fg_color;
780 XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
782 src.addr = (XPointer)&bg_pixel;
783 dst.addr = (XPointer)&bg_color;
784 XtConvertAndStore(widget, XtRPixel, &src, XtRColor, &dst);
787 cursor = XCreatePixmapCursor(XtDisplay(widget), curs_pix, curs_pix,
788 &fg_color, &bg_color, xhot, yhot);
789 XFreePixmap(XtDisplay(widget), curs_pix);
797 * Counts the number of expose events or events that could cause
798 * exposures currently waiting in the queue.
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)
804 x_get_num_pending_expose_events(Display *display)
806 int num_expose_events = 0;
809 XCheckIfEvent(display, &event,
810 expose_count_predicate, (XPointer)&num_expose_events);
811 return num_expose_events;
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.
822 expose_count_predicate(Display *display, XEvent *event, XPointer arg)
824 #define expose_count (*expose_count_out)
825 int *expose_count_out = (int *)arg;
837 case VisibilityNotify: