hvr@eng.sun.COM (Heather Rose) (03/08/90)
XView objects have an attribute, WIN_TRANSPARENT, which causes the object to absorb the underlying object as it's background. Any package which is a subclass of WINDOW should be able to understand this attribute. XView's WINDOW object, should be able to overlay any other XView object as long as it is a child of the frame (to avoid confusing the window manager). The WINDOW package will create an X11 window. Not all XView objects are X11 windows. XView objects also have an attribute WIN_SAVE_UNDER which will request the server to create backing store for an object. This may fail, so one should be prepared to repaint. If we put these all together, we get a simple method for creating a transparent overlay for temporary drawing or animation without affecting the appearance of the underlying object. Included below is a simple program derived from the online O'Reilly example, canvas/x_draw.c, which does just that. Regards, Heather ---------------------------- /* * overlay.c -- * Demonstrates the use of Xlib drawing functions inside an * XView canvas. Color is also used, but not required. * * Show how to draw using an overlay window on top of the canvas. */ #include <xview/xview.h> #include <xview/canvas.h> #include <xview/cms.h> #include <xview/xv_xrect.h> #include <xview/panel.h> /* indices into color table renders specified colors. */ #define WHITE 0 #define RED 1 #define GREEN 2 #define BLUE 3 #define ORANGE 4 #define AQUA 5 #define PINK 6 #define BLACK 7 Frame frame; Canvas canvas; Xv_Window overlay; int overlay_present = FALSE; GC gc; /* GC used for Xlib drawing */ unsigned long *colors; /* the color table */ /* * initialize cms data to support colors specified above. Assign * data to new cms -- use either static or dynamic cms depending * on -dynamic command line switch. */ main(argc, argv) int argc; char *argv[]; { unsigned char red[8], green[8], blue[8]; static char stipple_bits[] = {0xAA, 0xAA, 0x55, 0x55}; Panel panel; XFontStruct *font; Display *display; XGCValues gc_val; XID xid; void canvas_repaint(); Xv_cmsdata cms_data; int use_dynamic = FALSE; void toggle_overlay(); /* Create windows */ xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL); if (*++argv && !strcmp(*argv, "-dynamic")) use_dynamic = TRUE; frame = xv_create(NULL,FRAME, FRAME_LABEL, "xv_canvas_x_draw", XV_WIDTH, 400, XV_HEIGHT, 300, NULL); /* initialize RGB values for specified colors */ red[WHITE] = 255; green[WHITE] = 255; blue[WHITE] = 255; red[RED] = 255; green[RED] = 0; blue[RED] = 0; red[GREEN] = 0; green[GREEN] = 255; blue[GREEN] = 0; red[BLUE] = 0; green[BLUE] = 0; blue[BLUE] = 255; red[ORANGE] = 250; green[ORANGE] = 130; blue[ORANGE] = 80; red[AQUA] = 30; green[AQUA] = 230; blue[AQUA] = 250; red[PINK] = 230; green[PINK] = 30; blue[PINK] = 250; cms_data.type = use_dynamic? XV_DYNAMIC_CMS : XV_STATIC_CMS; cms_data.size = 8; cms_data.rgb_count = 8; cms_data.index = 0; cms_data.red = red; cms_data.green = green; cms_data.blue = blue; panel = xv_create(frame, PANEL, WIN_DYNAMIC_VISUAL, use_dynamic, WIN_CMS_NAME, "palette", WIN_CMS_DATA, &cms_data, NULL); (void) xv_create(panel, PANEL_MESSAGE, PANEL_LABEL_STRING, "Press button to toggle overlay", NULL); (void) xv_create(panel, PANEL_BUTTON, PANEL_LABEL_STRING, "overlay", PANEL_NOTIFY_PROC, toggle_overlay, NULL); window_fit_height(panel); canvas = xv_create(frame, CANVAS, CANVAS_REPAINT_PROC, canvas_repaint, CANVAS_X_PAINT_WINDOW, TRUE, WIN_DYNAMIC_VISUAL, use_dynamic, WIN_CMS_NAME, "palette", WIN_CMS_DATA, &cms_data, NULL); display = (Display *)xv_get(frame, XV_DISPLAY); xid = (XID)xv_get(canvas_paint_window(canvas), XV_XID); if (!(font = XLoadQueryFont(display, "fixed"))) { puts("cannot load fixed font"); exit(1); } /* Create and initialize GC */ gc_val.font = font->fid; gc_val.stipple = XCreateBitmapFromData(display, xid, stipple_bits, 16, 2); gc = XCreateGC(display, xid, GCFont | GCStipple, &gc_val); /* get the colormap from the canvas now that * the cms has been installed */ colors = (unsigned long *)xv_get(canvas, WIN_X_COLOR_INDICES); /* Start event loop */ xv_main_loop(frame); } /* * Draws onto the canvas using Xlib drawing functions. */ void canvas_repaint(canvas, pw, display, xid, xrects) Canvas canvas; Xv_Window pw; Display *display; Window xid; Xv_xrectlist *xrects; { static XPoint box[] = { {0,0}, {100,100}, {0,-100}, {-100,100}, {0,-100} }; static XPoint points[] = { {0,0}, /* this point to be overwritten below */ {25,0}, {25,0}, {25,0}, {25,0}, {-100,25}, {25,0}, {25,0}, {25,0}, {25,0}, {-100,25}, {25,0}, {25,0}, {25,0}, {25,0}, {-100,25}, {25,0}, {25,0}, {25,0}, {25,0}, {-100,25}, {25,0}, {25,0}, {25,0}, {25,0}, {-100,25}, }; XSetForeground(display, gc, colors[RED]); XDrawString(display, xid, gc, 30, 20, "XFillRectangle", 14); XFillRectangle(display, xid, gc, 25, 25, 100, 100); XSetFunction(display, gc, GXinvert); XFillRectangle(display, xid, gc, 50, 50, 50, 50); XSetFunction(display, gc, GXcopy); XSetForeground(display, gc, colors[BLACK]); XDrawString(display, xid, gc, 155, 20, "XFillRect - stipple", 19); XSetFillStyle(display, gc, FillStippled); XFillRectangle(display, xid, gc, 150, 25, 100, 100); XSetFillStyle(display, gc, FillSolid); XSetForeground(display, gc, colors[BLUE]); XDrawString(display, xid, gc, 280, 20, "XDrawPoints", 11); points[0].x = 275; points[0].y = 25; XDrawPoints(display, xid, gc, points, sizeof(points)/sizeof(XPoint), CoordModePrevious); XSetForeground(display, gc, colors[ORANGE]); XDrawString(display, xid, gc, 30, 145, "XDrawLine - solid", 17); XDrawLine(display, xid, gc, 25, 150, 125, 250); XDrawLine(display, xid, gc, 25, 250, 125, 150); XSetForeground(display, gc, colors[AQUA]); XDrawString(display, xid, gc, 155, 145, "XDrawLine - dashed", 18); XSetLineAttributes(display, gc, 5, LineDoubleDash, CapButt, JoinMiter); XDrawLine(display, xid, gc, 150, 150, 250, 250); XDrawLine(display, xid, gc, 150, 250, 250, 150); XSetLineAttributes(display, gc, 0, LineSolid, CapButt, JoinMiter); XSetForeground(display, gc, colors[PINK]); XDrawString(display, xid, gc, 280, 145, "XDrawLines", 10); box[0].x = 275; box[0].y = 150; XDrawLines(display, xid, gc, box, 5, CoordModePrevious); XSetForeground(display, gc, colors[GREEN]); XDrawRectangle(display, xid, gc, 5, 5, xv_get(pw, XV_WIDTH)-10, xv_get(pw, XV_HEIGHT)-10); XDrawRectangle(display, xid, gc, 7, 7, xv_get(pw, XV_WIDTH)-14, xv_get(pw, XV_HEIGHT)-14); } void toggle_overlay() { Display *display; XID xid; Xv_Window create_overlay(); if (overlay_present == FALSE) { overlay = create_overlay(frame, canvas); display = (Display *)xv_get(frame, XV_DISPLAY); xid = (XID)xv_get(overlay, XV_XID); XSetForeground(display, gc, colors[BLUE]); XSetFillStyle(display, gc, FillSolid); XDrawString(display, xid, gc, 50, 50, "Drawing in the Overlay", 22); XFillRectangle(display, xid, gc, 100, 100, 200, 200); XSetForeground(display, gc, colors[PINK]); XFillRectangle(display, xid, gc, 150, 150, 150, 150); overlay_present = TRUE; } else { xv_destroy(overlay); overlay_present = FALSE; } } Xv_Window create_overlay(owner, below) Xv_Window owner, below; { Xv_Window overlay; overlay = (Xv_Window) xv_create(owner, WINDOW, WIN_TRANSPARENT, WIN_SAVE_UNDER, TRUE, XV_X, (int) xv_get(below, XV_X, NULL), XV_Y, (int) xv_get(below, XV_Y, NULL), XV_WIDTH, (int) xv_get(below, XV_WIDTH, NULL), XV_HEIGHT, (int) xv_get(below, XV_HEIGHT, NULL), WIN_CMS_NAME, "palette", NULL); return(overlay); }