2012-11-30 11 views
5

questo è un sottoprogetto di un progetto di ricerca molto più ampio. Sto provando a fare screenshot di una finestra attiva (browser) ogni 100 ms, che devono poi essere archiviati in memoria per l'elaborazione OpenCV. Ho trovato da una domanda simile una soluzione per fare uno screenshot, e attualmente sto giocando con il codice per vedere se posso usarlo. Il seguente frammento sembra funzionare sia quando si acquisisce un'intera schermata del desktop, sia in uno specifico screenshot di Windows, ma non funziona con le finestre GTK. Ho provato a fare uno screenshot di Iceweasel & Nautilus su Debian Squeeze, e semplicemente non funziona. Sono un noob totale in X11, e non so come controllare gli errori, o se c'è qualcosa che mi manca per GTK, in quanto sembra funzionare per Windows QT.X11 screenshot della finestra attiva non riesce per GTK windows

typedef int (*handler)(Display *, XErrorEvent *); 

int handleX11Error(Display *d, XErrorEvent *er) 
{ 
    std::cout << "X11 Error: " << er->error_code << std::endl; 
} 

int main() 
{ 
    std::cout << "Sleeping 5 seconds" << std::endl; 
    // we may need to sleep if we want to focus another window. 
    sleep(5); 
    std::cout << "taking screenshot" << std::endl; 

    Display *display = XOpenDisplay(NULL); 
    //Window root = DefaultRootWindow(display); 
    XWindowAttributes gwa; 
    int revert = RevertToNone; 
    Window active; 
    XErrorEvent *error; 
    handler myHandler = &handleX11Error; 
    XSetErrorHandler(myHandler); 

    // X11 - Get Window that has focus 
    XGetInputFocus(display,&active,&revert); 

    //XGetWindowAttributes(display, root, &gwa); 
    if (!XGetWindowAttributes(display, active, &gwa)) 
    std::cout << "XGetWindowAttributes failed" << std::endl; 

    int width = gwa.width; 
    int height = gwa.height; 

    //XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap); 
    XImage *image = XGetImage(display,active, 0,0 , width,height,XAllPlanes(), ZPixmap); 

    unsigned char *array = new unsigned char[width * height * 3]; 
    CImg<unsigned char> pic(array,width,height,1,3); 

    for (int x = 0; x < width; x++){ 
     for (int y = 0; y < height ; y++){ 
    pic(x,y,0) = (XGetPixel(image,x,y) & image->red_mask) >> 16; 
    pic(x,y,1) = (XGetPixel(image,x,y) & image->green_mask) >> 8; 
    pic(x,y,2) = XGetPixel(image,x,y) & image->blue_mask; 
     } 
    } 
    delete[] array; 
    pic.save_png("blah.png"); 
    std::cout << "Finished" << std::endl; 
    return 0; 
} 

Il codice precedente funziona sia per gli screenshot del desktop completo o QT. Non ricevo errori (non so se li sto gestendo correttamente). Solo un'immagine vuota di pochi byte, che mi fa pensare che una delle funzioni X non funzioni (XGetInputFocus, XGetWindowAttributes, XGetImage), con la mia scommessa su XGetFocus che non funziona correttamente. Che cosa mi manca, oppure, c'è un'alternativa a questo? Si noti che sto eseguendo KDE (4.4.5) se è di qualche importanza.

UPDATE:

ho cercato di prendere uno screenshot utilizzando Qt4, e mentre funziona bene, funziona nello stesso problema quando si cerca di ottenere finestre focalizzate da X11:

int main(int argc, char **argv) 
{ 
    sleep(5); 
    Display *display = XOpenDisplay(NULL); 
    int revert = RevertToNone; 
    Window active; 
    XGetInputFocus(display,&active,&revert); 
    QApplication app(argc, argv);  
    QPixmap pixmap = QPixmap::grabWindow(active); 
    pixmap.save("test.png","PNG"); 
    QPushButton quit("Quit"); 
    quit.resize(75, 30); 
    quit.setFont(QFont("Times", 18, QFont::Bold)); 
    QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit())); 
    quit.show(); 
    return app.exec(); 
} 

Sono quindi convinto, che sia XGetInputFocus() che in qualche modo fallisce.

risposta

7

Dato che non ho ancora ricevuto alcuna risposta e ho passato la parte migliore di un'intera giornata alla ricerca di una soluzione, ho pensato di condividere come sono riuscito a farlo funzionare. Il sistema è Debian Squeeze, che esegue KDE 4.4.5. Apparentemente le app KDE e GTK non hanno un bell'aspetto. Citando persone da altri post su StackOverflow e Internet in generale, un'applicazione non-kde potrebbe non onorare lo _NET_WM_STATE, o potrebbe essere un'altra cosa, davvero non lo so. Ma il fatto che le app GTK che ho provato non funzionassero con la parte di codice che tutte le app Qt4 funzionavano, suggerisce un problema correlato a una qualche forma di segnalazione. Alcune rare (e davvero rari) soluzioni trovate sul punto della rete che forse l'albero delle finestre X11 potrebbe essere attraversato per trovare la finestra attiva, ma mi sembrava troppo complicato, e ho letto post di persone che non ottenevano risultati di successo. Quello che mi è venuta (che è bit e pezzi di frammenti trovati on-line) è la seguente utilizzando XDO (libxdo su Debian):

Display *display = XOpenDisplay(NULL); 
    Window active; 
    XWindowAttributes gwa; 

    // Use xdo to find the active window - care on the display ! 
    xdo_t* xdocontext = xdo_new(0); 
    xdo_window_get_active(xdocontext, &active); 
    if(active){ 
     XGetWindowAttributes(display, active, &gwa); 
     XImage *image = XGetImage(display,active, 0,0 , gwa.width,gwa.height,XAllPlanes(), ZPixmap); 
     unsigned char *array = new unsigned char[gwa.width * gwa.height * 3]; 
     CImg<unsigned char> pic(array,gwa.width,gwa.height,1,3); 

     for (int x = 0; x < gwa.width; x++){ 
     for (int y = 0; y < gwa.height ; y++){ 
      pic(x,y,0) = (XGetPixel(image,x,y) & image->red_mask) >> 16; 
      pic(x,y,1) = (XGetPixel(image,x,y) & image->green_mask) >> 8; 
      pic(x,y,2) = XGetPixel(image,x,y) & image->blue_mask; 
     } 
     } 
     delete[] array; 
     pic.save_png("blah.png"); 
    } else std::cout << "xdo failed to get active window" << std::endl; 

Le opere di cui sopra con GTK & applicazioni di KDE, spero davvero che possa aiutare qualcuno ci ha bloccato perché sembra che ci siano pochissimi post su questo.

+0

L'ho provato ma non funziona per la finestra nautilus per me quando applicato a questo programma: http://stackoverflow.com/questions/22749444/listening-to-keyboard-events-without-consuming-them-in- x11-tastiera-aggancio – user2029077