2012-01-14 6 views
5

Ho a lightweight application che rileva gli eventi Xorg e dbus. Per fare questo ho inizializzato ciclo dbus e ha iniziato g_main_loop, ma non so come aggiungere Xorg gestire in modo naturale evento:come aggiungere eventi Xorg che passano a 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); 

in iter di default che sto controllando se v'è in attesa X- evento e gestirli.

In entrambi i casi sembra errato, innanzitutto perché ho chiamate non necessarie per verificare l'evento, in secondo luogo perché eseguo un thread aggiuntivo e devo effettuare ulteriori blocchi.

P.S. So che posso usare gtk lib, ma non voglio avere dipendenze da alcun toolkit.

risposta

4

Se si desidera aggiungere la gestione degli eventi Xorg al ciclo principale senza utilizzare un timeout (che come si afferma è dispendioso), è necessario aggiungere una fonte che esegue il polling della connessione X. Per questo, è necessario scendere al di sotto del livello di astrazione Xlib per ottenere il descrittore del file di connessione X sottostante. Questo è ciò che fa il programma completo qui sotto. Si tratta di un adattamento di C. Tronche's excellent X11 tutorial per utilizzare il ciclo principale di glib per il polling. Ho anche disegnato "Fondamenti di GTK + Sviluppo" di Andrew Krause.

Se questo non sembra molto "naturale", è perché dubito che ci sia un modo molto "naturale" per farlo - stai davvero ri-implementando una parte fondamentale di GDK qui.

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

} 
Problemi correlati