2012-01-14 28 views
5

我有a lightweight application捕获Xorg和dbus事件。为了做到这一点,我初始化DBUS循环,并开始g_main_loop,但我不知道如何添加Xorg的事件以自然的方式处理:如何添加Xorg事件处理g_main_loop

GMainLoop * mainloop = NULL; 
mainloop = g_main_loop_new(NULL,FALSE); 
dbus_g_thread_init(); 
dbus_init(); 
// <<<<<<<<<<<<<<<<<<<<<<<<< 
//1 way using timeout 
//g_timeout_add(100, kbdd_default_iter, mainloop); 
//2nd way using pthread 
//GThread * t = g_thread_create(kbdd_default_loop, NULL, FALSE, NULL); 
//>>>>>>>>>>>>>>>>>>>>>>>>>>> 
g_main_loop_run(mainloop); 

在默认ITER我检查是否有等待X-事件并处理它们。

这两种方式似乎都不好,首先是因为我有不必要的检查事件调用,第二,因为我做了一个额外的线程,必须做出额外的锁。

P.S.我知道我可以使用gtk lib,但我不想在任何工具包上有依赖关系。

回答

4

如果您想在不使用超时的情况下将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; 

} 
相关问题