gpt4 book ai didi

c++ - 在 Linux/Ubuntu 中捕获窗口事件(屏幕捕获 + 鼠标/键盘事件)

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:07:55 31 4
gpt4 key购买 nike

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

(1) 现在我做了一些研究,我知道 Linux 使用“X Window”-System。是否建议从这一层开始编程,还是应该使用一些更高级别的框架(例如 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 source code是有关如何实现您想要的一切的重要信息来源。

关于c++ - 在 Linux/Ubuntu 中捕获窗口事件(屏幕捕获 + 鼠标/键盘事件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30110095/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com