/*
* To enable record extension in Xorg/xfree86, add the following line in
* Section "module"
* Load "record"
*/
# 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>
/* For This struct, refer to libxnee */
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, 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, when we the enalbe
* 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, "cocould not alloc record range object! /N ");
Exit (3 );
}
Rr-> device_events.first = keypress;
Rr-> device_events.last = motionpolicy;
RCS = xrecordallclients;
Rc = xrecordcreatecontext (ctrl_disp, 0, & RCs, 1, & RR, 1 );
If (! RC ){
Fprintf (stderr, "cocould 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 (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:
/* If escape is pressed, stop the loop and clean up, then exit */
If (keycode = 9) Stop = 1;
/* Note: You shoshould not use data_disp to do normal x operations !!! */
Printf ("keypress:/T % s", xkeysymtostring (xkeycodetokeysym (ctrl_disp, keycode, 0 )));
Break;
Case keyrelease:
Printf ("keyrelease:/T % s", xkeysymtostring (xkeycodetokeysym (ctrl_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 motionpolicy:
Printf ("mousemove:/trootx = % d, Rooty = % d", rootx, Rooty );
Cur_x = rootx;
Cur_y = Rooty;
Break;
Case createnoworkflow:
Break;
Case destroynotify:
Break;
Case noexpose:
Break;
Case expose:
Break;
Default:
Break;
}
Printf (", time = % d/N", time );
Xrecordfreedata (Hook );
}