> Thanks for the patch! There's a number of irrelevant white-space changes in
> that patch. Can you please clean it up and re-send it? Thanks.
>

Sorry, my mistake.

I removed the whitespace changes and further added a a small change in the
syndamon manpage.

:andre
diff --git a/configure.ac b/configure.ac
index 69f1041..4cf8a03 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,6 +111,7 @@ AC_SUBST([CFLAGS])
 
 # Checks for libraries.
 PKG_CHECK_MODULES(XLIB, x11) # needed for syndaemon
+PKG_CHECK_MODULES(XRECORD, xtst, AC_DEFINE([HAVE_XRECORD],[],[Use XRecord]), true)
 
 # Checks for header files.
 AC_HEADER_STDC
diff --git a/man/syndaemon.man b/man/syndaemon.man
index b9adc3d..eaaa0f0 100644
--- a/man/syndaemon.man
+++ b/man/syndaemon.man
@@ -48,6 +48,11 @@ Ignore modifier keys when monitoring keyboard activity.
 .TP
 \fB\-K\fP
 Like \-k but also ignore Modifier+Key combos.
+.LP
+.TP
+\fB\-R\fP
+Disable the use of the XRecord extension for detecting keyboard activity.
+This will force the use of polling the keyboard state.
 .SH "ENVIRONMENT VARIABLES"
 .LP
 .TP
diff --git a/tools/Makefile.am b/tools/Makefile.am
index a83da60..2f2199b 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -28,4 +28,4 @@ synclient_SOURCES = synclient.c
 synclient_LDFLAGS = -lm
 
 syndaemon_SOURCES = syndaemon.c
-syndaemon_LDFLAGS = $(XLIB_LIBS)
+syndaemon_LDFLAGS = $(XLIB_LIBS) $(XRECORD_LIBS)
diff --git a/tools/syndaemon.c b/tools/syndaemon.c
index 7aa8238..b8d1255 100644
--- a/tools/syndaemon.c
+++ b/tools/syndaemon.c
@@ -29,6 +29,9 @@
 #endif
 
 #include <X11/Xlib.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/record.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -45,6 +48,7 @@ static SynapticsSHM *synshm;
 static int pad_disabled;
 static int disable_taps_only;
 static int ignore_modifier_combos;
+static int ignore_modifier_keys = 0;
 static int background;
 static const char *pid_file;
 
@@ -64,6 +68,7 @@ usage(void)
     fprintf(stderr, "  -t Only disable tapping and scrolling, not mouse movements.\n");
     fprintf(stderr, "  -k Ignore modifier keys when monitoring keyboard activity.\n");
     fprintf(stderr, "  -K Like -k but also ignore Modifier+Key combos.\n");
+    fprintf(stderr, "  -R Don't use the XRecord extension.\n");
     exit(1);
 }
 
@@ -243,6 +248,194 @@ setup_keyboard_mask(Display *display, int ignore_modifier_keys)
     }
 }
 
+/* ---- the following code is for using the xrecord extension ----- */
+#ifdef HAVE_XRECORD
+
+#define MAX_MODIFIERS 16
+
+/* used for exchanging information with the callback function */
+struct xrecord_callback_results {
+    XModifierKeymap *modifiers;
+    Bool key_event;
+    Bool non_modifier_event;
+    KeyCode pressed_modifiers[MAX_MODIFIERS];
+};
+
+/* test if the xrecord extension is found */
+Bool check_xrecord(Display *display) {
+
+    Bool   found;
+    Status status;
+    int    major_opcode, minor_opcode, first_error;
+    int    version[2];
+
+    found = XQueryExtension(display,
+			    "RECORD",
+			    &major_opcode,
+			    &minor_opcode,
+			    &first_error);
+
+    status = XRecordQueryVersion(display, version, version+1);
+    if (!background && status) {
+	printf("X RECORD extension version %d.%d\n", version[0], version[1]);
+    }
+    return found;
+}
+
+/* called by XRecordProcessReplies() */
+void xrecord_callback( XPointer closure, XRecordInterceptData* recorded_data) {
+
+    struct xrecord_callback_results *cbres;
+    xEvent *xev;
+    int nxev;
+
+    cbres = (struct xrecord_callback_results *)closure;
+    /*printf("something happend, category=%d\n", recorded_data->category); */
+
+    if (recorded_data->category != XRecordFromServer) {
+	XRecordFreeData(recorded_data);
+	return;
+    }
+
+    nxev = recorded_data->data_len / 8;
+    xev = (xEvent *)recorded_data->data;
+    while(nxev--) {
+
+	if ( (xev->u.u.type == KeyPress) || (xev->u.u.type == KeyRelease)) {
+	    int i;
+	    int is_modifier = 0;
+
+	    cbres->key_event = 1; /* remember, a key was pressed. */
+
+	    /* test if it was a modifier */
+	    for (i = 0; i < 8 * cbres->modifiers->max_keypermod; i++) {
+		KeyCode kc = cbres->modifiers->modifiermap[i];
+
+		if (kc == xev->u.u.detail) {
+		    is_modifier = 1; /* yes, it is a modifier. */
+		    break;
+		}
+	    }
+
+	    if (is_modifier) {
+		if (xev->u.u.type == KeyPress) {
+		    for (i=0; i < MAX_MODIFIERS; ++i)
+			if (!cbres->pressed_modifiers[i]) {
+			    cbres->pressed_modifiers[i] = xev->u.u.detail;
+			    break;
+			}
+		} else { /* KeyRelease */
+		    for (i=0; i < MAX_MODIFIERS; ++i)
+			if (cbres->pressed_modifiers[i] == xev->u.u.detail)
+			    cbres->pressed_modifiers[i] = 0;
+		}
+
+	    } else {
+		/* remember, a non-modifier was pressed. */
+		cbres->non_modifier_event = 1;
+	    }
+	}
+
+	xev++;
+    }
+
+    XRecordFreeData(recorded_data); /* cleanup */
+}
+
+static int is_modifier_pressed(const struct xrecord_callback_results *cbres) {
+    int i;
+
+    for (i = 0; i < MAX_MODIFIERS; ++i)
+	if (cbres->pressed_modifiers[i])
+	    return 1;
+
+    return 0;
+}
+
+void record_main_loop(Display* display, double idle_time) {
+
+    struct xrecord_callback_results cbres;
+    XRecordContext context;
+    XRecordClientSpec cspec = XRecordAllClients;
+    Display *dpy_data;
+    XRecordRange *range;
+    int i;
+
+    pad_disabled = 0;
+
+    dpy_data = XOpenDisplay(NULL); /* we need an additional data connection. */
+    range  = XRecordAllocRange();
+
+    range->device_events.first = KeyPress;
+    range->device_events.last  = KeyRelease;
+
+    context =  XRecordCreateContext(dpy_data, 0,
+				    &cspec,1,
+				    &range, 1);
+
+    XRecordEnableContextAsync(dpy_data, context, xrecord_callback, (XPointer)&cbres);
+
+    cbres.modifiers  = XGetModifierMapping(display);
+    /* clear list of modifiers */
+    for (i = 0; i < MAX_MODIFIERS; ++i)
+	cbres.pressed_modifiers[i] = 0;
+
+    while (1) {
+
+	int fd = ConnectionNumber(dpy_data);
+	fd_set read_fds;
+	int ret;
+	int disable_event = 0;
+	struct timeval timeout;
+
+	FD_ZERO(&read_fds);
+	FD_SET(fd, &read_fds);
+
+	ret = select(fd+1, &read_fds, NULL, NULL,
+		     pad_disabled ? &timeout : NULL /* timeout only required for enabling */ );
+
+	if (FD_ISSET(fd, &read_fds)) {
+
+	    cbres.key_event = 0;
+	    cbres.non_modifier_event = 0;
+
+	    XRecordProcessReplies(dpy_data);
+
+	    if (!ignore_modifier_keys && cbres.key_event) {
+		disable_event = 1;
+	    }
+
+	    if (cbres.non_modifier_event &&
+		!(ignore_modifier_combos && is_modifier_pressed(&cbres)) ) {
+		disable_event = 1;
+	    }
+	}
+
+	if (disable_event) {
+	    /* adjust the enable_time */
+	    timeout.tv_sec  = (int)idle_time;
+	    timeout.tv_usec = (idle_time-(double)timeout.tv_sec) * 100000.;
+
+	    if (!pad_disabled) {
+		pad_disabled=1;
+		if (!background) printf("disable touchpad\n");
+
+		if (!synshm->touchpad_off)
+		    synshm->touchpad_off = disable_taps_only ? 2 : 1;
+	    }
+	}
+
+	if (ret == 0 && pad_disabled) { /* timeout => enable event */
+	    enable_touchpad();
+	    if (!background) printf("enable touchpad\n");
+	}
+
+    } /* end while(1) */
+
+    XFreeModifiermap(cbres.modifiers);
+}
+#endif // HAVE_XRECORD
+
 int
 main(int argc, char *argv[])
 {
@@ -251,10 +444,11 @@ main(int argc, char *argv[])
     Display *display;
     int c;
     int shmid;
-    int ignore_modifier_keys = 0;
+    int use_xrecord = 1;
+
 
     /* Parse command line parameters */
-    while ((c = getopt(argc, argv, "i:m:dtp:kK?")) != EOF) {
+    while ((c = getopt(argc, argv, "i:m:dtp:kKR?")) != EOF) {
 	switch(c) {
 	case 'i':
 	    idle_time = atof(optarg);
@@ -278,6 +472,9 @@ main(int argc, char *argv[])
 	    ignore_modifier_combos = 1;
 	    ignore_modifier_keys = 1;
 	    break;
+	case 'R':
+	    use_xrecord = 0;
+	    break;
 	default:
 	    usage();
 	    break;
@@ -333,11 +530,16 @@ main(int argc, char *argv[])
 	    fclose(fd);
 	}
     }
-
-    setup_keyboard_mask(display, ignore_modifier_keys);
-
-    /* Run the main loop */
-    main_loop(display, idle_time, poll_delay);
-
+#ifdef HAVE_XRECORD
+    if (use_xrecord && check_xrecord(display)) {
+	record_main_loop(display, idle_time);
+    } else
+#endif HAVE_XRECORD
+      {
+	setup_keyboard_mask(display, ignore_modifier_keys);
+
+	/* Run the main loop */
+	main_loop(display, idle_time, poll_delay);
+      }
     return 0;
 }
_______________________________________________
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Reply via email to