If -blinky is given and XI2 is available, draw one eye for each master pointer (up to 8).
No support for run-time addition or removal of master devices. This is xeyes, after all. Signed-off-by: Peter Hutterer <[email protected]> --- It's friday here... Eyes.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++------------ Eyes.h | 4 + EyesP.h | 14 ++++- Makefile.am | 3 + configure.ac | 5 ++ xeyes.c | 11 ++++ 6 files changed, 174 insertions(+), 38 deletions(-) diff --git a/Eyes.c b/Eyes.c index 3965833..b3676cc 100644 --- a/Eyes.c +++ b/Eyes.c @@ -36,6 +36,10 @@ from the X Consortium. * a widget which follows the mouse around */ +#if HAVE_CONFIG_H +#include <config.h> +#endif + # include <X11/Xos.h> # include <stdio.h> # include <X11/IntrinsicP.h> @@ -45,6 +49,10 @@ from the X Consortium. # include <math.h> # include <X11/extensions/shape.h> +#if HAVE_XI2 +#include <X11/extensions/XInput2.h> +#endif + #if (defined(SVR4) || defined(SYSV) && defined(i386)) extern double hypot(double, double); #endif @@ -69,6 +77,10 @@ static XtResource resources[] = { offset (backing_store), XtRString, "default"}, {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean), offset (shape_window), XtRImmediate, (XtPointer) TRUE}, +#if HAVE_XI2 + {XtNBlinky, XtCBlinky, XtRBoolean, sizeof (Boolean), + offset (blinky), XtRImmediate, (XtPointer) FALSE}, +#endif }; #undef offset @@ -87,7 +99,7 @@ static XtResource resources[] = { # 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_MAX_X (w->eyes.num_eyes * 2.0 - 1 - EYE_OFFSET) # define W_MIN_Y (-1.0 + EYE_OFFSET) # define W_MAX_Y (1.0 - EYE_OFFSET) @@ -115,6 +127,7 @@ static void Initialize ( XtGCMask valuemask; XGCValues myXGCV; int shape_event_base, shape_error_base; + int i; /* * set the colors if reverse video; these are the colors used: @@ -158,10 +171,12 @@ static void Initialize ( /* 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; + for (i = 0; i < w->eyes.num_eyes; i++) { + w->eyes.pupil[i].x = -1000; + w->eyes.pupil[i].y = -1000; + w->eyes.mouse[i].x = w->eyes.mouse[i].y = -1000; + } - w->eyes.mouse.x = w->eyes.mouse.y = -1000; if (w->eyes.shape_window && !XShapeQueryExtension (XtDisplay (w), &shape_event_base, @@ -235,11 +250,11 @@ static TPoint computePupil ( } static void computePupils ( + int num, TPoint mouse, - TPoint pupils[2]) + TPoint *pupils) { - pupils[0] = computePupil (0, mouse); - pupils[1] = computePupil (1, mouse); + pupils[num] = computePupil (num, mouse); } static void eyeBall ( @@ -260,47 +275,49 @@ static void eyeBall ( static void repaint_window (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); + int i; + for (i = 0; i < w->eyes.num_eyes; i++) { + eyeLiner (w, XtWindow (w), w->eyes.outGC, w->eyes.centerGC, i); + computePupils (i, w->eyes.mouse[i], w->eyes.pupil); + eyeBall (w, w->eyes.pupGC, i); + } } } + static void draw_eye(EyesWidget w, TPoint mouse, int eye1, int eye2) { - TPoint newpupil[2]; + TPoint newpupil[MAX_PUPILS]; XPoint xnewpupil, xpupil; - 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); - xpupil.x = Xx(newpupil[0].x, newpupil[0].y, &w->eyes.t); - xpupil.y = Xy(newpupil[0].x, newpupil[0].y, &w->eyes.t); + if (!TPointEqual (mouse, w->eyes.mouse[eye1])) { + computePupils (eye1, mouse, newpupil); + xpupil.x = Xx(w->eyes.pupil[eye1].x, w->eyes.pupil[eye1].y, &w->eyes.t); + xpupil.y = Xy(w->eyes.pupil[eye1].x, w->eyes.pupil[eye1].y, &w->eyes.t); + xnewpupil.x = Xx(newpupil[eye1].x, newpupil[eye1].y, &w->eyes.t); + xnewpupil.y = Xy(newpupil[eye1].x, newpupil[eye1].y, &w->eyes.t); if (!XPointEqual (xpupil, xnewpupil)) { - if (w->eyes.pupil[0].x != -1000 || w->eyes.pupil[0].y != -1000) + if (w->eyes.pupil[eye1].x != -1000 || w->eyes.pupil[eye1].y != -1000) eyeBall (w, w->eyes.centerGC, eye1); - w->eyes.pupil[0] = newpupil[0]; + w->eyes.pupil[eye1] = newpupil[eye1]; eyeBall (w, w->eyes.pupGC, eye1); } - w->eyes.mouse = mouse; + w->eyes.mouse[eye1] = mouse; w->eyes.update = 0; if (eye1 == eye2) return; - computePupils (mouse, newpupil); - 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); - xpupil.x = Xx(newpupil[1].x, newpupil[1].y, &w->eyes.t); - xpupil.y = Xy(newpupil[1].x, newpupil[1].y, &w->eyes.t); + computePupils (eye2, mouse, newpupil); + xpupil.x = Xx(w->eyes.pupil[eye2].x, w->eyes.pupil[eye2].y, &w->eyes.t); + xpupil.y = Xy(w->eyes.pupil[eye2].x, w->eyes.pupil[eye2].y, &w->eyes.t); + xnewpupil.x = Xx(newpupil[eye2].x, newpupil[eye2].y, &w->eyes.t); + xnewpupil.y = Xy(newpupil[eye2].x, newpupil[eye2].y, &w->eyes.t); if (!XPointEqual (xpupil, xnewpupil)) { - if (w->eyes.pupil[1].x != -1 || w->eyes.pupil[1].y != -1) + if (w->eyes.pupil[eye2].x != -1 || w->eyes.pupil[eye2].y != -1) eyeBall (w, w->eyes.centerGC, eye2); - w->eyes.pupil[1] = newpupil[1]; + w->eyes.pupil[eye2] = newpupil[eye2]; eyeBall (w, w->eyes.pupGC, eye2); } } else { @@ -327,6 +344,40 @@ static void draw_it_core(EyesWidget w) draw_eye(w, mouse, 0, 1); } +#if HAVE_XI2 +static void draw_eye_for_device(EyesWidget w, int device, int deviceid) +{ + Window rep_root, rep_child; + double rep_rootx, rep_rooty; + double dx, dy; + TPoint mouse; + Display *dpy = XtDisplay (w); + Window win = XtWindow (w); + XIButtonState btn_state; + XIModifierState mod_state; + XIGroupState group_state; + + XIQueryPointer (dpy, deviceid, win, &rep_root, &rep_child, + &rep_rootx, &rep_rooty, &dx, &dy, &btn_state, + &mod_state, &group_state); + mouse.x = Tx(dx, dy, &w->eyes.t); + mouse.y = Ty(dx, dy, &w->eyes.t); + + draw_eye(w, mouse, device, device); +} + +static void draw_it_blinky(EyesWidget w) +{ + int i; + + for (i = 0; i < w->eyes.num_eyes; i++) { + if (!w->eyes.devices[i]) + continue; + draw_eye_for_device(w, i, w->eyes.devices[i]); + } +} +#endif + /* ARGSUSED */ static void draw_it ( XtPointer client_data, @@ -335,19 +386,26 @@ static void draw_it ( EyesWidget w = (EyesWidget)client_data; if (XtIsRealized((Widget)w)) { - draw_it_core(w); +#if HAVE_XI2 + if (w->eyes.blinky) + draw_it_blinky(w); + else +#endif + draw_it_core(w); } w->eyes.interval_id = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w), delays[w->eyes.update], draw_it, (XtPointer)w); } /* draw_it */ + static void Resize (Widget gw) { EyesWidget w = (EyesWidget) gw; XGCValues xgcv; Widget parent; int x, y; + int i; if (XtIsRealized (gw)) { @@ -366,8 +424,8 @@ static void Resize (Widget gw) 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); + for (i = 0; i < w->eyes.num_eyes; i++) + eyeLiner (w, w->eyes.shape_mask, w->eyes.shapeGC, (GC) 0, i); x = y = 0; for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) { x += parent->core.x + parent->core.border_width; @@ -380,6 +438,46 @@ static void Resize (Widget gw) } } +#ifdef HAVE_XI2 +static int InitInputDevices(Widget gw) +{ + EyesWidget w = (EyesWidget)gw; + Display *dpy = XtDisplay (w); + + XIDeviceInfo *info; + int ndevices; + int i, idx; + int maj = 2, min = 0; + + memset(w->eyes.devices, 0, sizeof(w->eyes.devices)); + + if (!w->eyes.blinky) + return 2; + + if (XIQueryVersion(dpy, &maj, &min) == BadRequest) { + w->eyes.blinky = FALSE; + return 2; + } + + info = XIQueryDevice(dpy, XIAllMasterDevices, &ndevices); + if (!info) + return 0; + + idx = 0; + for(i = 0; i < ndevices; i++) { + XIDeviceInfo* dev = &info[i]; + if (dev->use == XIMasterPointer) { + w->eyes.devices[idx++] = dev->deviceid; + if (idx == MAX_PUPILS) + break; + } + } + + XIFreeDeviceInfo(info); + return idx; +} +#endif + static void Realize ( Widget gw, XtValueMask *valueMask, @@ -387,12 +485,16 @@ static void Realize ( { EyesWidget w = (EyesWidget)gw; + w->eyes.num_eyes = 2; 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 ); +#ifdef HAVE_XI2 + w->eyes.num_eyes = InitInputDevices(gw); +#endif Resize (gw); w->eyes.interval_id = XtAppAddTimeOut(XtWidgetToApplicationContext(gw), @@ -417,12 +519,13 @@ static void Redisplay( Region region) { EyesWidget w; + int i; 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; + for (i = 0; i < w->eyes.num_eyes; i++) { + w->eyes.pupil[i].x = -1000; + w->eyes.pupil[i].y = -1000; + } (void) repaint_window ((EyesWidget)gw); } diff --git a/Eyes.h b/Eyes.h index 239a127..8f77c21 100644 --- a/Eyes.h +++ b/Eyes.h @@ -34,6 +34,10 @@ #define XtNshapeWindow "shapeWindow" #define XtCShapeWindow "ShapeWindow" +#if HAVE_XI2 +#define XtNBlinky "blinky" +#define XtCBlinky "Blinky" +#endif typedef struct _EyesRec *EyesWidget; /* completely defined in EyesPrivate.h */ typedef struct _EyesClassRec *EyesWidgetClass; /* completely defined in EyesPrivate.h */ diff --git a/EyesP.h b/EyesP.h index 7dea77a..1af695c 100644 --- a/EyesP.h +++ b/EyesP.h @@ -5,11 +5,16 @@ #ifndef _EyesP_h #define _EyesP_h +#if HAVE_CONFIG_H +#include <config.h> +#endif + #include "Eyes.h" #include <X11/CoreP.h> #include "transform.h" #define SEG_BUFF_SIZE 128 +#define MAX_PUPILS 8 /* New fields for the eyes widget instance record */ typedef struct { @@ -25,12 +30,17 @@ typedef struct { Boolean reverse_video; /* swap fg and bg pixels */ Boolean shape_window; /* use SetWindowShapeMask */ int update; /* current timeout index */ - TPoint mouse; /* old mouse position */ - TPoint pupil[2]; /* pupil position */ + TPoint mouse[MAX_PUPILS]; /* old mouse position */ + TPoint pupil[MAX_PUPILS]; /* pupil position */ Transform t; Transform maskt; XtIntervalId interval_id; Pixmap shape_mask; /* window shape */ + int num_eyes; /* number of eyes, default 2 */ +#ifdef HAVE_XI2 + Boolean blinky; + int devices[MAX_PUPILS]; +#endif } EyesPart; /* Full instance record declaration */ diff --git a/Makefile.am b/Makefile.am index ca2956c..8b57f50 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,6 +23,9 @@ bin_PROGRAMS = xeyes AM_CFLAGS = $(XEYES_CFLAGS) xeyes_LDADD = $(XEYES_LIBS) -lm +if HAVE_XI2 +xeyes_LDADD += $(XI2_LIBS) +endif xeyes_SOURCES = \ Eyes.c \ diff --git a/configure.ac b/configure.ac index 188d2ca..9543acc 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,11 @@ XORG_CWARNFLAGS # Checks for pkg-config packages PKG_CHECK_MODULES(XEYES, x11 xt xext xmu) +PKG_CHECK_MODULES(XI2, [xi >= 1.2.99.1], + HAVE_XI2="yes"; AC_DEFINE(HAVE_XI2, 1, [XI2 available]), + HAVE_XI2="no") +AM_CONDITIONAL(HAVE_XI2, [ test "$HAVE_XI2" = "yes" ]) + XEYES_CFLAGS="$CWARNFLAGS $XEYES_CFLAGS" AC_SUBST(XEYES_CFLAGS) AC_SUBST(XEYES_LIBS) diff --git a/xeyes.c b/xeyes.c index 24b36b0..353d072 100644 --- a/xeyes.c +++ b/xeyes.c @@ -30,6 +30,10 @@ from the X Consortium. */ /* $XFree86: xc/programs/xeyes/xeyes.c,v 1.3 2000/02/17 14:00:35 dawes Exp $ */ +#if HAVE_CONFIG_H +#include <config.h> +#endif + #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Shell.h> @@ -54,6 +58,10 @@ usage(void) fprintf(stderr, "\n"); fprintf(stderr, " [-outline {color}] [-center {color}] [-backing {backing-store}]\n"); +#if HAVE_XI2 + fprintf(stderr, +" [-blinky]\n"); +#endif exit(1); } @@ -66,6 +74,9 @@ static XrmOptionDescRec options[] = { {"-backing", "*eyes.backingStore", XrmoptionSepArg, NULL}, {"-shape", "*eyes.shapeWindow", XrmoptionNoArg, "TRUE"}, {"+shape", "*eyes.shapeWindow", XrmoptionNoArg, "FALSE"}, +#if HAVE_XI2 +{"-blinky", "*eyes.blinky", XrmoptionNoArg, "TRUE"}, +#endif }; static Atom wm_delete_window; -- 1.6.3.rc1.2.g0164.dirty _______________________________________________ xorg-devel mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-devel
