[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