/ *
* TOEABLE RECORD EXTENSION in Xorg / XFree86, Add The Following Line in
* Section "Module"
* LOAD "Record"
* /
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/ * for this struct, refer to libxnee * /
Typedef union {
UNSIGNED CHAR TYPE;
Xevent Event;
XResourcesReq Req;
XGENERICREPLY Reply;
Xerror Error;
XCONNSETUPPREFIX SETUP;
} XRecordDatum;
/ *
* Fixme: we need define a private struct for callback function,
* To store cur_x, cur_y, data_disp, ctrl_disp etc.
* /
Display * DATA_DISP = NULL;
Display * ctrl_disp = null;
/ * Stop flag * /
INT STOP = 0;
Void Event_Callback (XPointer, XRecordInterceptData *);
INT main (int Argc, char ** argv)
{
Ctrl_disp = xopendisplay (null);
Data_disp = Xopendisplay (NULL);
IF (! Ctrl_Disp ||! data_disp) {
FPRINTF (stderr, "error to open local display! / n");
Exit (1);
}
/ *
* WE Must set the ctrl_disp to sync mode, or, We the entbe
* Context in data_disp, There will be a fatal x error !!!
* /
XSynchronize (Ctrl_Disp, true);
Int Major, Minor;
IF (! xRecordQueryVersion (Ctrl_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 (Ctrl_Disp, 0, & RCS, 1, & RR, 1);
IF (! rc) {
FPRINTF (stderr, "could not create a record context! / n");
EXIT (4);
}
IF (! xRecordenableContextasync (Data_Disp, RC, Event_Callback, Null) {
FPRINTF (stderr, "Cound Not Enable the Record CONTEXT! / N");
EXIT (5);
}
While (stop! = 1) {
XRecordProcessReplies (DATA_DISP);
}
XRecordDisableContext (Ctrl_Disp, RC);
XRecordFreeContext (Ctrl_Disp, RC);
Xfree (rr);
XCloseDisplay (DATA_DISP);
XCloseDisplay (Ctrl_DISP);
Return 0;
}
Void Event_Callback (Xreg 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 = (xRecorddata *) 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.keybuttonPoint.Rooty;
INT TIME = HOOK-> Server_Time;
Switch (Event_Type) {
Case KeyPress:
/ * if escape ispel, stop the loop and clean up, then exit * /
IF (Keycode == 9) stop = 1;
/ * Note: You Should Not USE DATA_DISP To Do Normal X Operations !!! * /
Printf ("KeyPress: / T% S", XkeysymtoKeysym (Ctrl_Disp, Keycode, 0))));
Break;
Case Keyrelease:
Printf ("KeyRelease: / T% S", xkeysymtostring (xkeycodetokeysym (ctrl_disp, keycode, 0))));
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);
}