![C 编程:检测鼠标指针移动](https://linux22.com/image/939076/C%20%E7%BC%96%E7%A8%8B%EF%BC%9A%E6%A3%80%E6%B5%8B%E9%BC%A0%E6%A0%87%E6%8C%87%E9%92%88%E7%A7%BB%E5%8A%A8.png)
我正在做一个项目,需要仅当鼠标指针在一段时间内(例如 30 秒)没有移动时设置一个标志:如果鼠标空闲了 30 秒,则设置no_movement
(no_movement=true;
)。
到目前为止,我知道 X window 服务器是许多桌面环境的后端,并且我知道在组织和tronche.com(我从那里得知有一个名为的指针事件MotionNotify
)。
使用apt show xserver-xorg | grep Version
我发现我的系统上安装的 Xserver 版本是 1:7.7+22ubuntu1(在 Ubuntu 21.04 上)
获取鼠标指针移动反馈的推荐方法是什么?
感谢您花时间回复我。
答案1
X11 有相当完善的“事件掩码”文档
https://tronche.com/gui/x/xlib/events/mask.html
或者总是有XQueryPointer)..
// Try this C program as the basis of what you want todo..
#include <stdio.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
int main(int argc, char **argv)
{
Display *display;
Window root_window;
/* Initialize (FIXME: no error checking). */
display = XOpenDisplay(0);
root_window = XRootWindow(display, 0);
/* check XInput */
int xi_opcode, event, error;
if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
fprintf(stderr, "Error: XInput extension is not supported!\n");
return 1;
}
/* Check XInput 2.0 */
int major = 2;
int minor = 0;
int retval = XIQueryVersion(display, &major, &minor);
if (retval != Success) {
fprintf(stderr, "Error: XInput 2.0 is not supported (ancient X11?)\n");
return 1;
}
/*
* Set mask to receive XI_RawMotion events. Because it's raw,
* XWarpPointer() events are not included, you can use XI_Motion
* instead.
*/
unsigned char mask_bytes[(XI_LASTEVENT + 7) / 8] = {0}; /* must be zeroed! */
XISetMask(mask_bytes, XI_RawMotion);
/* Set mask to receive events from all master devices */
XIEventMask evmasks[1];
/* You can use XIAllDevices for XWarpPointer() */
evmasks[0].deviceid = XIAllMasterDevices;
evmasks[0].mask_len = sizeof(mask_bytes);
evmasks[0].mask = mask_bytes;
XISelectEvents(display, root_window, evmasks, 1);
XEvent xevent;
while (1) {
XNextEvent(display, &xevent);
if (xevent.xcookie.type != GenericEvent || xevent.xcookie.extension != xi_opcode) {
/* not an XInput event */
continue;
}
XGetEventData(display, &xevent.xcookie);
if (xevent.xcookie.evtype != XI_RawMotion) {
/*
* Not an XI_RawMotion event (you may want to detect
* XI_Motion as well, see comments above).
*/
XFreeEventData(display, &xevent.xcookie);
continue;
}
XFreeEventData(display, &xevent.xcookie);
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
/*
* We need:
* child_return - the active window under the cursor
* win_{x,y}_return - pointer coordinate with respect to root window
*/
int retval = XQueryPointer(display, root_window, &root_return, &child_return,
&root_x_return, &root_y_return,
&win_x_return, &win_y_return,
&mask_return);
if (!retval) {
/* pointer is not in the same screen, ignore */
continue;
}
/* We used root window as its reference, so both should be the same */
assert(root_x_return == win_x_return);
assert(root_y_return == win_y_return);
printf("root: x %d y %d\n", root_x_return, root_y_return);
if (child_return) {
int local_x, local_y;
XTranslateCoordinates(display, root_window, child_return,
root_x_return, root_y_return,
&local_x, &local_y, &child_return);
printf("local: x %d y %d\n\n", local_x, local_y);
}
}
XCloseDisplay(display);
return 0;
}
答案2
您可以使用 Xlib.h,但最重要的是在编译文件中必须输入链接器命令(-lX11
)示例:https(gcc a.c -o find -lX11
)您可以使用其他编译器,如 gcc、clang、cc 等。
我从以下来源获得信息:
https://tronche.com/gui/x/xlib/display/display-macros.html
https://www.x.org/releases/X11R7.5/doc/man/man3/XOpenDisplay.3.html#toc3
https://www.unix.com/man-page/ultrix/3x11/defaultrootwindow/
https://tronche.com/gui/x/xlib/window-information/XQueryPointer.html
代码:
#include <X11/Xlib.h>
#include <stdio.h>
int main(void){
printf("\n GOOD\n******\n");
Display *win = XOpenDisplay(NULL);
Window screen = DefaultRootWindow(win); // to To access the home screen
int x, y, winX, winY;
unsigned int mask;
Window child;
XQueryPointer(win, screen, &screen, &child, &x, &y, &winX, &winY, &mask);
printf("\nx => %d, y => %d\n", x, y);
XCloseDisplay(win);
return 0;
}