[comp.windows.x] XView: WIN_TRANSPARENT, overlays, WINDOW

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);
}