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

Reply via email to