From fd688af424be0b953f7b7d1107d07ee668655868 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 22 Oct 2019 14:20:53 +0200 Subject: Improve Xlib error handling --- src/xprivate.cpp | 67 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/src/xprivate.cpp b/src/xprivate.cpp index 1273e1e..bef9471 100644 --- a/src/xprivate.cpp +++ b/src/xprivate.cpp @@ -3,6 +3,10 @@ #include #include +// Put this here as we need it in the static error handler +static Display* __display; +static XErrorHandler old_handler; + static double toVertRefresh(const XRRModeInfo *mode) { if (mode->hTotal > 0 && mode->vTotal > 0) @@ -61,9 +65,15 @@ static int modeEqual(const XRRModeInfo *a, const XRRModeInfo *b) static int errorHandler(Display *dpy, XErrorEvent *err) { - char buf[1000]; - XGetErrorText(dpy, err->error_code, buf, 1000); - qDebug() << "**X11 error**" << buf; + if (dpy != __display) { + if (old_handler != nullptr) { + return old_handler(dpy, err); + } + } else { + char buf[1000]; + XGetErrorText(dpy, err->error_code, buf, 1000); + qDebug() << "**X11 error**" << buf; + } return 0; } @@ -75,12 +85,12 @@ XPrivate::XPrivate() : _screenResources(nullptr) { // Get initial data (to be freed) - _display = XOpenDisplay(nullptr); + __display = _display = XOpenDisplay(nullptr); if (_display == nullptr) { qFatal("Cannot open display"); ::exit(1); } - XSetErrorHandler(errorHandler); + old_handler = XSetErrorHandler(errorHandler); _EDID_ATOM = XInternAtom(_display, RR_PROPERTY_RANDR_EDID, False); } @@ -120,7 +130,7 @@ void XPrivate::updateScreenResources() freeResources(); _screenResources = XRRGetScreenResourcesCurrent(_display, DefaultRootWindow(_display)); // Create the modemap - qDebug() << "Modes"; + qDebug() << "updateScreenResources: Modes"; for (int i = 0; i < _screenResources->nmode; ++i) { _modeMap.insert( _screenResources->modes[i].id, @@ -145,7 +155,7 @@ void XPrivate::updateScreenResources() */ // Create crtcMap - qDebug() << "CRTCs"; + qDebug() << "updateScreenResources: CRTCs"; for (int i = 0; i < _screenResources->ncrtc; ++i) { XRRCrtcInfo * info = XRRGetCrtcInfo( _display, @@ -160,7 +170,7 @@ void XPrivate::updateScreenResources() } // Create outputmap and connectedOutputMap - qDebug() << "Outputs"; + qDebug() << "updateScreenResources: Outputs"; QHash tempMap; QMap typeCount; for (int i = 0; i < _screenResources->noutput; ++i) { @@ -234,7 +244,7 @@ void XPrivate::updateScreenResources() return; qSort(screens.begin(), screens.end(), xRectLessThan); int endX = -0xffff; - qDebug() << "From left to right"; + qDebug() << "updateScreenResources: From left to right"; for (OutputInfo* output : screens) { if (output->mode == nullptr) { qDebug() << "(Ignoring" << output->outputName << "since it's disconnected)"; @@ -252,33 +262,37 @@ void XPrivate::updateScreenResources() endX = output->crtc->x + int(output->mode->width); } } - qDebug() << "Loaded."; + qDebug() << "updateScreenResources: Loaded."; } void XPrivate::addMissingEdidResolutions() { - XRRScreenResources *resptr = XRRGetScreenResourcesCurrent(_display, DefaultRootWindow(_display)); - for (int i = 0; i < resptr->noutput; ++i) { - unsigned char prop[512]; - unsigned long edidLen = 512; - if (!getEdid(resptr->outputs[i], prop, &edidLen)) - continue; - if (edidLen < 128) - continue; - for (unsigned int j = 54; j < 125; j+= 18) { - addMissingModesFromDtd(resptr, resptr->outputs[i], prop + j); - } - for (unsigned int j = 128; j < edidLen - 127; j += 128) { - addMissingModesFromExtBlock(resptr, resptr->outputs[i], prop + j); - } - } - XRRFreeScreenResources(resptr); + qDebug() << "addMissingEdidResolutions"; + XRRScreenResources *resptr = XRRGetScreenResourcesCurrent(_display, DefaultRootWindow(_display)); + if (resptr == nullptr) + return; + for (int i = 0; i < resptr->noutput; ++i) { + unsigned char prop[512]; + unsigned long edidLen = 512; + if (!getEdid(resptr->outputs[i], prop, &edidLen)) + continue; + if (edidLen < 128) + continue; + for (unsigned int j = 54; j < 125; j+= 18) { + addMissingModesFromDtd(resptr, resptr->outputs[i], prop + j); + } + for (unsigned int j = 128; j < edidLen - 127; j += 128) { + addMissingModesFromExtBlock(resptr, resptr->outputs[i], prop + j); + } + } + XRRFreeScreenResources(resptr); } bool XPrivate::getEdid(RROutput outputId, unsigned char *buffer, unsigned long *size) { int numProps = 0; bool found = false; + qDebug() << "getEdid:" << outputId; Atom* properties = XRRListOutputProperties(_display, outputId, &numProps); for (int i = 0; i < numProps; ++i) { if (properties[i] == _EDID_ATOM) { @@ -351,6 +365,7 @@ void XPrivate::addMissingModesFromExtBlock(XRRScreenResources *res, RROutput out dtdOffset = 128; } + qDebug() << "addMissingModesFromExtBlock:" << outputId; for (int i = dtdOffset; i < 128 - 17; i += 18) { addMissingModesFromDtd(res, outputId, data + i); } -- cgit v1.2.3-55-g7522