2012-11-30 4 views
5

jest to podprojekt znacznie większy projekt badawczy. Próbuję robić zrzuty ekranu z aktywnego okna (przeglądarki) co 100ms, które następnie są przechowywane w pamięci do przetwarzania OpenCV. Z podobnego pytania znalazłem rozwiązanie do robienia zrzutu ekranu, a ja obecnie gram z kodem, aby sprawdzić, czy mogę go użyć. Wydaje się, że poniższy fragment działa podczas robienia całego zrzutu pulpitu lub określonego zrzutu okna, ale nie działa w przypadku okien GTK. Próbowałem zrobić zrzut ekranu Iceweasel & Nautilus na Debian Squeeze, i po prostu nie działa. Jestem totalnym noobem w X11 i nie wiem, jak sprawdzić błędy, lub jeśli czegoś brakuje mi w GTK, ponieważ wydaje się, że działa to w przypadku okien QT.Zrzut ekranu X11 aktywnego okna kończy się niepowodzeniem w przypadku okien GTK

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; 
} 

Powyższy kod działa albo dla pełnych zrzutów pulpitu lub QT. Nie otrzymuję błędu (nie wiem, czy poprawnie je obsługuję). Tylko puste zdjęcie kilku bajtów, co powoduje, że myślę, że jedna z funkcji X zawodzi (XGetInputFocus, XGetWindowAttributes, XGetImage), a mój zakład na XGetFocus nie działa poprawnie. Czego mi brakuje, czy istnieje alternatywa dla tego? Zwróć uwagę, że używam KDE (4.4.5), jeśli ma jakiekolwiek znaczenie.

UPDATE:

Próbowałem zrobić zrzut ekranu przy użyciu Qt4, a jednocześnie działa dobrze, to działa w ten sam problem, gdy próbuje dostać koncentruje okna z 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(); 
} 

jestem dlatego jest przekonany, że to XGetInputFocus() w jakiś sposób zawodzi.

Odpowiedz

7

Ponieważ nie otrzymałem jeszcze żadnych odpowiedzi, a sice spędziłem większą część całego dnia szukając rozwiązania, pomyślałem, że podzielę się tym, jak udało mi się to sprawić. System to Debian Squeeze, uruchamiający KDE 4.4.5. Najwyraźniej aplikacje KDE i GTK nie odtwarzają się nawzajem. Cytując ludzi z innych postów na stackoverflow i ogólnie w Internecie, aplikacja inna niż kde może nie honorować _NET_WM_STATE, lub może być coś innego, naprawdę nie wiem. Ale fakt, że aplikacje GTK, które wypróbowałem, nie działał z kawałkiem kodu, który działały wszystkie aplikacje Qt4, wskazuje na problem związany z jakąś formą raportowania. Niektóre rzadkie (i naprawdę mam na myśli rzadkie) rozwiązania znalezione w sieci wskazują, że być może drzewo X11 może zostać przemierzone, aby znaleźć aktywne okno, ale wydawało mi się to zbyt skomplikowane i czytałem posty osób, które nie osiągnęły dobrych wyników. Co wymyśliłem (czyli kawałki fragmentów znalezionych w Internecie) jest następujący użyciu xdo (libxdo na Debianie):

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; 

Powyższe prace z GTK & KDE aplikacje, mam nadzieję, może pomóc ktoś utknął w tym, ponieważ wydaje się, że jest bardzo mało postów na ten temat.

+0

Przetestowałem to, ale nie działa ono dla okna nautilus dla mnie, gdy zastosowałem do tego programu: http://stackoverflow.com/questions/22749444/listening-to-keyboard-events-without-consuming-them-in- Zahaczanie za pomocą klawiatury x11 – user2029077

Powiązane problemy