[英]Capturing Window Events in Linux/Ubuntu (Screen-Capture + Mouse/Keyboard-Events)
I want to develop an Application in C++ for Linux that needs to interact with other programs via standard IO (Mouse + Keyboard). 我想为Linux开发C ++应用程序,该应用程序需要通过标准IO(鼠标+键盘)与其他程序进行交互。 It should be able to send Mouse/Keyboard Input to a Window and to capture a "screenshot" of that specific window.
它应该能够将鼠标/键盘输入发送到窗口,并捕获该特定窗口的“屏幕快照”。
(1) Now I have done some research and I know that Linux uses the "X Window"-System. (1)现在,我已经进行了一些研究,并且我知道Linux使用“ X Window”系统。 Is it advised to start on this layer for the programming or should I use some higher level framework (eg wxWidgets)?
是否建议从这一层开始进行编程,还是应该使用更高级别的框架(例如wxWidgets)?
(2) Is it possible to send input events to/capture the screen of a window even though it's not focused? (2)是否可以将输入事件发送到/捕获窗口的屏幕,即使它没有聚焦?
(3) I am not asking you for code, but I would love to work through some literature on that topic. (3)我不是要您提供代码,而是希望阅读一些有关该主题的文献。 Sadly, I couldn't find any good sources on this topic.
可悲的是,我找不到关于此主题的任何好的资料。
It would be great if someone could help me on this one! 如果有人可以帮助我,那就太好了!
Thank you in Advance!! 先感谢您!!
[ Note: This program should running as backend and later execute commands from a java application. [注意:该程序应作为后端运行,并稍后从Java应用程序执行命令。 The plan is to implement this backend C++ App for Windows/Linux seperately ]
该计划是分别为Windows / Linux实施此后端C ++ App]
Solution 1 I can recommend a piece of code for sending keyboard events which I use myself to simulate key presses. 解决方案1我可以推荐一段用于发送键盘事件的代码,这些代码我自己用来模拟按键。 It is based on XSendEvent.
它基于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);
}
Then, you can use it to send a key event (in this case Alt+W) as follows: 然后,您可以使用它来发送按键事件(在本例中为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);
Solution 2 A similar behavior can be achieved using the XTest library. 解决方案2使用XTest库可以实现类似的行为。 It operates on a "higher level" though and for instance the window manager will pick up those keypresses as well.
但是,它在“更高级别”上运行,例如,窗口管理器也将拾取这些按键。 The pressKey function for XTest can look like this (not very clean code):
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);
}
Solution 3 Another solution is to just script your way out with such tools as xdotool . 解决方案3另一个解决方案是仅使用xdotool这样的工具编写脚本。 Basically, most of what you described can be achieved with a bash script.
基本上,您描述的大部分内容都可以通过bash脚本来实现。 Also xdotool source code is a great source of information on how to achieve all you want.
此外, xdotool源代码还是有关如何实现所需功能的大量信息来源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.