x11 - 在 X11 根窗口中检测修改键释放

标签 x11 hotkeys xlib

总体目标类似于 Windows 的 Alt-Tab,因此我将使用这些键进行说明。我想要:
按 Alt -> 按 Tab -> [ 弹出窗口出现 ] -> 在按住 Alt 的任何时候按 Tab -> 松开 Alt -> [ 弹出窗口消失 ]。

我无法检测到最终的 Alt 版本。

  • 简单的方法:捕获 Alt-Tab:
    XGrabKey (dpy, 
      XKeysymToKeycode(dpy,XK_Tab), Mod1Mask,
      root, True, GrabModeAsync, GrabModeAsync);
    

    (完整代码:http://pastebin.com/K2P65KJn)

    结果:

    [按下 Alt ]
    [ 标签按下 ]
    按 Alt-Tab 报告
    [标签发布]
    释放 Alt-Tab 报告
    [Alt 发布] -> 没有任何报告
  • 捕获 Alt-Tab 和 Any-Alt:
    XGrabKey (dpy, 
      XKeysymToKeycode(dpy,XK_Tab), Mod1Mask,
      root, True, GrabModeAsync, GrabModeAsync);
    XGrabKey (dpy, 
      XKeysymToKeycode(dpy,XK_Alt_L), AnyModifier,
      root, True, GrabModeAsync, GrabModeAsync);
    

    (完整代码:http://pastebin.com/75mD1tjA)

    有用!

    [按下 Alt ]
    按 Alt 报告
    [ 标签按下 ]
    按 Alt-Tab 报告
    [标签发布]
    释放 Alt-Tab 报告
    [Alt 发布]
    释放 Alt-Alt 报告

    但这对任何正在运行的程序隐藏了任何 Alt 组合。
    我找不到推回不属于我们的事件的方法(尝试过 XSendEvent),而且总体上从一开始就捕获 Alt 看起来太具有侵略性了。
  • 在第一次按下 Alt-Tab 后捕获 Alt,然后在释放后取消捕获 Alt。

    不幸的是,仍然没有报道第一个 Alt 版本:

    [按下 Alt ]
    [ 标签按下 ]
    按 Alt-Tab 报告,Alt 捕获这里
    [标签发布]
    释放 Alt-Tab 报告
    [Alt 发布] -> 没有任何报道!报告了随后的 Alt 新闻/发布,但没有用:
    [按下 Alt ]
    按 Alt 报告
    ...

  • 我需要搞乱低级 xinput 还是有另一种方法来实现目标?

    最佳答案

    看来您不会收到 KeyRelease事件,如果您在按键后注册了它的兴趣。

    我可以想到两种不同的方法来解决这个问题。

  • 选择 KeyReleaseMask对于所有窗口(并跟踪出现和消失的窗口);或
  • 一旦你知道 Alt 被按下,用 XQueryKeyboard 轮询键盘状态每 0.1 秒左右,直到它被释放。

  • 我已经测试了第一种方法,它似乎有效:
    #include <X11/Xlib.h>            
    #include <X11/Xutil.h>           
    #include <stdbool.h>             
    #include <stdio.h>               
    
    void dowin (Display* dpy, Window win, int reg)
    {                                             
      Window root, parent;                        
      Window* children;                           
      int nchildren, i;                           
    
      XSelectInput (dpy, win, reg ? KeyReleaseMask|SubstructureNotifyMask : 0);
      XQueryTree (dpy, win, &root, &parent, &children, &nchildren);            
    
      for (i = 0; i < nchildren; ++i)
      {                              
        dowin (dpy, children[i], reg);
      }                               
    
      XFree(children);
    }                 
    
    
    int main()        
    {                 
        Display*    dpy     = XOpenDisplay(0);
        Window      win     = DefaultRootWindow(dpy);
        XEvent      ev;
    
        unsigned int    alt_modmask       = Mod1Mask;
        unsigned int    ignored_modmask   = 0; // stub
        KeyCode         tab_keycode       = XKeysymToKeycode(dpy,XK_Tab);
        KeyCode         alt_keycode       = XKeysymToKeycode(dpy,XK_Alt_L);
    
        dowin (dpy, win, True);
    
        XGrabKey (dpy,
                tab_keycode,
                alt_modmask | ignored_modmask,
                win,
                True,
                GrabModeAsync, GrabModeAsync);
    
    
        while(true)
        {
            ev.xkey.keycode = 0;
            ev.xkey.state = 0;
            ev.xkey.type = 0;
    
            XNextEvent(dpy, &ev);
            switch(ev.type)
            {
                case KeyPress:
                    printf ("Press %x: d-%d\n", ev.xkey.window, ev.xkey.state, ev.xkey.keycode);
                    break;
    
                case KeyRelease:
                    printf ("Release %x: %d-%d\n", ev.xkey.window, ev.xkey.state, ev.xkey.keycode);
                    break;
    
                case MapNotify:
                    printf ("Mapped %x\n", ev.xmap.window);
                    dowin (dpy, ev.xmap.window, True);
                    break;
    
                case UnmapNotify:
                    printf ("Unmapped %x\n", ev.xunmap.window);
                    dowin (dpy, ev.xunmap.window, False);
                    break;
    
                default:
                    printf ("Event type %d\n", ev.type);
                    break;
            }
    
        }
    
        XCloseDisplay(dpy);
        return 0;
    }
    

    关于x11 - 在 X11 根窗口中检测修改键释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39087079/

    相关文章:

    Cocoa NSStatusBar 全局热键

    .net - C# Hide() 在启动时,没有 ShowInTaskbar 为 false

    X11:XGrabPointer会阻止其他应用程序发生任何鼠标事件吗?

    c - 如何从X服务器读取鼠标点击事件

    python - 如何使用 python-xlib 读取 X 属性?

    xcode - 是否可以在Xcode中按住Command键将符号单击到新选项卡中?

    linux - linux gui 中的 DDE/IPC?

    linux - Master/Slave AMD + NVidia中的GPU和linux

    c++ - Xorg 选择夹板

    macos - Mac OS X 10.9 上的 Gnuplot - X11 终端和鼠标交互