Вам не нужно делать ничего более низкого уровня, чем ядро или драйверы устройств, чтобы сделать это.
Вы можете использовать расширение XTest X11 для фальсификации входных событий программно, дляпример (из этой публикации , есть другой пример для клавиатуры ).
#include <X11/extensions/XTest.h>
#include <unistd.h>
int main ()
{
Display *dpy = NULL;
XEvent event;
dpy = XOpenDisplay (NULL);
/* Get the current pointer position */
XQueryPointer (dpy, RootWindow (dpy, 0),
&event.xbutton.root, &event.xbutton.window,
&event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y,
&event.xbutton.state);
/* Fake the pointer movement to new relative position */
XTestFakeMotionEvent (dpy, 0, event.xbutton.x + 100,
event.xbutton.y + 50, CurrentTime);
XSync(dpy, 0);
XCloseDisplay (dpy);
return 0;
}
Для захвата изображений самый простой способ - использовать вставка функции (через LD_PRELOAD
) для «перехвата» вызовов на glXSwapBuffers
, чтобудет вызван, как только каждый кадр будет нарисован.Оттуда вы можете скопировать содержимое кадрового буфера, используя glReadPixels
и делать с ним все, что вы хотите.
Например непроверенный контур для перехвата кадров OpenGL:
// Function pointer to the *real* glXSwapBuffers
static void (*glx_fptr)(Display*, GLXDrawable) = NULL;
// Make sure init gets called when the shared object is loaded. GCC specific.
static void init(void) __attribute__((constructor));
static void init(void) {
dlerror();
// find the real glXSwapBuffers
glx_fptr = dlsym(RTLD_NEXT, "glXSwapBuffers");
if (NULL == glx_fptr)
fprintf(stderr, "[glvidcap] %s\n", dlerror());
}
void glXSwapBuffers(Display *dpy, GLXDrawable drawable) {
unsigned int w = 0;
unsigned int h = 0;
static int x,y;
static Window win;
static unsigned int border,depth;
// Find the window size. (You could skip this and make it all static if you
// Trust the window not to change size
XGetGeometry(dpy, drawable, &win, &x, &y, &w, &h, &border, &depth);
// Assuming frame is some memory you want the frame dumped to:
glReadPixels(0,0,w,h,GL_BGR,GL_UNSIGNED_BYTE, frame);
// Call the real function:
assert(glx_fptr);
glx_fptr(dpy, drawable);
}
Затем вы хотите скомпилировать его как общий объект и LD_PRELOAD
этот общий объект перед запуском любой игры, на которую вы смотрите.
Если вместо этого это приложение SDLВы можете перехватить вызовы на SDL_Flip
или SDL_UpdateRect
, в зависимости от ситуации.