捕获Linux/Ubuntu(屏幕捕获 鼠标/键盘事件)中的窗口事件



我想为Linux中的C 开发一个应用程序,需要通过标准IO(鼠标 键盘)与其他程序进行交互。它应该能够将鼠标/键盘输入发送到窗口并捕获该特定窗口的"屏幕截图"。

(1)现在我已经进行了一些研究,我知道Linux使用了" X Window"系统。是否建议它从该层开始进行编程,或者我应该使用一些更高级别的框架(例如WXWIDGETS)?

(2)即使没有集中注意力,也可以将输入事件发送到/捕获屏幕吗?

(3)我不是要您提供代码,但是我很想通过一些有关该主题的文献进行工作。可悲的是,我找不到有关此主题的任何好消息。

如果有人可以帮助我这样做,那就太好了!

预先感谢您!!

[注意:此程序应作为后端运行,然后从Java应用程序中执行命令。该计划是为Windows/Linux单独实现此后端C 应用程序]

解决方案1 我可以推荐一个用于发送键盘事件的代码,我自己用我自己来模拟键盘。它基于Xsendevent。

#include <X11/Xlib.h>
#include <X11/keysym.h>
/** Modifier states */
#define MOD_ALT 0x8
#define MOD_CONTROL 0x4
#define MOD_CONTROL_ALT 0xc
#define MOD_SHIFT_CONTROL 0x5
#define MOD_SHIFT_ALT 0x9
XKeyEvent createKeyEvent(Display *display, Window &win,
                           Window &winRoot, bool press,
                           int keycode, int modifiers)
{
   XKeyEvent event;
   event.display     = display;
   event.window      = win;
   event.root        = winRoot;
   event.subwindow   = None;
   event.time        = CurrentTime;
   event.x           = 1;
   event.y           = 1;
   event.x_root      = 1;
   event.y_root      = 1;
   event.same_screen = True;
   event.keycode     = XKeysymToKeycode(display, keycode);
   event.state       = modifiers;
   if(press)
      event.type = KeyPress;
   else
      event.type = KeyRelease;
   return event;
}

void pressKey(Display* display, Window &win_focus, Window &win_root,
              KeySym key, int modifiers)
{
    // Send a fake key press event to the window.
    XKeyEvent event = createKeyEvent(display, win_focus, win_root, true, key, modifiers);
    XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
    // Send a fake key release event to the window.
    event = createKeyEvent(display, win_focus, win_root, false, key, modifiers);
    XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
}

然后,您可以使用它来发送关键事件(在这种情况下为Alt W)如下:

// Obtain the X11 display.
Display *display = XOpenDisplay(0);
if (display == NULL)
{
  printf("Null display!n");
  return 1;
}
// Get the root window for the current display
Window win_root = XDefaultRootWindow(display);
// Find the window which has the current keyboard focus
Window win_focus;
int    revert;
XGetInputFocus(display, &win_focus, &revert);

pressKey(display, win_focus, win_root, XK_w, MOD_ALT);
if (display)
  XCloseDisplay(display);

解决方案2 使用Xtest库可以实现类似的行为。尽管它在"更高级别"上运行,例如,窗口管理器也将拿起这些按键。Xtest的pressKey函数看起来像这样(不是很干净的代码):

void pressKey(Display* display, KeySym modifier1, KeySym modifier2, KeySym key)
{
    // Release every other modifier
    KeyCode keycodec = XKeysymToKeycode(display, XK_Control_L);
    KeyCode keycodea = XKeysymToKeycode(display, XK_Alt_L);
    KeyCode keycodes = XKeysymToKeycode(display, XK_Shift_L);
    XTestFakeKeyEvent(display, keycodec, False, 0); // key release event
    XTestFakeKeyEvent(display, keycodea, False, 0); // key release event
    XTestFakeKeyEvent(display, keycodes, False, 0); // key release event
    XFlush(display);
    // Press the actual keys
    KeyCode keycode1 = XKeysymToKeycode(display, modifier1);
    KeyCode keycode2 = XKeysymToKeycode(display, modifier2);
    KeyCode keycode3 = XKeysymToKeycode(display, key);
    if (keycode1)
        XTestFakeKeyEvent(display, keycode1, True, 0); // key press event
    if (keycode2)
        XTestFakeKeyEvent(display, keycode2, True, 0); // key press event
    if (keycode3)
    {
        XTestFakeKeyEvent(display, keycode3, True, 0); // key press event
        XTestFakeKeyEvent(display, keycode3, False, 0); // key release event
    }
    if (keycode2)
        XTestFakeKeyEvent(display, keycode2, False, 0); // key release event
    if (keycode1)
        XTestFakeKeyEvent(display, keycode1, False, 0); // key release event
    XFlush(display);
}

解决方案3 另一个解决方案是只用Xdotool等工具脚本脚本。基本上,您所描述的大部分都可以通过BASH脚本来实现。另外,Xdotool源代码是有关如何实现您想要的一切的重要信息来源。

最新更新