[Xcb] magical callback funness
Jeremy Kolb
jkolb at brandeis.edu
Thu Mar 24 09:27:57 PST 2005
Henrik Sandklef wrote:
>>I've run into a snag with record. It there's a request/reply called
>>RecordGetContext. This gets the events recorded on the current
>>connection.
>
>
> When working with RECORD you use a context type. When having made one such
> you can:
>
> 1 Query the state
> -------------------
> Done using the function XRecordGetContext
>
> The request "RecordGetContext" is sent after the
> function XRecordGetContext has been called
>
> 2 Start/stop recording
> -------------------
> Done using the function XRecordEnableContext/XRecordDisableContext
>
> The request RecordEnableContext is sent after the
> function XRecordEnableContext has been called
>
> The request RecordDisableContext is sent after the
> function XRecordDisableContext has been called
>
>
>
>>However when calling the reply it enters a loop and prints
>>out how no record was found for such and such an event.
>
>
> Calling the reply? Can you please give some more info? Do you mean sending?
>
> Can you show me your source code?
>
>
>> The problem is
>>that I can't get out of this loop to do other things like parse the
>>information and what not.
>
>
> Where is your code located? In the client or the server?
>
>
>
>>Xlib seems to solve this problem by installing a callback (I'm not
>>really sure how it works though). when enabling the context
>>(RecordEnableContext).
>
> This is right.
>
>
>>I'm not sure how to solve this. Ideas, suggestions?
>
> Show the sources :)
>
> /h
>
I just committed my record.xml file, you'll have to edit Makefile.in in
both cvs/xcb-proto/src and cvs/xcb/src to build it. I don't want to
enable it by default yet because I want to fully test it first.
Anyways, here's my test program. record_test.c.orig is the xlib version
from blogs.sun.com/yongsun (used with his permission). record_test.c
will be the xcbified version.
Jeremy
-------------- next part --------------
// Assuming xcb is installed to /opt/fdo
// gcc -I/opt/fdo/include -L/opt/fdo/lib -lXCB -g record_test.c -o record_test
#include <stdio.h>
#include <stdlib.h>
#include <X11/XCB/xcb.h>
#include <X11/XCB/record.h>
XCBConnection *rec_con = NULL;
XCBConnection *loc_con = NULL;
int main(int argc, char **argv)
{
int major = 1;
int minor = 13;
loc_con = XCBConnectBasic();
rec_con = XCBConnectBasic();
if (!loc_con || !rec_con) {
fprintf(stderr, "Error, cannot open display!\n");
exit(1);
}
XCBRecordQueryVersionRep *qv = NULL;
XCBGenericError *err = NULL;
qv = XCBRecordQueryVersionReply(rec_con,
XCBRecordQueryVersion(rec_con, major, minor),
&err);
if (!qv || err) {
fprintf(stderr, "RECORD extension not supported on this server!\n");
exit(1);
}
major = qv->major_version;
minor = qv->minor_version;
printf("RECORD extension version is %d.%d\n", major, minor);
XCBRecordRange *rr;
rr = (XCBRecordRange *)calloc(1, sizeof(XCBRecordRange)); // IMPORTANT
CARD32 rcs = XCBRecordCSAllClients;
XCBRecordContext rc = XCBRecordContextNew(rec_con);
rr->device_events.first = XCBKeyPress;
rr->device_events.last = XCBMotionNotify;
// Make sure to check context later.
XCBRecordCreateContext(rec_con, rc, 0, 1, 1, &rcs, rr);
XCBRecordEnableContextRep *ecr = NULL;
XCBRecordEnableContextCookie ecc;
ecc = XCBRecordEnableContext(rec_con, rc);
ecr = XCBRecordEnableContextReply(rec_con, ecc, &err);
if (!ecr || err) {
fprintf(stderr, "Could not enable the record context!\n");
XCBRecordBadContextError *berr;
berr = ((XCBRecordBadContextError *) err);
fprintf(stderr, "Context: %d\tCode: %d\tInvalid: %d\n",
rc.xid, berr->error_code, berr->invalid_record);
exit(1);
}
//while(1) {
XCBRecordGetContextCookie gcc;
XCBRecordGetContextRep *gcr;
gcc = XCBRecordGetContext(rec_con, rc);
gcr = XCBRecordGetContextReply(rec_con, gcc, &err);
if (!gcr || err) {
fprintf(stderr, "Could not get context.\n");
exit(1);
}
printf("enabled: %d, num_clients: %d\n", gcr->enabled, gcr->num_intercepted_clients);
//}
XCBRecordDisableContext(rec_con, rc);
XCBRecordFreeContext(rec_con, rc);
free(rr);
}
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlibint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/keysymdef.h>
#include <X11/keysym.h>
#include <X11/extensions/record.h>
#include <X11/extensions/XTest.h>
typedef union {
unsigned char type;
xEvent event;
xResourceReq req;
xGenericReply reply;
xError error;
xConnSetupPrefix setup;
} XRecordDatum;
/*
* FIXME: We need define a private struct for callback function,
* to store cur_x, cur_y, rec_disp, loc_disp etc.
*/
Display *rec_disp = NULL;
Display *loc_disp = NULL;
void event_callback(XPointer, XRecordInterceptData *);
int
main(int argc, char **argv)
{
loc_disp = XOpenDisplay(NULL);
rec_disp = XOpenDisplay(NULL);
if (!loc_disp || !rec_disp) {
fprintf(stderr, "Error to open local display!\n");
exit(1);
}
int major,
minor;
if (!XRecordQueryVersion(rec_disp, &major, &minor)) {
fprintf(stderr,
"RECORD extension not supported on this X server!\n");
exit(2);
}
printf("RECORD extension for local server is version is %d.%d\n",
major, minor);
XRecordRange *rr;
XRecordClientSpec rcs;
XRecordContext rc;
rr = XRecordAllocRange();
if (!rr) {
fprintf(stderr, "Could not alloc record range object!\n");
exit(3);
}
rr->device_events.first = KeyPress;
rr->device_events.last = MotionNotify;
rcs = XRecordAllClients;
rc = XRecordCreateContext(rec_disp, 0, &rcs, 1, &rr, 1);
if (!rc) {
fprintf(stderr, "Could not create a record context!\n");
exit(4);
}
if (!XRecordEnableContextAsync(rec_disp, rc, event_callback, NULL)) {
fprintf(stderr, "Cound not enable the record context!\n");
exit(5);
}
while (1)
XRecordProcessReplies(rec_disp);
XRecordDisableContext(rec_disp, rc);
XRecordFreeContext(rec_disp, rc);
XFree(rr);
XCloseDisplay(rec_disp);
XCloseDisplay(loc_disp);
return 0;
}
void
event_callback(XPointer priv, XRecordInterceptData * hook)
{
/*
* FIXME: we need use XQueryPointer to get the first location
*/
static int cur_x = 0;
static int cur_y = 0;
if (hook->category != XRecordFromServer) {
XRecordFreeData(hook);
return;
}
XRecordDatum *data = (XRecordDatum *) hook->data;
int event_type = data->type;
BYTE btncode,
keycode;
btncode = keycode = data->event.u.u.detail;
int rootx = data->event.u.keyButtonPointer.rootX;
int rooty = data->event.u.keyButtonPointer.rootY;
int time = hook->server_time;
switch (event_type) {
case KeyPress:
printf("KeyPress: \t%s",
XKeysymToString(XKeycodeToKeysym(loc_disp, keycode, 0)));
break;
case KeyRelease:
printf("KeyRelease: \t%s",
XKeysymToString(XKeycodeToKeysym(loc_disp, keycode, 0)));
break;
case ButtonPress:
printf("ButtonPress: \t%d, rootX=%d, rootY=%d", btncode, cur_x,
cur_y);
break;
case ButtonRelease:
printf("ButtonRelease: \t%d, rootX=%d, rootY=%d", btncode, cur_x,
cur_y);
break;
case MotionNotify:
printf("MouseMove: \trootX=%d, rootY=%d", rootx, rooty);
cur_x = rootx;
cur_y = rooty;
break;
case CreateNotify:
break;
case DestroyNotify:
break;
case NoExpose:
break;
case Expose:
break;
default:
break;
}
printf(", time=%d\n", time);
XRecordFreeData(hook);
}
More information about the xcb
mailing list