X11/Xlib的全局热键 [英] Global Hotkey with X11/Xlib

查看:333
本文介绍了X11/Xlib的全局热键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是拥有一个程序,该程序在后台休眠,但可由用户通过某些热键"激活.通过深入研究Xlib手册和Xlib O'reilly手册,我了解到正确的方法是使用XGrabKey.但是,由于对概念的简单证明不起作用,因此我对过程的理解是不正确的.

My goal is to have a program that sleeps in the background but can be activated by the user via some "hotkey". From digging around the Xlib manual and the Xlib O'reilly manual, I gather that the correct way to to this is with XGrabKey. However my understanding of the process is incorrect as a simple proof of concept does not work.

我的理解是,如果我用根窗口作为grab_window调用XGrabKey,并且owner_events为false,那么每当按下我的热键时,事件将仅发送 到根窗口.如果然后从根窗口中选择KeyPress事件,然后侦听X事件,则在按下热键时应该会收到一个按键事件.我在下面粘贴了一个最小的示例.

My understanding is that if I call XGrabKey with the root window as the grab_window, and owner_events false, then whenever my hotkey is pressed the event will be sent only to the root window. If I then select KeyPress events from the root window, and then listen for X events, I should get a key press event when the hotkey is pressed. I've pasted a minimal example below.

我希望在运行程序时,无论哪个窗口具有焦点,如果按下Ctrl + Shift + K,我的程序都将输出按下热键!"在控制台中,然后终止.

What I expect is that when the program is run, regardless of what window has focus, if Ctrl+Shift+K is pressed, my program should output "Hot key pressed!" in the console, and then terminate.

此外,据我了解,如果XGrabKey失败,则默认错误处理程序将显示一条消息,并且由于该错误,我不认为调用成功.

Furthermore, it is my understanding that if the XGrabKey fails, the default error handler will display a message, and since it does not I am assuming that the call succeeds.

很显然,我的理解在某种程度上存在缺陷.谁能指出我正确的方向?

Obviously, my understanding is flawed somehow. Can anyone point me in the right direction?

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

推荐答案

您的程序在这里工作.我的猜测是您还有另一个修改器处于活动状态,例如NumLock. GrabKey仅在 exact 修饰符掩码上有效.

Your program works here. My guess is you have another modifier active, such as NumLock. GrabKey only works on the exact modifier mask.

例如,以下是metacity窗口管理器中的一些(GPL)代码

For example here is some (GPL) code from metacity window manager

/* 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);
}

这篇关于X11/Xlib的全局热键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆