我试着编写了一个程序,每当在Ubuntu(KDE)中按下每个键时,它都会挂钩键盘消息来发音每个键的名称;而不会干扰程序中键盘的正常操作(只需宣布键名称)。
这是我的程序:
# include <X11/Xlib.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <iostream>
using namespace std;
void SendPressKeyEvent(Display *display, XKeyEvent xkey)
{
Window current_focus_window;
int current_focus_revert;
XGetInputFocus(display, ¤t_focus_window, ¤t_focus_revert);
xkey.type = KeyPress;
xkey.display = display;
xkey.window = current_focus_window;
xkey.root = DefaultRootWindow(display);
xkey.subwindow = None;
xkey.time = 1000 * time(0);
xkey.x = 0;
xkey.y = 0;
xkey.x_root = 0;
xkey.y_root = 0;
xkey.same_screen = True;
XSendEvent(display, InputFocus, True, KeyPressMask, (XEvent *)(&xkey));
}
void SendReleaseKeyEvent(Display *display, XKeyEvent xkey)
{
Window current_focus_window;
int current_focus_revert;
XGetInputFocus(display, ¤t_focus_window, ¤t_focus_revert);
xkey.type = KeyRelease;
xkey.display = display;
xkey.window = current_focus_window;
xkey.root = DefaultRootWindow(display);
xkey.subwindow = None;
xkey.time = 1000 * time(0);
xkey.x = 0;
xkey.y = 0;
xkey.x_root = 0;
xkey.y_root = 0;
xkey.same_screen = True;
XSendEvent(display, InputFocus, True, KeyReleaseMask, (XEvent *)(&xkey));
}
void *TaskCode(void* arg)
{
switch(*(int*)arg)
{
case 38:
system("espeak -v en " ""a"");
}
return 0;
}
int main()
{
Display *display = XOpenDisplay(0);
if(display == 0)
exit(1);
XGrabKeyboard(display, DefaultRootWindow(display), True, GrabModeAsync, GrabModeAsync, CurrentTime);
XEvent event;
while(true)
{
XNextEvent(display, &event);
if(event.type == Expose)
{
}
if(event.type == KeyPress)
{
SendPressKeyEvent(display,event.xkey);
if(event.xkey.keycode == 38)
{
pthread_t thread;
int thread_arg = event.xkey.keycode;
pthread_create(&thread,0, TaskCode, (void*) &thread_arg);
}
}
if(event.type == KeyRelease)
SendReleaseKeyEvent(display,event.xkey);
}
XCloseDisplay(display);
}
本程序只针对密钥a,可以扩展到其他密钥。
但当这个程序运行时,一些程序(如Chromium)在它们的编辑框中不会显示闪烁(光标)。此外,所有KDE热键都被禁用。
如何才能解决这个问题?
4条答案
按热度按时间omjgkv6w1#
这是我的快速和肮脏的例子
这并不可靠,但大多数情况下它是有效的。(它显示的是我现在在这个框中输入的密钥)。你可能会调查为什么它有时会失败;)而且它原则上不能显示热键。热键是被抢占的密钥,只有一个客户端可以获得被抢占的密钥。这里除了加载专门为此目的而设计的X11扩展(例如XEvIE)外,什么都做不了。
zbwhf8kr2#
感谢n.m.的answer和parsa的评论,这是我的最终代码:
将这些内容添加到Qt Creator的项目.pro文件中:
如有任何改进建议,我们将不胜感激。
为了存档,我还使用Grabing添加了我的最终代码:
一切都很好,除了与所讨论的代码不同,它忽略了语言布局。按下任何类型的
a
,无论语言布局如何!7qhs6swi3#
作为监听X事件的替代方案,还可以直接监听Linux输入事件:https://stackoverflow.com/a/27693340/21501
这样做的好处是可以修改正在运行的事件流,并阻止、编辑或生成输入事件。
iyr7buue4#
收听所有事件的正确方法是使用X记录扩展库,它是
libXtst
的一部分,显然安装在几乎每个X系统上。它是here文档,但由于文档不完整,您需要浏览以前的实现。Here是一个很好的工作演示,而here是一个更有能力和更完整的实现。下面包括第一个示例的简化版本。
gcc -o x1 x1.c -lX11 -lXtst