2012-01-14 24 views
5

Tôi có a lightweight application để bắt các sự kiện Xorg và dbus. Để làm được điều này, tôi khởi tạo vòng lặp dbus và bắt đầu g_main_loop, nhưng tôi không biết làm thế nào để thêm Xorg xử lý theo một cách tự nhiên sự kiện:cách thêm sự kiện bàn giao Xorg vào 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); 

trong iter mặc định Tôi đang kiểm tra nếu có chờ đợi X- sự kiện và xử lý chúng.

Cả hai cách đều có vẻ xấu, đầu tiên vì tôi có các cuộc gọi không cần thiết để kiểm tra sự kiện, thứ hai vì tôi tạo một chuỗi bổ sung và phải tạo thêm khóa.

P.S. Tôi biết tôi có thể sử dụng gtk lib, nhưng tôi không muốn có phụ thuộc vào bất kỳ bộ công cụ nào.

Trả lời

4

Nếu bạn muốn thêm thao tác xử lý sự kiện Xorg vào vòng lặp chính mà không sử dụng hết thời gian chờ (khi bạn trạng thái lãng phí), bạn sẽ cần thêm nguồn thăm dò kết nối X. Để làm điều đó, bạn sẽ cần phải xuống dưới lớp trừu tượng Xlib để lấy bộ mô tả tệp kết nối X bên dưới. Đó là những gì chương trình hoàn chỉnh dưới đây. Nó là một sự thích nghi của C. Tronche's excellent X11 tutorial để sử dụng vòng lặp chính glib để bỏ phiếu. Tôi cũng đã vẽ từ "Foundations of GTK + Development" của Andrew Krause.

Nếu điều này dường như không "tự nhiên", đó là vì tôi nghi ngờ có một cách "rất tự nhiên" để làm điều này - bạn thực sự đang triển khai lại phần cốt lõi của GDK tại đây.

/* 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; 

} 
Các vấn đề liên quan