抱歉标题很差,要更好地描述它并不容易。我正在学习 C,作为一个玩具项目,我正在为我的窗口管理器构建一个简单的状态栏。基本上它只是将文本输出到根 X11 窗口名称,由 wm (DWM) 获取。
现在我想添加检测到的简单点击,以便在点击特定区域时可以做一些事情。鼠标的轮询发生在一个while循环中;状态栏的更新也存在于 while 循环中,但间隔不同(频率较低)。一切正常,除了没有其他 X11 应用程序接收到我在 while 循环中听到的鼠标点击。
我XNextEvent
首先使用,但发现如果鼠标空闲,它会阻塞 while 循环。然后我了解XCheckWindowEvent
了如果我要轮询的事件匹配,哪个返回布尔值,然后我可以处理它。但是当鼠标空闲时(大部分时间),循环不会暂停。
但是,既然这样做了,每当我移动鼠标时,我就不能再点击任何其他窗口了。光标移动得很好,但点击似乎不起作用。
我说得有道理吗?
这是我的程序列表(对于状态设置部分稍微简化,因为这可能会分散注意力)。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include <unistd.h>
#include <fcntl.h>
#include <X11/Xlib.h>
#define EVTMASK (ButtonPressMask | PointerMotionMask)
void set_status(Display *display, Window window, char *str);
void process_mouse(Display *display, Window window, XEvent xevent);
char *key_name[] = {
"first",
"second (or middle)",
"third"
};
int
main(void)
{
const int MSIZE = 1024;
Display *display;
XEvent xevent;
Window window;
char *status;
char *bg_color = "#000000";
char *clr_yellow = "#ecbe7b";
time_t previousTime = time(NULL);
time_t interval_status = 1;
time_t currentTime;
if (!(display = XOpenDisplay(NULL))) {
fprintf(stderr, "Cannot open display.\n");
return EXIT_FAILURE;
}
// Setup X11 for mouse grabbing
window = DefaultRootWindow(display);
XAllowEvents(display, AsyncBoth, CurrentTime);
XGrabPointer(display,
window,
1,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask ,
GrabModeAsync,
GrabModeAsync,
None,
None,
CurrentTime);
status = (char*) malloc(sizeof(char)*MSIZE);
if(!status)
return EXIT_FAILURE;
while(1)
{
process_mouse(display, window, xevent);
if((time(¤tTime) - previousTime) >= interval_status)
{
int ret = snprintf(status, MSIZE, "^b%s^^c%s^%s Status me!", bg_color, clr_yellow);
set_status(display, window, status);
previousTime += interval_status;
}
}
return 0;
}
void
set_status(Display *display, Window window, char *str)
{
XStoreName(display, window, str);
XSync(display, False);
}
void
process_mouse(Display *display, Window window, XEvent xevent)
{
if(XCheckWindowEvent(display, window, EVTMASK, &xevent)) {
switch (xevent.type) {
case MotionNotify:
printf("Mouse move : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
break;
case ButtonPress:
printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]);
break;
case ButtonRelease:
printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
break;
}
XPutBackEvent(display, &xevent);
}
}
开放式问题:我应该回到NextEvent
方法并在不同的线程上听鼠标吗?