From: cpg@cs.utexas.edu (Carlos M. Puchol)
Newsgroups: fj.mail-lists.x-window
Subject: Scrolling canvases in XView3
Date: 28 Dec 92 14:01:21 GMT
Distribution: fj
Organization: Department of Computer Sciences, UT Austin

Date: 28 Dec 92 12:29:38 GMT
Message-Id: <ljtspiINNb1v@thor.cs.utexas.edu>
Newsgroups: comp.windows.open-look,comp.windows.x,alt.toolkits.xview

Hi I am having a problem with the XView toolkit. It may be a bug,
since the behaviour I get is different than what it is said
in the manual (Vol 7 of the X Series). If anyone has any clue
if I am right and the manual is wrong or the opposite,
please let me know.

I have a canvas and the canvas paint window is much bigger than
the view window, so I install scrollbars in the canvas. Initially,
C is visible and W is not.

    ------------------
    |         |      |
    | canvas  |      |
    |   C     |  W   |
    |         |      |
    |---------.      |
    |                |
    |  paint window  |
    |                |
    ------------------

When the scrollbars are pushed, the resize callback is called. The
params that it receives are the actual width and height of the paint
window.

The manual (third edition, page 99) says that ...

	"If the user scrolls the canvas, your canvas repaint procedure
	 will be called provided that the canvas WIN_RETAINED is set
	 to FALSE."

If WIN_RETAINED is TRUE the repaint procedure is not called either.

Now, in my application, the graphics in the whole W area are drawn
at the beginning of the program. If I draw some simple graphics (or
strings or somesuch), when I scroll C to see part of the area in W,
the graphics are there (no problem). I draw some simple junk graphics
for debugging purposes.

In the "real" application I have several Pixmaps that I copy (XCopyArea)
at the beginning of the program (basically shapes). There are lines which
join the shapes. When the whole thing is up, if I scroll C to see part of
W, I see "some" lines, but the rest of the window is blank (including the
background, which should be filled with the bacground Pixmap in the Graphic
Context).

My understanding after reading the manual is that the repaint proc should
be called with the newly exposed area if:

	WIN_RETAINED is set to FALSE
or
	(WIN_RETAINED  is set to TRUE) _and_ (the server has not saved
	the area just exposed)

I enclose a modified version of the program canvas_event.c from the manual,
which ilustrates the problems I have. Note that in this case, in my server
(and I guess in most servers) when the user scrolls, the strings are seen in
the W area, since the server keeps it.

Thanks a bunch in advance,

-- Carlos Puchol (cpg@cs.utexas.edu)

/*
 *  canvas_event.c
 *  Demonstrates how to get keyboard and mouse events in an canvas
 *  window.  Looks for keyboards, pointer movement and button
 *  events and displays the info in the canvas.
 */
#include <X11/Xlib.h>
#include <xview/xview.h>
#include <xview/canvas.h>
#include <xview/xv_xrect.h>
#include <xview/scrollbar.h>

void    event_proc(), repaint_proc(), resize_proc();
char    kbd_msg[128], ptr_msg[128], but_msg[128];

/*
 * main()
 *      Create a canvas specifying a repaint procedure.
 *      Get the paint window for the canvas and set the input
 *      mask and the event procedure.
 */
main(argc, argv)
int argc;
char *argv[];
{
    Frame       frame;
    Canvas      canvas;

    /* Initialize XView */
    xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);

    /* Create windows -- base frame and canvas. */
    frame = (Frame)xv_create(NULL, FRAME, NULL);

    canvas = (Canvas)xv_create(frame, CANVAS,
        XV_WIDTH,               400,
        XV_HEIGHT,              400,
	WIN_RETAINED, FALSE,
	CANVAS_AUTO_EXPAND, TRUE,
	CANVAS_AUTO_SHRINK, FALSE,
        CANVAS_X_PAINT_WINDOW,  TRUE,
        CANVAS_REPAINT_PROC,    repaint_proc,
	CANVAS_RESIZE_PROC, resize_proc,
        NULL);
    window_fit(frame);

    xv_create(canvas, SCROLLBAR,
	SCROLLBAR_DIRECTION, SCROLLBAR_HORIZONTAL,
	SCROLLBAR_PIXELS_PER_UNIT, 25,
	NULL);

    xv_create(canvas, SCROLLBAR,
	SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL,
	SCROLLBAR_PIXELS_PER_UNIT, 25,
	NULL);

    xv_set(canvas,
	CANVAS_WIDTH, 1200,
	CANVAS_HEIGHT, 1200,
	NULL);


    /* No input mask */

    /* Initial messages */
    strcpy(kbd_msg, "Keyboard: key press events");
    strcpy(ptr_msg, "Pointer: pointer movement events");
    strcpy(but_msg, "Button: button press events");

    /* Start event loop */
    xv_main_loop(frame);
}

/*
 * event_proc()
 *      Called when an event is received in the canvas window.
 *      Updates the keyboard, pointer and button message strings
 *      and then calls repaint_proc() to paint them to the window.
 */
void
event_proc(window, event)
Xv_Window window;
Event    *event;
{
    if (event_is_ascii(event))
        sprintf(kbd_msg, "Keyboard: key '%c' %d pressed at %d,%d",
                event_action(event), event_action(event),
                event_x(event), event_y(event));
    else
        switch (event_action(event)) {
            case KBD_USE:
                sprintf(kbd_msg, "Keyboard: got keyboard focus");
                break;
            case KBD_DONE:
                sprintf(kbd_msg, "Keyboard: lost keyboard focus");
                break;
            case LOC_MOVE:
                sprintf(ptr_msg, "Pointer: moved to %d,%d",
                    event_x(event), event_y(event));
                break;
            case LOC_DRAG:
                sprintf(ptr_msg, "Pointer: dragged to %d,%d",
                    event_x(event), event_y(event));
                break;
            case LOC_WINENTER:
                sprintf(ptr_msg, "Pointer: entered window at %d,%d",
                    event_x(event), event_y(event));
                break;
            case LOC_WINEXIT:
                sprintf(ptr_msg, "Pointer: exited window at %d,%d",
                    event_x(event), event_y(event));
                break;
            case ACTION_SELECT:
            case MS_LEFT:
                sprintf(but_msg, "Button: Select (Left) at %d,%d",
                    event_x(event), event_y(event));
                break;
            case ACTION_ADJUST:
            case MS_MIDDLE:
                sprintf(but_msg, "Button: Adjust (Middle) at %d,%d",
                    event_x(event), event_y(event));
                break;
            case ACTION_MENU:
            case MS_RIGHT:
                sprintf(but_msg, "Button: Menu (Right) at %d,%d",
                    event_x(event), event_y(event));
                break;
            default:
                return;
        }

    /* call repaint proc directly to update messages */
    repaint_proc((Canvas)NULL, window,
        (Display *)xv_get(window, XV_DISPLAY),
        xv_get(window, XV_XID), (Xv_xrectlist *) NULL);
}

/*
 * repaint_proc()
 *      Called to repaint the canvas in response to damage events
 *      and the initial painting of the canvas window.
 *      Displays the keyboard, pointer and button message strings
 *      after erasing the previous messages.
 */
void
repaint_proc(canvas, paint_window, dpy, xwin, xrects)
Canvas        canvas;           /* Ignored */
Xv_Window     paint_window;     /* Ignored */
Display      *dpy;
Window        xwin;
Xv_xrectlist *xrects;           /* Ignored */
{
    GC gc = DefaultGC(dpy, DefaultScreen(dpy));
    int i;

    fprintf(stderr,"Repaint called.\n");
    XClearWindow(dpy, xwin);
    XDrawString(dpy, xwin, gc, 25, 25, kbd_msg, strlen(kbd_msg));
    XDrawString(dpy, xwin, gc, 25, 50, ptr_msg, strlen(ptr_msg));
    XDrawString(dpy, xwin, gc, 25, 75, but_msg, strlen(but_msg));
    for (i=0; i < 100; i++)
        XDrawString(dpy, xwin, gc, 25+i*10, 75+i*10, but_msg, strlen(but_msg));
}


void resize_proc(canvas, width, height)
Canvas  canvas;
int     width, height;
{
        fprintf(stderr, "Resize callback called with W:%d H:%d.\n",
                width, height);
}