[PATCH] xeyes: Add -blinky option.

Peter Hutterer peter.hutterer at who-t.net
Fri Jul 17 02:58:30 PDT 2009


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 <peter.hutterer at who-t.net>
---

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


More information about the xorg-devel mailing list