如果您想在不使用超時的情況下將Xorg事件處理添加到主循環中(因爲這種狀態非常浪費),您需要添加一個輪詢X連接的源。爲此,您需要在Xlib抽象層下面獲取底層的X連接文件描述符。以下是完整的程序。這是修改C. Tronche's excellent X11 tutorial使用glib主循環輪詢。我也從Andrew Krause的「GTK +開發基礎」中吸取了教訓。
如果這看起來不是很「自然」,那是因爲我懷疑是否有一種非常「自然」的方式來做到這一點 - 您真的在這裏重新實現了GDK的核心部分。
/* needed to break into 'Display' struct internals. */
#define XLIB_ILLEGAL_ACCESS
#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <glib.h>
typedef struct _x11_source {
GSource source;
Display *dpy;
Window w;
} x11_source_t;
static gboolean
x11_fd_prepare(GSource *source,
gint *timeout)
{
*timeout = -1;
return FALSE;
}
static gboolean
x11_fd_check (GSource *source)
{
return TRUE;
}
static gboolean
x11_fd_dispatch(GSource* source, GSourceFunc callback, gpointer user_data)
{
static gint counter = 0;
Display *dpy = ((x11_source_t*)source)->dpy;
Window window = ((x11_source_t*)source)->w;
XEvent e;
while (XCheckWindowEvent(dpy,
window,
EnterWindowMask,
&e))
{
if (e.type == EnterNotify)
g_print("We're in!!! (%d)\n", ++counter);
}
return TRUE;
}
static gboolean
msg_beacon(gpointer data)
{
static gint counter = 0;
g_print("Beacon %d\n", ++counter);
return TRUE;
}
int
main()
{
Display *dpy = XOpenDisplay(NULL);
assert(dpy);
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, blackColor, blackColor);
XSelectInput(dpy, w, StructureNotifyMask | EnterWindowMask);
XMapWindow(dpy, w);
for (;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify)
break;
}
GMainLoop *mainloop = NULL;
mainloop = g_main_loop_new(NULL, FALSE);
/* beacon to demonstrate we're not blocked. */
g_timeout_add(300, msg_beacon, mainloop);
GPollFD dpy_pollfd = {dpy->fd,
G_IO_IN | G_IO_HUP | G_IO_ERR,
0};
GSourceFuncs x11_source_funcs = {
x11_fd_prepare,
x11_fd_check,
x11_fd_dispatch,
NULL, /* finalize */
NULL, /* closure_callback */
NULL /* closure_marshal */
};
GSource *x11_source =
g_source_new(&x11_source_funcs, sizeof(x11_source_t));
((x11_source_t*)x11_source)->dpy = dpy;
((x11_source_t*)x11_source)->w = w;
g_source_add_poll(x11_source, &dpy_pollfd);
g_source_attach(x11_source, NULL);
g_main_loop_run(mainloop);
return 0;
}