2012-01-14 58 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; 

} 
相關問題