|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: E T
Length: 13630 (0x353e) Types: TextFile Names: »Eyes.c«
└─⟦276d19d6e⟧ Bits:30007243 EUUGD5_I: X11R5 └─⟦af7d3f39a⟧ »./mit-2/mit-2.00« └─⟦0abaffd9e⟧ └─⟦this⟧ »mit/demos/xeyes/Eyes.c«
/* $XConsortium: Eyes.c,v 1.26 91/08/23 12:26:40 gildea Exp $ */ /* * Copyright 1991 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /* * Eyes.c * * a widget which follows the mouse around */ # include <X11/Xos.h> # include <stdio.h> # include <X11/IntrinsicP.h> # include <X11/StringDefs.h> # include <X11/Xmu/Converters.h> # include "EyesP.h" # include <math.h> # include <X11/extensions/shape.h> #if (defined(SVR4) || defined(SYSV) && defined(SYSV386)) && __STDC__ extern double hypot(double, double); #endif #define offset(field) XtOffsetOf(EyesRec, eyes.field) #define goffset(field) XtOffsetOf(WidgetRec, core.field) static XtResource resources[] = { {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), goffset(width), XtRImmediate, (XtPointer) 150}, {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), goffset(height), XtRImmediate, (XtPointer) 100}, {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(puppixel), XtRString, XtDefaultForeground}, {XtNoutline, XtCForeground, XtRPixel, sizeof(Pixel), offset(outline), XtRString, XtDefaultForeground}, {XtNcenterColor, XtCBackground, XtRPixel, sizeof (Pixel), offset(center), XtRString, XtDefaultBackground}, {XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean), offset (reverse_video), XtRImmediate, (XtPointer) FALSE}, {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int), offset (backing_store), XtRString, "default"}, {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean), offset (shape_window), XtRImmediate, (XtPointer) TRUE}, }; #undef offset #undef goffset # define NUM_EYES 2 # define EYE_X(n) ((n) * 2.0) # define EYE_Y(n) (0.0) # define EYE_OFFSET (0.1) /* padding between eyes */ # define EYE_THICK (0.175) /* thickness of eye rim */ # define BALL_WIDTH (0.3) # define BALL_PAD (0.05) # define EYE_WIDTH (2.0 - (EYE_THICK + EYE_OFFSET) * 2) # define EYE_HEIGHT EYE_WIDTH # define EYE_HWIDTH (EYE_WIDTH / 2.0) # define EYE_HHEIGHT (EYE_HEIGHT / 2.0) # define BALL_HEIGHT BALL_WIDTH # define BALL_DIST ((EYE_WIDTH - BALL_WIDTH) / 2.0 - BALL_PAD) # define W_MIN_X (-1.0 + EYE_OFFSET) # define W_MAX_X (3.0 - EYE_OFFSET) # define W_MIN_Y (-1.0 + EYE_OFFSET) # define W_MAX_Y (1.0 - EYE_OFFSET) # define TPointEqual(a, b) ((a).x == (b).x && (a).y == (b).y) # define XPointEqual(a, b) ((a).x == (b).x && (a).y == (b).y) static int delays[] = { 50, 100, 200, 400, 0 }; static void Initialize(), Realize(), Destroy(); static void Redisplay(), Resize (); static Boolean SetValues(); static int repaint_window(); static void draw_it (); static void ClassInitialize(); EyesClassRec eyesClassRec = { { /* core fields */ /* superclass */ &widgetClassRec, /* class_name */ "Eyes", /* size */ sizeof(EyesRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, } }; static void ClassInitialize() { XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, NULL, 0 ); } WidgetClass eyesWidgetClass = (WidgetClass) &eyesClassRec; /* ARGSUSED */ static void Initialize (greq, gnew) Widget greq, gnew; { EyesWidget w = (EyesWidget)gnew; XtGCMask valuemask; XGCValues myXGCV; int shape_event_base, shape_error_base; /* * set the colors if reverse video; these are the colors used: * * background - paper white * foreground - text, ticks black * border - border black (foreground) * * This doesn't completely work since the parent has already made up a * border. Sigh. */ if (w->eyes.reverse_video) { Pixel fg = w->eyes.puppixel; Pixel bg = w->core.background_pixel; if (w->core.border_pixel == fg) w->core.border_pixel = bg; if (w->eyes.outline == fg) w->eyes.outline = bg; if (w->eyes.center == bg) w->eyes.center = fg; w->eyes.puppixel = bg; w->core.background_pixel = fg; } myXGCV.foreground = w->eyes.puppixel; myXGCV.background = w->core.background_pixel; valuemask = GCForeground | GCBackground; w->eyes.pupGC = XtGetGC(gnew, valuemask, &myXGCV); myXGCV.foreground = w->eyes.outline; valuemask = GCForeground | GCBackground; w->eyes.outGC = XtGetGC(gnew, valuemask, &myXGCV); myXGCV.foreground = w->eyes.center; myXGCV.background = w->eyes.puppixel; valuemask = GCForeground | GCBackground; w->eyes.centerGC = XtGetGC(gnew, valuemask, &myXGCV); w->eyes.update = 0; /* wait for Realize to add the timeout */ w->eyes.interval_id = 0; w->eyes.pupil[0].x = w->eyes.pupil[1].x = -1000; w->eyes.pupil[0].y = w->eyes.pupil[1].y = -1000; if (w->eyes.shape_window && !XShapeQueryExtension (XtDisplay (w), &shape_event_base, &shape_error_base)) w->eyes.shape_window = False; w->eyes.shape_mask = 0; w->eyes.shapeGC = 0; } static void Resize (gw) Widget gw; { EyesWidget w = (EyesWidget) gw; XGCValues xgcv; Widget parent; int x, y; if (XtIsRealized (gw)) { XClearWindow (XtDisplay (w), XtWindow (w)); SetTransform (&w->eyes.t, 0, w->core.width, w->core.height, 0, W_MIN_X, W_MAX_X, W_MIN_Y, W_MAX_Y); if (w->eyes.shape_window) { w->eyes.shape_mask = XCreatePixmap (XtDisplay (w), XtWindow (w), w->core.width, w->core.height, 1); if (!w->eyes.shapeGC) w->eyes.shapeGC = XCreateGC (XtDisplay (w), w->eyes.shape_mask, 0, &xgcv); XSetForeground (XtDisplay (w), w->eyes.shapeGC, 0); XFillRectangle (XtDisplay (w), w->eyes.shape_mask, w->eyes.shapeGC, 0, 0, w->core.width, w->core.height); XSetForeground (XtDisplay (w), w->eyes.shapeGC, 1); eyeLiner (w, w->eyes.shape_mask, w->eyes.shapeGC, (GC) 0, 0); eyeLiner (w, w->eyes.shape_mask, w->eyes.shapeGC, (GC) 0, 1); x = y = 0; for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) { x += parent->core.x + parent->core.border_width; x += parent->core.y + parent->core.border_width; } XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding, x, y, w->eyes.shape_mask, ShapeSet); XFreePixmap (XtDisplay (w), w->eyes.shape_mask); } } } static void Realize (gw, valueMask, attrs) Widget gw; XtValueMask *valueMask; XSetWindowAttributes *attrs; { EyesWidget w = (EyesWidget)gw; if (w->eyes.backing_store != Always + WhenMapped + NotUseful) { attrs->backing_store = w->eyes.backing_store; *valueMask |= CWBackingStore; } XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent, *valueMask, attrs ); Resize (gw); w->eyes.interval_id = XtAppAddTimeOut(XtWidgetToApplicationContext(gw), delays[w->eyes.update], draw_it, (XtPointer)gw); } static void Destroy (gw) Widget gw; { EyesWidget w = (EyesWidget)gw; if (w->eyes.interval_id) XtRemoveTimeOut (w->eyes.interval_id); XtReleaseGC(gw, w->eyes.pupGC); XtReleaseGC(gw, w->eyes.outGC); XtReleaseGC(gw, w->eyes.centerGC); } /* ARGSUSED */ static void Redisplay(gw, event, region) Widget gw; XEvent *event; Region region; { EyesWidget w; w = (EyesWidget) gw; w->eyes.pupil[0].x = -1000; w->eyes.pupil[0].y = -1000; w->eyes.pupil[1].x = -1000; w->eyes.pupil[1].y = -1000; (void) repaint_window ((EyesWidget)gw); } static TPoint computePupil (num, mouse) int num; TPoint mouse; { double cx, cy; double dist; double angle; double x, y; double h; double dx, dy; double cosa, sina; TPoint ret; dx = mouse.x - EYE_X(num); dy = mouse.y - EYE_Y(num); if (dx == 0 && dy == 0) { cx = EYE_X(num); cy = EYE_Y(num); } else { angle = atan2 ((double) dy, (double) dx); cosa = cos (angle); sina = sin (angle); h = hypot (EYE_HHEIGHT * cosa, EYE_HWIDTH * sina); x = (EYE_HWIDTH * EYE_HHEIGHT) * cosa / h; y = (EYE_HWIDTH * EYE_HHEIGHT) * sina / h; dist = BALL_DIST * hypot (x, y); if (dist > hypot ((double) dx, (double) dy)) { cx = dx + EYE_X(num); cy = dy + EYE_Y(num); } else { cx = dist * cosa + EYE_X(num); cy = dist * sina + EYE_Y(num); } } ret.x = cx; ret.y = cy; return ret; } static void computePupils (mouse, pupils) TPoint mouse; TPoint pupils[2]; { pupils[0] = computePupil (0, mouse); pupils[1] = computePupil (1, mouse); } /* ARGSUSED */ static void draw_it(client_data, id) XtPointer client_data; XtIntervalId *id; /* unused */ { EyesWidget w = (EyesWidget)client_data; Window rep_root, rep_child; int rep_rootx, rep_rooty; unsigned int rep_mask; int dx, dy; TPoint mouse; Display *dpy = XtDisplay (w); Window win = XtWindow (w); TPoint newpupil[2]; XPoint xnewpupil, xpupil; if (XtIsRealized((Widget)w)) { XQueryPointer (dpy, win, &rep_root, &rep_child, &rep_rootx, &rep_rooty, &dx, &dy, &rep_mask); mouse.x = Tx(dx, dy, &w->eyes.t); mouse.y = Ty(dx, dy, &w->eyes.t); if (!TPointEqual (mouse, w->eyes.mouse)) { computePupils (mouse, newpupil); xpupil.x = Xx(w->eyes.pupil[0].x, w->eyes.pupil[0].y, &w->eyes.t); xpupil.y = Xy(w->eyes.pupil[0].x, w->eyes.pupil[0].y, &w->eyes.t); xnewpupil.x = Xx(newpupil[0].x, newpupil[0].y, &w->eyes.t); xnewpupil.y = Xy(newpupil[0].x, newpupil[0].y, &w->eyes.t); if (!XPointEqual (xpupil, xnewpupil)) { if (w->eyes.pupil[0].x != -1000 || w->eyes.pupil[0].y != -1000) eyeBall (w, w->eyes.centerGC, 0); w->eyes.pupil[0] = newpupil[0]; eyeBall (w, w->eyes.pupGC, 0); } xpupil.x = Xx(w->eyes.pupil[1].x, w->eyes.pupil[1].y, &w->eyes.t); xpupil.y = Xy(w->eyes.pupil[1].x, w->eyes.pupil[1].y, &w->eyes.t); xnewpupil.x = Xx(newpupil[1].x, newpupil[1].y, &w->eyes.t); xnewpupil.y = Xy(newpupil[1].x, newpupil[1].y, &w->eyes.t); if (!XPointEqual (xpupil, xnewpupil)) { if (w->eyes.pupil[1].x != -1 || w->eyes.pupil[1].y != -1) eyeBall (w, w->eyes.centerGC, 1); w->eyes.pupil[1] = newpupil[1]; eyeBall (w, w->eyes.pupGC, 1); } w->eyes.mouse = mouse; w->eyes.update = 0; } else { if (delays[w->eyes.update + 1] != 0) ++w->eyes.update; } } w->eyes.interval_id = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w), delays[w->eyes.update], draw_it, (XtPointer)w); } /* draw_it */ static repaint_window (w) EyesWidget w; { if (XtIsRealized ((Widget) w)) { eyeLiner (w, XtWindow (w), w->eyes.outGC, w->eyes.centerGC, 0); eyeLiner (w, XtWindow (w), w->eyes.outGC, w->eyes.centerGC, 1); computePupils (w->eyes.mouse, w->eyes.pupil); eyeBall (w, w->eyes.pupGC, 0); eyeBall (w, w->eyes.pupGC, 1); } } /* ARGSUSED */ static Boolean SetValues (current, request, new) Widget current, request, new; { return( FALSE ); } eyeLiner (w, d, outgc, centergc, num) EyesWidget w; Drawable d; GC outgc, centergc; int num; { Display *dpy = XtDisplay(w); TFillArc (dpy, d, outgc, &w->eyes.t, EYE_X(num) - EYE_HWIDTH - EYE_THICK, EYE_Y(num) - EYE_HHEIGHT - EYE_THICK, EYE_WIDTH + EYE_THICK * 2.0, EYE_HEIGHT + EYE_THICK * 2.0, 90 * 64, 360 * 64); if (centergc) { TFillArc (dpy, d, centergc, &w->eyes.t, EYE_X(num) - EYE_HWIDTH, EYE_Y(num) - EYE_HHEIGHT, EYE_WIDTH, EYE_HEIGHT, 90 * 64, 360 * 64); } } eyeBall (w, gc, num) EyesWidget w; GC gc; int num; { Display *dpy = XtDisplay(w); Window win = XtWindow(w); TFillArc (dpy, win, gc, &w->eyes.t, w->eyes.pupil[num].x - BALL_WIDTH / 2.0, w->eyes.pupil[num].y - BALL_HEIGHT / 2.0, BALL_WIDTH, BALL_HEIGHT, 90 * 64, 360 * 64); }