XGrabKeyboard仅在程序运行时阻止键盘

XGrabKeyboard only blocks the keyboard while the program is running

本文关键字:键盘 运行时 程序 XGrabKeyboard      更新时间:2023-10-16

我正在编写一个代码来获取按下的键并阻止键盘输入。示例:如果按下Super_L或Super_R键,则阻止它们打开应用程序菜单。当程序打开时,代码可以工作,但当程序关闭时,密钥会发送到系统。示例:如果用户按下Super_L键,程序运行时不会发生任何事情,但当程序关闭时,Ubuntu应用程序菜单会自动打开。如何解决此问题?

void hook()
{
    Display *dpy = XOpenDisplay(0);
    XEvent ev;
    if(!dpy)
    {
        qDebug() << "Error";
        return;
    }
    XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
    forever
    {
        XNextEvent(dpy, &ev);
        switch (ev.type)
        {
        case KeyPress:
            qDebug() << "KeyPress" << XKeysymToString(XKeycodeToKeysym(dpy, ev.xkey.keycode, 0));
            break;
        case KeyRelease:
            qDebug() << "KeyRelease" << XKeysymToString(XKeycodeToKeysym(dpy, ev.xkey.keycode, 0));
            break;
        }
    }
}

引用手册:

当X服务器与客户端的连接被对XCloseDisplay()的显式调用,或者由退出的进程,X服务器执行以下自动操作:

  • 它将取消客户端拥有的所有选择(请参见XSetSelectionOwner()
  • 如果客户端主动抓取指针或键盘,则执行XUngrabPointer()XUngrabKeyboard()
  • 如果客户端已经占用了服务器,则执行XUngrabServer()
  • 它释放客户端进行的所有被动抓取

Grabs是由客户请求并授予客户的。在抓取过程中,所有相关事件都会传递到抓取客户端。没有客户,就没有抓人。

我不知道该怎么办。如果您希望某个功能正常工作,请确保实现该功能的应用程序正在运行。

来自man XGetKeyboard:

如果活动键盘抓取的事件窗口不可见,X服务器会自动执行UngrabKeyboard请求。

这是故意的。否则,键盘可能会被一个不起作用的应用程序无限期地占用,这不会得到用户的赞赏。诚然,该窗口仍然可以查看(它是根窗口),但显示连接已关闭,因此原理是相同的。

如果您的应用程序在关闭后仍需要保留抓取。。。好吧,你将不得不呆在幕后而不真正退出。