私の目標は、バックグラウンドでスリープするが、ユーザーが「ホットキー」を介してアクティブ化できるプログラムを作成することです。XlibマニュアルとXlibO'reillyマニュアルを掘り下げてみると、これを行う正しい方法はXGrabKeyを使用することであることがわかりました。ただし、単純な概念実証が機能しないため、プロセスの私の理解は正しくありません。
私の理解では、ルートウィンドウをgrab_windowとしてXGrabKeyを呼び出し、owner_eventsをfalseにすると、ホットキーが押されるたびに、イベントはルートウィンドウにのみ送信されます。次に、ルートウィンドウからKeyPressイベントを選択し、Xイベントをリッスンすると、ホットキーが押されたときにキープレスイベントを取得する必要があります。以下に最小限の例を貼り付けました。
プログラムの実行時に、フォーカスのあるウィンドウに関係なく、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;
}