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

时间:2016-08-22 19:12:03

标签: x11 hotkeys xlib

总体目标就像Windows的Alt-Tab,所以我将使用这些键进行解释。我想:
按Alt - >按Tab键 - > [popup出现] - >任何时候按住Tab键按Tab键 - >发布Alt - > [popup消失]。

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

  1. 琐碎的方法:抓住Alt-Tab:

    XGrabKey (dpy, 
      XKeysymToKeycode(dpy,XK_Tab), Mod1Mask,
      root, True, GrabModeAsync, GrabModeAsync);
    

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

    结果:

    [按下了]
    [按下按钮]
    按Alt-Tab报告
    [标签发布]
    释放Alt-Tab报告了
    [已发布] - >没有报道

  2. 抓住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-Tab报告
    [标签发布]
    释放Alt-Tab报告了
    [Alt发布]
    发布Alt-Alt报告

    但是这会隐藏任何正在运行的程序中的Alt组合。 我找不到推回不属于我们的事件的方法(尝试过XSendEvent),并且从一开始就从总体上抓取Alt看起来太具有侵略性。

  3. 在第一次Alt-Tab按下后抓取Alt,然后在释放后取消对齐。

    不幸的是,仍未报告第一个Alt版本:

    [按下了]
    [按下按钮]
    按下Alt-Tab报告,Alt抓住了这里 [标签发布]
    释放Alt-Tab报告了
    [已发布] - >没有报道!报告后续的Alt按下/释放,但没有用处:
    [按下了]
    按Alt报告了
    ...

  4. 我是否需要处理低级xinput,或者还有另一种方法来实现目标?

1 个答案:

答案 0 :(得分:1)

如果您在按下按键后对其产生了兴趣,那么您似乎无法获得KeyRelease事件。

我可以想出两种不同的方法。

  1. 所有窗口选择KeyReleaseMask(并跟踪出现和消失的窗口);
  2. 一旦你知道Alt被按下,每0.1秒左右用XQueryKeyboard轮询键盘状态,直到它被释放。
  3. 我测试了第一种方法,它似乎正在起作用:

    #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;
    }