summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-08-07 12:17:24 +0200
committerKeith Packard <keithp@keithp.com>2013-08-07 12:17:24 +0200
commit3604b25f447790aa28117a55f04fd7fc5c828568 (patch)
tree1678e028be235e68e2bce8ae73e321d4cacf9489
parent31cce6ec946c27fcad853cd0ce5ca5cbe6f510ab (diff)
Use XI2 raw events to notice when mouse movesdri3
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--Eyes.c125
-rw-r--r--EyesP.h1
-rw-r--r--configure.ac2
3 files changed, 118 insertions, 10 deletions
diff --git a/Eyes.c b/Eyes.c
index 70e833d..98afe7e 100644
--- a/Eyes.c
+++ b/Eyes.c
@@ -48,6 +48,7 @@ from the X Consortium.
# include <X11/extensions/shape.h>
# include <X11/Xlibint.h>
# include <stdlib.h>
+# include <X11/extensions/XInput2.h>
#if (defined(SVR4) || defined(SYSV) && defined(i386))
extern double hypot(double, double);
@@ -157,9 +158,7 @@ static void CheckPresent(EyesWidget w) {
present_reply = xcb_present_query_version_reply(xt_xcb(w),
present_cookie,
NULL);
- if (xfixes_reply && damage_reply && present_reply)
- printf ("Using present extension\n");
- else
+ if (!xfixes_reply || !damage_reply || !present_reply)
w->eyes.present = FALSE;
}
@@ -213,6 +212,104 @@ static void UpdatePresent(EyesWidget w) {
#define EyesDrawable(w) XtWindow(w)
#endif
+struct root_listen_list {
+ struct root_listen_list *next;
+ Widget widget;
+};
+
+static struct root_listen_list *root_listen_list;
+
+static Boolean xi2_dispatcher(XEvent *event) {
+ struct root_listen_list *rll;
+ Boolean was_dispatched = False;
+
+ for (rll = root_listen_list; rll; rll = rll->next) {
+ if (XtDisplay(rll->widget) == event->xany.display) {
+ XtDispatchEventToWidget(rll->widget, event);
+ was_dispatched = True;
+ }
+ }
+ return was_dispatched;
+}
+
+static void select_xi2_events(Widget w)
+{
+ XIEventMask evmasks[1];
+ unsigned char mask1[(XI_LASTEVENT + 7)/8];
+ unsigned char mask2[(XI_LASTEVENT + 7)/8];
+
+ memset(mask1, 0, sizeof(mask1));
+
+ /* select for button and key events from all master devices */
+ XISetMask(mask1, XI_RawMotion);
+
+ evmasks[0].deviceid = XIAllMasterDevices;
+ evmasks[0].mask_len = sizeof(mask1);
+ evmasks[0].mask = mask1;
+
+ XISelectEvents(XtDisplay(w),
+ RootWindowOfScreen(XtScreen(w)),
+ evmasks, 1);
+ XtSetEventDispatcher(XtDisplay(w),
+ GenericEvent,
+ xi2_dispatcher);
+}
+
+static void draw_it_core(EyesWidget w);
+
+static void EyesGeneric(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
+{
+ draw_it_core((EyesWidget) w);
+}
+
+static Boolean xi2_add_root_listener(Widget widget)
+{
+ struct root_listen_list *rll = malloc (sizeof (struct root_listen_list));
+
+ if (!rll)
+ return False;
+ rll->widget = widget;
+ rll->next = root_listen_list;
+ if (!root_listen_list)
+ select_xi2_events(widget);
+ root_listen_list = rll;
+ XtInsertEventTypeHandler(widget, GenericEvent, NULL, EyesGeneric, NULL, XtListHead);
+ return True;
+}
+
+static void xi2_remove_root_listener(Widget widget)
+{
+ struct root_listen_list *rll, **prev;
+
+ for (prev = &root_listen_list; (rll = *prev) != NULL; prev = &rll->next) {
+ if (rll->widget == widget) {
+ *prev = rll->next;
+ free(rll);
+ break;
+ }
+ }
+}
+
+/* Return 1 if XI2 is available, 0 otherwise */
+static int has_xi2(Display *dpy)
+{
+ int major, minor;
+ int rc;
+
+ /* We support XI 2.2 */
+ major = 2;
+ minor = 2;
+
+ rc = XIQueryVersion(dpy, &major, &minor);
+ if (rc == BadRequest) {
+ return 0;
+ } else if (rc != Success) {
+ return 0;
+ }
+ return 1;
+}
+
+
/* ARGSUSED */
static void Initialize (
Widget greq,
@@ -282,6 +379,8 @@ static void Initialize (
w->eyes.shape_mask = 0;
w->eyes.gc[PART_SHAPE] = NULL;
+ w->eyes.has_xi2 = has_xi2(XtDisplay(w));
+
#ifdef XRENDER
for (i = 0; i < PART_SHAPE; i ++) {
XColor c;
@@ -514,6 +613,7 @@ static void repaint_window (EyesWidget w)
#ifdef PRESENT
MakePresentData(w);
#endif
+
eyeLiner (w, TRUE, 0);
eyeLiner (w, TRUE, 1);
computePupils (w, w->eyes.mouse, w->eyes.pupil);
@@ -599,9 +699,11 @@ static void draw_it (
if (XtIsRealized((Widget)w)) {
draw_it_core(w);
}
- w->eyes.interval_id =
- XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w),
- delays[w->eyes.update], draw_it, (XtPointer)w);
+ if (!w->eyes.has_xi2) {
+ w->eyes.interval_id =
+ XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w),
+ delays[w->eyes.update], draw_it, (XtPointer)w);
+ }
} /* draw_it */
static void Resize (Widget gw)
@@ -688,9 +790,13 @@ static void Realize (
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);
+
+ if (w->eyes.has_xi2)
+ xi2_add_root_listener(gw);
+ else
+ w->eyes.interval_id =
+ XtAppAddTimeOut(XtWidgetToApplicationContext(gw),
+ delays[w->eyes.update], draw_it, (XtPointer)gw);
}
static void Destroy (Widget gw)
@@ -702,6 +808,7 @@ static void Destroy (Widget gw)
XtRemoveTimeOut (w->eyes.interval_id);
for (i = 0; i < PART_MAX; i ++)
XtReleaseGC(gw, w->eyes.gc[i]);
+ xi2_remove_root_listener(gw);
#ifdef XRENDER
if (w->eyes.picture)
XRenderFreePicture (XtDisplay(w), w->eyes.picture);
diff --git a/EyesP.h b/EyesP.h
index 29fe8a3..ecd565b 100644
--- a/EyesP.h
+++ b/EyesP.h
@@ -33,6 +33,7 @@ typedef struct {
Transform maskt;
XtIntervalId interval_id;
Pixmap shape_mask; /* window shape */
+ Boolean has_xi2;
#ifdef XRENDER
Boolean render;
Picture picture;
diff --git a/configure.ac b/configure.ac
index a34df57..c390d7e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,7 @@ XORG_MACROS_VERSION(1.8)
XORG_DEFAULT_OPTIONS
# Checks for pkg-config packages
-PKG_CHECK_MODULES(XEYES, [x11 xt xext xmu xproto >= 7.0.17])
+PKG_CHECK_MODULES(XEYES, [xi >= 1.7 x11 xt xext xmu xproto >= 7.0.17])
dnl Optional dependencies
AC_ARG_WITH(xrender, AS_HELP_STRING([--with-xrender],[Use Xrender for rendering (Default is YES)]),use_xrender="$withval",use_xrender="try")