|
/*-----------------------------------------------------
test XSelectAsyncInput() call...
test drawing lines and segments in batch.
For oblique lines, the length of the line
is the equivalent calculated as the radius
of a circle...
argv[1] = starting length
argv[2] = ending length
argv[3] = increment
mouse button 1 - vertical lines
mouse button 3 - horizontal lines
mouse button 2 - diagonal lines - direction
determined by click-drag-release.
modify the comments at line 329+ to draw
lines or segments.
-----------------------------------------------------*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/resource.h>
#define MILLION 1000000.0
#ifndef HZ
#define HZ 60.0
#endif
#define STRING "Lines Test"
#define BORDER 1
#define FONT "vrb-25"
#define CVT (3.1415927/180.0)
#define ABS(a) ((a) >= 0 ? (a) : -(a))
float SCWetime(), SCWctime();
/* This structure forms the WM_HINTS property of the window,
* letting the window manager know how to handle this window.
* See Section 9.1 of the Xlib manual.
*/
XWMHints xwmh = {
(InputHint|StateHint), /* flags */
True, /* input */
NormalState, /* initial_state */
0, /* icon pixmap */
0, /* icon window */
0, 0, /* icon location */
0, /* icon mask */
0, /* Window group */
};
XSegment segments[5000];
int nsegments;
Display *dpy; /* X server connection */
Window win; /* Window ID */
static int ctrl_c_cancel;
void async_input_handler();
/*--------------------------------------------------------------*
* async input handler proc *
*--------------------------------------------------------------*/
void async_input_handler (bs)
unsigned long bs;
{
XEvent event;
static XComposeStatus kbd_status;
KeySym key_sym;
char key_ascii;
if (XCheckMaskEvent (dpy, KeyPressMask, &event))
{
switch (event.type)
{
case KeyPress:
if (XLookupString (&event, &key_ascii, 1, &key_sym, &kbd_status))
if (key_ascii == 3)
{
printf ("Ctrl-C interrupt!\n");
ctrl_c_cancel = True;
}
break;
default:
printf (" ack!!!\n");
break;
}
}
}
/*--------------------------------------------------------------*
* main *
*--------------------------------------------------------------*/
main (argc,argv)
int argc;
char **argv;
{
GC gc; /* GC to draw with */
XFontStruct *fontstruct; /* Font descriptor */
unsigned long fth, pad; /* Font size parameters */
unsigned long fg, bg, bd; /* Pixel values */
unsigned long bw; /* Border width */
XGCValues gcv; /* Struct for creating GC */
XEvent event; /* Event received */
XSizeHints xsh; /* Size hints for window manager */
char *geomSpec; /* Window geometry string */
XSetWindowAttributes xswa; /* Temporary Set Window Attribute struct */
int scr_num, i, j, k, start_x, start_y, end_x, end_y, e_x, e_y;
Screen *scr;
int dfd, dfd_mask, nfound, pressing = False;
float angle[38], sina[38], cosa[38];
int cx, cy, rx, ry;
XPoint points[38];
char *x_debug;
int x1, y1, x2, y2;
int repeat, batchcount;
float xx, yy, rr;
float cpu_start, cpu_end, elp_start, elp_end;
XComposeStatus kbd_status;
KeySym key_sym;
char key_ascii;
if ((dpy = XOpenDisplay(NULL)) == NULL)
{
fprintf(stderr, "%s: can't open %s\en", argv[0], XDisplayName(NULL));
exit(1);
}
fg = WhitePixelOfScreen (DefaultScreenOfDisplay (dpy));
bg = BlackPixelOfScreen (DefaultScreenOfDisplay (dpy));
xsh.flags = (PPosition | PSize);
xsh.height = 750;
xsh.width = 900;
xsh.x = 25;
xsh.y = 25;
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
xsh.x, xsh.y, xsh.width, xsh.height,
bw, bd, bg);
XSetStandardProperties(dpy, win, STRING, STRING, None, &argv, argc, &xsh);
XSetWMHints(dpy, win, &xwmh);
xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
xswa.bit_gravity = CenterGravity;
XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);
gcv.function = GXxor;
gcv.plane_mask = 0xFF;
gcv.foreground = fg;
gcv.background = bg;
gc = XCreateGC (dpy, win,
(GCFunction | GCPlaneMask | GCForeground | GCBackground),
&gcv);
/*....*/
XSynchronize (dpy, True);
/*....*/
XSelectInput (dpy, win,
ButtonPressMask | ButtonReleaseMask | KeyPressMask);
/*....
XSelectAsyncInput (dpy, win, KeyPressMask,
async_input_handler, NULL);
....*/
XMapWindow(dpy, win);
XFlush (dpy);
printf ("sleeping...\n");
sleep (3);
printf ("...done.\n");
XSetInputFocus (dpy, win, RevertToNone, CurrentTime);
XClearWindow(dpy, win);
gcv.function = GXxor;
gcv.foreground = fg;
XChangeGC (dpy, gc, GCForeground | GCFunction, &gcv);
for (j = 0; j <= 36; j++)
{
angle [j] = j * 10 * CVT;
sina [j] = sin (angle [j]);
cosa [j] = cos (angle [j]);
}
ctrl_c_cancel = False;
while (1)
{
XNextEvent (dpy, &event);
switch (event.type)
{
case KeyPress:
printf ("key press!\n");
if (XLookupString (&event, &key_ascii, 1, &key_sym, &kbd_status))
if (key_ascii == 3)
{
printf ("Ctrl-C interrupt!\n");
ctrl_c_cancel = True;
}
break;
case ButtonPress:
if (!pressing)
{
pressing = True;
start_x = event.xbutton.x;
start_y = event.xbutton.y;
}
else
{
printf ("\n");
pressing = False;
}
break;
case ButtonRelease:
if (pressing)
{
pressing = False;
repeat = 8;
batchcount = 250;
nsegments = repeat * batchcount;
end_x = event.xbutton.x;
end_y = event.xbutton.y;
for (k = atoi (argv [1]);
k <= atoi (argv [2]);
k += atoi (argv [3]))
{
if (ctrl_c_cancel)
{
ctrl_c_cancel = False;
break;
}
if (event.xbutton.button == Button2)
{
printf ("oblique... ");
/*....determine lengths of sides of triangle....*/
xx = (float) end_x - start_x;
yy = (float) end_y - start_y;
rr = (float) sqrt (xx*xx + yy*yy);
/*....normalize xx and yy....*/
xx = xx/rr;
yy = yy/rr;
/*....calculate the ending point of the line....*/
e_x = start_x + xx * k;
e_y = start_y + yy * k;
}
else if (event.xbutton.button == Button1)
{
printf ("vertical... ");
e_x = start_x;
e_y = start_y + k;
}
else /* MB3 */
{
printf ("horizontal... ");
e_x = start_x + k;
e_y = start_y;
}
x1 = start_x;
x2 = e_x;
y1 = start_y;
y2 = e_y;
elp_start = SCWetime (0.0);
cpu_start = SCWctime (0.0);
for (i = 0; i < repeat; i++)
{
for (j = 0; j < batchcount; j++)
{
segments [i * batchcount + j].x1 = x1 + j;
segments [i * batchcount + j].y1 = y1;
segments [i * batchcount + j].x2 = x2 + j;
segments [i * batchcount + j].y2 = y2;
}
x1 += 3;
x2 += 3;
y1 += 1;
y2 += 1;
}
for (i = 0; i < 100; i++)
/*...*/
XDrawSegments (dpy, win, gc, segments, nsegments);
/*....*/
/*...
XDrawLines (dpy, win, gc, segments, 2*nsegments,
CoordModeOrigin);
...*/
cpu_end = SCWctime (cpu_start);
elp_end = SCWetime (elp_start);
printf ("cpu: %5.3f elp: %5.3f (len=%d)\n",
cpu_end, elp_end, k);
} /*...k loop...*/
}
break;
default:
printf ("%c%c%cUnknown Event!\n", 7, 7, 7);
break;
}
}
}
float SCWctime (last)
float last;
{
struct rusage me,kids;
static int first_time = 1;
static double first_cpuse = 0.0;
double cpuse;
getrusage (RUSAGE_SELF, &me);
getrusage (RUSAGE_CHILDREN, &kids);
cpuse = me.ru_utime.tv_sec + me.ru_utime.tv_usec/MILLION +
/*
me.ru_stime.tv_sec + me.ru_stime.tv_usec/MILLION +
*/
kids.ru_utime.tv_sec + kids.ru_utime.tv_usec/MILLION;
/*
kids.ru_stime.tv_sec + kids.ru_stime.tv_usec/MILLION;
*/
if (first_time)
{
first_cpuse = cpuse;
first_time = 0;
}
return (cpuse - first_cpuse - last);
}
float SCWetime (last)
float last;
{
struct timeb elp_time;
static int first_time = 1;
static double first_elapsed = 0.0;
double elapsed;
ftime (&elp_time);
elapsed = elp_time.time + elp_time.millitm/1000.0;
if (first_time)
{
first_elapsed = elapsed;
first_time = 0;
}
return (elapsed - first_elapsed - last);
}
|