检测 X11 root 中的修改键释放 window
Detect modifier key release in X11 root window
总体目标类似于 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 键]
[按下 Tab 键]
报告按 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
[按下 Tab 键]
报告按 Alt-Tab
[标签发布]
报告释放 Alt-Tab
[替代发布]
发布 Alt-Alt 报告
但这会隐藏任何 运行 程序的任何 Alt 组合。
我找不到推回不属于我们的事件的方法(试过 XSendEvent),而且从一开始就抓住 Alt 看起来太具有侵略性了。
在第一次按下 Alt-Tab 后抓住 Alt,然后在释放 Alt 后取消抓住 Alt。
遗憾的是,第一个 Alt 版本仍未报告:
[按下 Alt 键]
[按下 Tab 键]
按 Alt-Tab 报告,Alt 抓住这里
[标签发布]
报告释放 Alt-Tab
[ 替代发布 ] -> 没有任何报道!随后的 Alt press/release 被报告,但没有用:
[ Alt 按下 ]
报告按 Alt
...
我需要搞乱低级 xinput 还是有其他方法可以实现目标?
如果您在按下键后注册了对它的兴趣,那么您似乎不会收到 KeyRelease
事件。
我可以想到两种不同的解决方法。
- Select
KeyReleaseMask
for all windows(并跟踪出现和消失的情况 windows); 或
- 一旦你知道 Alt 被按下,每隔 0.1 秒左右用
XQueryKeyboard
轮询键盘状态,直到它被释放。
我已经测试了第一种方法,它似乎有效:
#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;
}
总体目标类似于 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 键]
[按下 Tab 键]
报告按 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
[按下 Tab 键]
报告按 Alt-Tab
[标签发布]
报告释放 Alt-Tab
[替代发布]
发布 Alt-Alt 报告但这会隐藏任何 运行 程序的任何 Alt 组合。 我找不到推回不属于我们的事件的方法(试过 XSendEvent),而且从一开始就抓住 Alt 看起来太具有侵略性了。
在第一次按下 Alt-Tab 后抓住 Alt,然后在释放 Alt 后取消抓住 Alt。
遗憾的是,第一个 Alt 版本仍未报告:
[按下 Alt 键]
[按下 Tab 键]
按 Alt-Tab 报告,Alt 抓住这里
[标签发布]
报告释放 Alt-Tab
[ 替代发布 ] -> 没有任何报道!随后的 Alt press/release 被报告,但没有用:
[ Alt 按下 ]
报告按 Alt
...
我需要搞乱低级 xinput 还是有其他方法可以实现目标?
如果您在按下键后注册了对它的兴趣,那么您似乎不会收到 KeyRelease
事件。
我可以想到两种不同的解决方法。
- Select
KeyReleaseMask
for all windows(并跟踪出现和消失的情况 windows); 或 - 一旦你知道 Alt 被按下,每隔 0.1 秒左右用
XQueryKeyboard
轮询键盘状态,直到它被释放。
我已经测试了第一种方法,它似乎有效:
#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;
}