在Windows环境下,GUI线程通常使用GetMessage等待消息,在另一个线程使用PostMessage将消息放入队列后,GUI线程将返回GetMessage(退出阻塞)。
有人能告诉我,在XWindows下使用XNextEvent等待事件时,如何在另一个线程中“唤醒”GUI线程?是否有类似于PostMessage的API可以使用?
在Windows环境下,GUI线程通常使用GetMessage等待消息,在另一个线程使用PostMessage将消息放入队列后,GUI线程将返回GetMessage(退出阻塞)。
有人能告诉我,在XWindows下使用XNextEvent等待事件时,如何在另一个线程中“唤醒”GUI线程?是否有类似于PostMessage的API可以使用?
select()
来知道何时有输入可用。调用ConnectionNumber(display)
来获取您需要传递给select()
的文件描述符#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
Display *dis;
Window win;
int x11_fd;
fd_set in_fds;
struct timeval tv;
XEvent ev;
int main() {
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 256, 256, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
// You don't need all of these. Make the mask as you normally would.
XSelectInput(dis, win,
ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | StructureNotifyMask
);
XMapWindow(dis, win);
XFlush(dis);
// This returns the FD of the X11 display (or something like that)
x11_fd = ConnectionNumber(dis);
// Main loop
while(1) {
// Create a File Description Set containing x11_fd
FD_ZERO(&in_fds);
FD_SET(x11_fd, &in_fds);
// Set our timer. One second sounds good.
tv.tv_usec = 0;
tv.tv_sec = 1;
// Wait for X Event or a Timer
int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv);
if (num_ready_fds > 0)
printf("Event Received!\n");
else if (num_ready_fds == 0)
// Handle timer here
printf("Timer Fired!\n");
else
printf("An error occured!\n");
// Handle XEvents and flush the input
while(XPending(dis))
XNextEvent(dis, &ev);
}
return(0);
}
Window interClientCommunicationWindow;
Bool x11EventLoopActive = True;
// create a dummy window, that we can use to end the blocking XNextEvent call
interClientCommunicationWindow = XCreateSimpleWindow(dpy, root, 10, 10, 10, 10, 0, 0, 0);
XSelectInput(dpy, interClientCommunicationWindow, StructureNotifyMask);
XEvent event;
while(x11EventLoopActive) {
XNextEvent(dpy, &event);
...
}
x11EventLoopActive = False;
// push a dummy event into the queue so that the event loop has a chance to stop
XClientMessageEvent dummyEvent;
memset(&dummyEvent, 0, sizeof(XClientMessageEvent));
dummyEvent.type = ClientMessage;
dummyEvent.window = interClientCommunicationWindow;
dummyEvent.format = 32;
XSendEvent(dpy, interClientCommunicationWindow, 0, 0, (XEvent*)&dummyEvent);
XFlush(dpy);
pending
。 这段代码是用Crystal编写的,但在C中是相同的:loop do
while @display.pending > 0
event = @display.next_event
# do stuff with event
end
sleep 16.milliseconds
end
然而,这种方式需要更多的资源(显然取决于睡眠时间),这就是为什么接受的答案可能是一个更好的想法。
XMaskWindow
,你熟悉这个吗?但它从来没有给我任何东西,我在这里发布了相关信息:http://stackoverflow.com/questions/33717635/xmaskevent-not-returning-cannot-do-with-xnextevent - Noitidartselect()
的第一个参数应该是x11_fd + 1
,而不是1。来自man 2 select
: - Daniel Januspselect()
或poll()
而不是select()
,因为pselect()
具有更好的信号处理能力,并且可以避免在select()
中可能发生的信号竞争条件。 - 12431234123412341234123