mzu*_*her 21 x11 keyboard autorepeat
如果在启用AutoRepeat的同时在X11中按住某个键,则会连续收到KeyPress和KeyRelease事件.我知道,自动重复可使用功能被禁用XAutoRepeatOff(),但是这改变了整个X服务器的设置.有没有办法为单个应用程序禁用AutoRepeat或忽略重复的击键?
我正在寻找的是当按下一个键时的单个KeyPress事件和一个释放键时的单个KeyRelease事件,而不会干扰X服务器的AutoRepeat设置.
这是一个让你前进的最小例子(主要来自初学者Xlib教程):
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
Display *dis;
Window win;
XEvent report;
int main ()
{
dis = XOpenDisplay (NULL);
// XAutoRepeatOn(dis);
win = XCreateSimpleWindow (dis, RootWindow (dis, 0), 1, 1, 500, 500,
0, BlackPixel (dis, 0), BlackPixel (dis, 0));
XSelectInput (dis, win, KeyPressMask | KeyReleaseMask);
XMapWindow (dis, win);
XFlush (dis);
while (1)
{
XNextEvent (dis, &report);
switch (report.type)
{
case KeyPress:
fprintf (stdout, "key #%ld was pressed.\n",
(long) XLookupKeysym (&report.xkey, 0));
break;
case KeyRelease:
fprintf (stdout, "key #%ld was released.\n",
(long) XLookupKeysym (&report.xkey, 0));
break;
}
}
return (0);
}
Run Code Online (Sandbox Code Playgroud)
小智 19
当您收到一个密钥释放并且下一个事件是按下相同的组合键时,它会自动重复并且该键未被实际释放.你可以使用这样的代码来查看下一个事件
if (event->type == KeyRelease && XEventsQueued(disp, QueuedAfterReading))
{
XEvent nev;
XPeekEvent(disp, &nev);
if (nev.type == KeyPress && nev.xkey.time == event->xkey.time &&
nev.xkey.keycode == event->xkey.keycode)
{
/* Key wasn’t actually released */
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用XkbSetDetectableAutorepeat函数告诉X服务器仅在用户实际释放密钥时发送KeyRelease事件 - 当您不想要自动重复事件时,则丢弃任何KeyPress而不匹配KeyRelease.
供您参考,这是一个工作的最小示例,删除自动重复的KeyPress事件. 谢谢,kralyk!
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
Display *dis;
Window win;
XEvent report;
int main ()
{
dis = XOpenDisplay (NULL);
// XAutoRepeatOn(dis);
win = XCreateSimpleWindow (dis, RootWindow (dis, 0), 1, 1, 500, 500,
0, BlackPixel (dis, 0), BlackPixel (dis, 0));
XSelectInput (dis, win, KeyPressMask | KeyReleaseMask);
XMapWindow (dis, win);
XFlush (dis);
while (1)
{
XNextEvent (dis, &report);
switch (report.type)
{
case KeyPress:
fprintf (stdout, "key #%ld was pressed.\n",
(long) XLookupKeysym (&report.xkey, 0));
break;
case KeyRelease:
{
unsigned short is_retriggered = 0;
if (XEventsQueued(dis, QueuedAfterReading))
{
XEvent nev;
XPeekEvent(dis, &nev);
if (nev.type == KeyPress && nev.xkey.time == report.xkey.time &&
nev.xkey.keycode == report.xkey.keycode)
{
fprintf (stdout, "key #%ld was retriggered.\n",
(long) XLookupKeysym (&nev.xkey, 0));
// delete retriggered KeyPress event
XNextEvent (dis, &report);
is_retriggered = 1;
}
}
if (!is_retriggered)
fprintf (stdout, "key #%ld was released.\n",
(long) XLookupKeysym (&report.xkey, 0));
}
break;
}
}
return (0);
}
Run Code Online (Sandbox Code Playgroud)