KDEAmbi/hgx11grab.cpp
Tobias J. Endres 06e4555269 feat: Add debug logging to hgx11grab.cpp
Added qDebug() statements to trace the execution flow and print out important values in the screen grabbing process.
This will help to identify the root cause of the screen grabbing issue.
2025-08-14 00:59:25 +02:00

209 lines
6.2 KiB
C++

#include "hgx11grab.h"
#include <QDebug>
// public
hgx11grab::hgx11grab(Display *display, unsigned short scaleDivisor, const char *filter)
{
qDebug() << "hgx11grab constructor";
_filter_p = filter;
_display_p = display;
if (!XShmQueryExtension(_display_p)) {
qCritical() << "Xshm is: not available.";
return;
}
qDebug() << "XShm extension is available.";
int dummy, pixmaps_supported;
if (!XRenderQueryExtension(_display_p, &dummy, &dummy)) {
qCritical() << "XRender is not available.";
return;
}
qDebug() << "XRender extension is available.";
if (!XShmQueryVersion(_display_p, &dummy, &dummy, &pixmaps_supported)) {
qCritical("Could not get x shared memory version.");
return;
}
qDebug() << "XShm version query successful.";
bool _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_display_p) == ZPixmap;
if (!_XShmPixmapAvailable) {
qCritical() << "XshmPixMap is: not available.";
return;
}
qDebug() << "XShm pixmap is available.";
_window_m = DefaultRootWindow(_display_p);
qDebug() << "Root window:" << _window_m;
if (!_getWinAttr()) {
return;
}
_destWidth_m = int(_srcWidth_m / scaleDivisor);
_destHeight_m = int(_srcHeight_m / scaleDivisor);
qDebug() << "Destination size:" << _destWidth_m << "x" << _destHeight_m;
_imgSize_m = _destHeight_m * _destWidth_m * 4;
memset(&_pictAttr_m, 0, sizeof(_pictAttr_m));
_pictAttr_m.repeat = RepeatNone;
_mTransform_m.matrix[0][0] = XDoubleToFixed(1.0);
_mTransform_m.matrix[0][1] = 0;
_mTransform_m.matrix[0][2] = 0;
_mTransform_m.matrix[1][0] = 0;
_mTransform_m.matrix[1][1] = XDoubleToFixed(1.0);
_mTransform_m.matrix[1][2] = 0;
_mTransform_m.matrix[2][0] = 0;
_mTransform_m.matrix[2][1] = 0;
_setScale();
connect(this, SIGNAL(scaleChanged()), this, SLOT(_changeScale()));
qDebug() << "hgx11grab constructor finished.";
}
hgx11grab::~hgx11grab()
{
_freeResources();
}
int hgx11grab::getDest_height() const
{
return _destHeight_m;
}
int hgx11grab::getDest_width() const
{
return _destWidth_m;
}
// private
bool hgx11grab::_getWinAttr()
{
qDebug() << "Getting window attributes.";
if (XGetWindowAttributes(_display_p, _window_m, &_windowAttr_m) == 0) {
qWarning() << "Failed to obtain X11 window attributes.";
return false;
}
qDebug() << "Window size:" << _windowAttr_m.width << "x" << _windowAttr_m.height;
if (_srcWidth_m != _windowAttr_m.width || _srcHeight_m != _windowAttr_m.height) {
qDebug() << "Screen size changed.";
if (0 != _srcWidth_m) {
_freeResources();
}
_srcWidth_m = _windowAttr_m.width;
_srcHeight_m = _windowAttr_m.height;
emit scaleChanged();
}
return true;
}
void hgx11grab::_freeResources()
{
if (_freed_m) {
return;
}
qDebug() << "Freeing resources.";
XDestroyImage(_xImage_p);
XShmDetach(_display_p, &_shminfo_m);
shmdt(_shminfo_m.shmaddr);
shmctl(_shminfo_m.shmid, IPC_RMID, nullptr);
XRenderFreePicture(_display_p, _srcPicture_m);
XRenderFreePicture(_display_p, _dstPicture_m);
XFreePixmap(_display_p, _pixmap_m);
_freed_m = 1;
}
void hgx11grab::_setScale()
{
_scale_m = (1.0 / (double(_srcWidth_m) / double(_destWidth_m)));
_mTransform_m.matrix[2][2] = XDoubleToFixed(_scale_m);
}
// public slots
void hgx11grab::grabFrame()
{
qDebug() << "Grabbing frame.";
if (!_getWinAttr()) {
return;
}
_freed_m = 0;
_xImage_p = XShmCreateImage(
_display_p, _windowAttr_m.visual,
uint(_windowAttr_m.depth), ZPixmap, nullptr, &_shminfo_m,
uint(_destWidth_m), uint(_destHeight_m)
);
qDebug() << "XShmCreateImage successful.";
_shminfo_m.shmid = shmget(IPC_PRIVATE, ulong(_xImage_p->bytes_per_line * _xImage_p->height), IPC_CREAT|0777);
_xImage_p->data = reinterpret_cast<char *>(shmat(_shminfo_m.shmid, nullptr, 0));
_shminfo_m.shmaddr = _xImage_p->data;
_shminfo_m.readOnly = false;
qDebug() << "Shared memory segment created.";
XShmAttach(_display_p, &_shminfo_m);
_pixmap_m = XShmCreatePixmap(_display_p, _window_m, _xImage_p->data, &_shminfo_m, uint(_destWidth_m), uint(_destHeight_m), uint(_windowAttr_m.depth));
qDebug() << "XShm pixmap created.";
_dstFormat_p = XRenderFindVisualFormat(_display_p, _windowAttr_m.visual);
_srcFormat_p = XRenderFindVisualFormat(_display_p, _windowAttr_m.visual);
_srcPicture_m = XRenderCreatePicture(_display_p, _window_m, _srcFormat_p, CPRepeat, &_pictAttr_m);
_dstPicture_m = XRenderCreatePicture(_display_p, _pixmap_m, _dstFormat_p, CPRepeat, &_pictAttr_m);
qDebug() << "XRender pictures created.";
XRenderSetPictureFilter(_display_p, _srcPicture_m, _filter_p, nullptr, 0);
XRenderSetPictureTransform(_display_p, _srcPicture_m, &_mTransform_m);
XRenderComposite(
_display_p, // *dpy,
PictOpSrc, // op,
_srcPicture_m, // src
None, // mask
_dstPicture_m, // dst
0, // src_x
0, // src_y
0, // mask_x
0, // mask_y
0, // dst_x
0, // dst_y
uint(_destWidth_m), // width
uint(_destHeight_m) // height
);
qDebug() << "XRenderComposite successful.";
XSync(_display_p, false);
XShmGetImage(_display_p, _pixmap_m, _xImage_p, 0, 0, 0xFFFFFFFF);
qDebug() << "XShmGetImage successful.";
if (_xImage_p == nullptr) {
qWarning() << "Failed to get image from X11 server.";
return;
}
QImage qimg(reinterpret_cast<const uchar *>(_xImage_p->data), _destWidth_m, _destHeight_m, _xImage_p->bytes_per_line, QImage::Format_ARGB32);
qimg = qimg.convertToFormat(QImage::Format_RGB888);
imgdata_m = QByteArray::fromRawData(reinterpret_cast<const char *>(qimg.bits()), qimg.sizeInBytes()).toBase64().data();
qDebug() << "Image converted and encoded.";
_freeResources();
imageCreated();
}
// private slots
void hgx11grab::_changeScale()
{
_imgSize_m = _destHeight_m * _destWidth_m * 4;
_setScale();
}