代码之家  ›  专栏  ›  技术社区  ›  cheshirekow

带有x11/xlib的全局热键

  •  28
  • cheshirekow  · 技术社区  · 14 年前

    我的目标是有一个在后台睡觉的程序,但是用户可以通过一些“热键”来激活它。通过深入了解XLIB手册和XLIB O'Reilly手册,我认为正确的方法是使用XGrabKey。然而,我对这个过程的理解是错误的,因为一个简单的概念证明是行不通的。

    我的理解是,如果我使用根窗口作为抓取窗口调用xgrabkey,并且owner事件为false,那么每当按下热键时,都会发送事件。 只有 到根窗口。如果我从根窗口中选择key press events,然后监听x事件,我应该在按下热键时得到一个keypress事件。我在下面粘贴了一个最小的示例。

    我所期望的是,当程序运行时,无论哪个窗口有焦点,如果按下ctrl+shift+k,程序都应该输出“热键按下!”在控制台中,然后终止。

    此外,据我所知,如果XGrabKey失败,默认的错误处理程序将显示一条消息,因为它不成功,所以我假设调用成功。

    显然,我的理解有缺陷。有人能给我指出正确的方向吗?

    #include <iostream>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    
    
    using namespace std;
    
    
    int main()
    {
        Display*    dpy     = XOpenDisplay(0);
        Window      root    = DefaultRootWindow(dpy);
        XEvent      ev;
    
        unsigned int    modifiers       = ControlMask | ShiftMask;
        int             keycode         = XKeysymToKeycode(dpy,XK_Y);
        Window          grab_window     =  root;
        Bool            owner_events    = False;
        int             pointer_mode    = GrabModeAsync;
        int             keyboard_mode   = GrabModeAsync;
    
        XGrabKey(dpy, keycode, modifiers, grab_window, owner_events, pointer_mode,
                 keyboard_mode);
    
        XSelectInput(dpy, root, KeyPressMask );
        while(true)
        {
            bool shouldQuit = false;
            XNextEvent(dpy, &ev);
            switch(ev.type)
            {
                case KeyPress:
                    cout << "Hot key pressed!" << endl;
                    XUngrabKey(dpy,keycode,modifiers,grab_window);
                    shouldQuit = true;
    
                default:
                    break;
            }
    
            if(shouldQuit)
                break;
        }
    
        XCloseDisplay(dpy);
        return 0;
    }
    
    3 回复  |  直到 9 年前
        1
  •  21
  •   Havoc P    14 年前

    /* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
    static void
    meta_change_keygrab (MetaDisplay *display,
                         Window       xwindow,
                         gboolean     grab,
                         int          keysym,
                         unsigned int keycode,
                         int          modmask)
    {
      unsigned int ignored_mask;
    
      /* Grab keycode/modmask, together with
       * all combinations of ignored modifiers.
       * X provides no better way to do this.
       */
    
      meta_topic (META_DEBUG_KEYBINDINGS,
                  "%s keybinding %s keycode %d mask 0x%x on 0x%lx\n",
                  grab ? "Grabbing" : "Ungrabbing",
                  keysym_name (keysym), keycode,
                  modmask, xwindow);
    
      /* efficiency, avoid so many XSync() */
      meta_error_trap_push (display);
    
      ignored_mask = 0;
      while (ignored_mask <= display->ignored_modifier_mask)
        {
          if (ignored_mask & ~(display->ignored_modifier_mask))
            {
              /* Not a combination of ignored modifiers
               * (it contains some non-ignored modifiers)
               */
              ++ignored_mask;
              continue;
            }
    
          if (meta_is_debugging ())
            meta_error_trap_push_with_return (display);
          if (grab)
            XGrabKey (display->xdisplay, keycode,
                      modmask | ignored_mask,
                      xwindow,
                      True,
                      GrabModeAsync, GrabModeSync);
          else
            XUngrabKey (display->xdisplay, keycode,
                        modmask | ignored_mask,
                        xwindow);
    
          if (meta_is_debugging ())
            {
              int result;
    
              result = meta_error_trap_pop_with_return (display, FALSE);
    
              if (grab && result != Success)
                {      
                  if (result == BadAccess)
                    meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), keysym_name (keysym), modmask | ignored_mask);
                  else
                    meta_topic (META_DEBUG_KEYBINDINGS,
                                "Failed to grab key %s with modifiers %x\n",
                                keysym_name (keysym), modmask | ignored_mask);
                }
            }
    
          ++ignored_mask;
        }
    
      meta_error_trap_pop (display, FALSE);
    }
    
        2
  •  9
  •   Christian Hujer    10 年前

    ControlMask | ShiftMask

    • XGrabKey()
    • AnyModifier event.xkey.state

    <X.h> ShiftMask LockMask ControlMask Mod1Mask Mod2Mask Mod3Mask Mod4Mask Mod5Mask

    Mask        | Value | Key
    ------------+-------+------------
    ShiftMask   |     1 | Shift
    LockMask    |     2 | Caps Lock
    ControlMask |     4 | Ctrl
    Mod1Mask    |     8 | Alt
    Mod2Mask    |    16 | Num Lock
    Mod3Mask    |    32 | Scroll Lock
    Mod4Mask    |    64 | Windows
    Mod5Mask    |   128 | ???
    

    ModNMask

    ShiftMask | CtrlMask Mod1Mask | Mod4Mask

    XGrabKey(dpy, keycode, AnyModifier, grab_window, owner_events, pointer_mode, keyboard_mode);
    

    switch (ev.type)  {
    case KeyPress:
        if ((ev.xkey.state & (ShiftMask | CtrlMask | Mod1Mask | Mod4Mask)) == (ShiftMask | CtrlMask))
            // ...
    }