Je tente de résoudre ce que je pensais être un problème très simple. Je veux garder une QPixmap à jour avec tout le contenu de l'écran. Vous pouvez obtenir un tel pixmap en faisant ceci:Conserver QPixmap copier le contenu de l'écran en utilisant X11, XDamage, XRender, et d'autres trucs
QDesktopWidget *w = QApplication::desktop();
if (w)
{
QRect r = w->screenGeometry();
QPixmap p = QPixmap::grabWindow(w->winId(), 0, 0, r.width(), r.height())
QByteArray bitmap;
}
Le problème est que QDesktopWidget finit par re-saisir tout l'écran pixmap du serveur X11 chaque fois que vous demandez, même si rien n'a changé.
J'ai besoin de ce code pour être rapide, donc j'essaye de le faire moi-même. Mon point de départ était le qx11mirror demo, cependant, cela fait essentiellement la même chose. Il utilise l'extension XDamage pour fonctionner quand quelque chose a changé, mais au lieu d'utiliser les informations du rectangle endommagé pour mettre à jour cette partie de la pixmap en cache, il définit simplement un drapeau "dirty", qui déclenche tout un rafraîchissement. J'essaie donc de modifier l'exemple qx11mirror pour simplement mettre à jour la partie endommagée des fenêtres, mais je n'arrive pas à faire quoi que ce soit au travail - tout ce que je reçois est un pixmap vide (noir). Le code que j'utilise est:
void QX11Mirror::x11Event(XEvent *event)
{
if (event->type == m_damageEvent + XDamageNotify)
{
XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event);
XWindowAttributes attr;
XGetWindowAttributes(QX11Info::display(), m_window, &attr);
XRenderPictFormat *format = XRenderFindVisualFormat(QX11Info::display(), attr.visual);
bool hasAlpha = (format->type == PictTypeDirect && format->direct.alphaMask);
int x = attr.x;
int y = attr.y;
int width = attr.width;
int height = attr.height;
// debug output so I can see the window pos vs the damaged area:
qDebug() << "repainting dirty area:" << x << y << width << height << "vs" << e->area.x << e->area.y << e->area.width << e->area.height;
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors; // Don't clip child widgets
Picture picture = XRenderCreatePicture(QX11Info::display(),
m_window,
format,
CPSubwindowMode,
&pa);
XserverRegion region = XFixesCreateRegionFromWindow(QX11Info::display(),
m_window, WindowRegionBounding);
XFixesTranslateRegion(QX11Info::display(), region, -x, -y);
XFixesSetPictureClipRegion(QX11Info::display(), picture, 0, 0, region);
XFixesDestroyRegion(QX11Info::display(), region);
//QPixmap dest(width, height);
XRenderComposite(QX11Info::display(), // display
hasAlpha ? PictOpOver : PictOpSrc, // operation mode
picture, // src drawable
None, // src mask
dest.x11PictureHandle(), // dest drawable
e->area.x, // src X
e->area.y, // src Y
0, // mask X
0, // mask Y
e->area.x, // dest X
e->area.y, // dest Y
e->area.width, // width
e->area.height); // height
m_px = dest;
XDamageSubtract(QX11Info::display(), e->damage, None, None);
emit windowChanged();
}
else if (event->type == ConfigureNotify)
{
XConfigureEvent *e = &event->xconfigure;
m_position = QRect(e->x, e->y, e->width, e->height);
emit positionChanged(m_position);
}
}
Quelqu'un peut-il me diriger dans la bonne direction? La documentation pour XRender, XDamage et les autres extensions X11 est plutôt mauvaise.
Raisons d'utiliser XRender sur XCopyArea
Le texte suivant extrait de here.
Il est parfaitement possible de créer un GC pour une fenêtre et utiliser XCopyArea() pour copier le contenu de la fenêtre si vous voulez utiliser le protocole de base, mais puisque l'extension Composite expose de nouveaux visuels), il n'y a aucune garantie que le format de la source dessinable correspondra à celui de la destination. Avec le protocole de base, cette situation entraînera une erreur de correspondance, ce qui ne se produira pas avec l'extension Xrender.
En outre, le protocole de base ne comprend pas les canaux alpha, ce qui signifie qu'il ne peut pas composer des fenêtres qui utilisent le nouveau visuel ARGB. Lorsque la source et la destination ont le même format, il n'y a pas non plus d'avantage de performance à utiliser le protocole de base à partir de X11R6.8. Cette version est également la première à supporter la nouvelle extension Composite. Donc, en conclusion, il n'y a pas d'inconvénients, et seulement des avantages à choisir Xrender sur le protocole de base pour ces opérations.
Pourquoi? XRender est sujet à erreur (si vous ne le faites pas exactement dans le bon sens, cela ne fonctionnera pas ..) – ypnos
J'ai trouvé que d'essayer de mettre à jour l'écran que la mise à jour des pièces endommagées ne fonctionne pas très bien dans la pratique. Par exemple, les applications OpenGL ne semblent jamais signaler de dommages. Je pense que votre meilleur pari est de continuer à recapturer l'écran. – ldog
Vous pouvez recapturer l'écran en temps quasi réel (10-20 images par secondes) si vous le faites intelligemment. – ldog