我试图编写一个程序,只要在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可以扩展到其他键的键。
a
但是,当该程序运行时,某些程序(例如Chromium)不会在其编辑框中显示闪烁信号(光标)。同样,所有的KDE热键也被禁用。
如何解决?
这是我的例子
#include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <ctype.h> int main () { Display* d = XOpenDisplay(NULL); Window root = DefaultRootWindow(d); Window curFocus; char buf[17]; KeySym ks; XComposeStatus comp; int len; int revert; XGetInputFocus (d, &curFocus, &revert); XSelectInput(d, curFocus, KeyPressMask|KeyReleaseMask|FocusChangeMask); while (1) { XEvent ev; XNextEvent(d, &ev); switch (ev.type) { case FocusOut: printf ("Focus changed!\n"); printf ("Old focus is %d\n", (int)curFocus); if (curFocus != root) XSelectInput(d, curFocus, 0); XGetInputFocus (d, &curFocus, &revert); printf ("New focus is %d\n", (int)curFocus); if (curFocus == PointerRoot) curFocus = root; XSelectInput(d, curFocus, KeyPressMask|KeyReleaseMask|FocusChangeMask); break; case KeyPress: printf ("Got key!\n"); len = XLookupString(&ev.xkey, buf, 16, &ks, &comp); if (len > 0 && isprint(buf[0])) { buf[len]=0; printf("String is: %s\n", buf); } else { printf ("Key is: %d\n", (int)ks); } } } }
它不可靠,但在大多数情况下都有效。(它显示的是我正在此框中输入的键)。您可能会调查为什么有时会失败;)原则上它也不能显示热键。热键是获取的密钥,只有一个客户端可以获取获取的密钥。除了加载为此目的而设计的特殊X11扩展(例如XEvIE)以外,这里绝对不能做任何事情。