File indexing completed on 2024-05-05 16:19:52

0001 /*
0002     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #ifndef KXERRORHANDLER_H
0008 #define KXERRORHANDLER_H
0009 #include <config-kwindowsystem.h>
0010 
0011 #include <QtGlobal>
0012 
0013 #if KWINDOWSYSTEM_HAVE_X11
0014 
0015 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0016 #include <private/qtx11extras_p.h>
0017 #else
0018 #include <QX11Info>
0019 #endif
0020 
0021 #include <X11/Xlib.h>
0022 
0023 class KXErrorHandlerPrivate;
0024 /**
0025  * This class simplifies handling of X errors. It shouldn't be necessary to use
0026  * with Qt classes, as the toolkit should handle X errors itself, so this
0027  * class will be mainly used with direct Xlib usage, and some lowlevel classes
0028  * like NETWinInfo.
0029  *
0030  * The usual usage is to create a KXErrorHandler instance right before starting
0031  * operations that might cause X errors, and checking if there was an error
0032  * by calling error() after the operations are finished. The handlers
0033  * may be nested, but must be destroyed in reverse order they were created.
0034  *
0035  * There's no need to do X sync before creating an instance, every instance
0036  * will handle only errors for request issued after the instance was created.
0037  * Errors for older requests will be passed to previous error handler.
0038  * When checking for error by calling error() at the end, it is necessary
0039  * to sync with X, to catch all errors that were caused by requests issued
0040  * before the call to error(). This can be done by passing true to error()
0041  * to cause explicit XSync(), however, if the last X request needed a roundtrip
0042  * (e.g. XGetWindowAttributes(), XGetGeometry(), etc.), it is not required
0043  * to do an explicit sync.
0044  *
0045  * @author Lubos Lunak <l.lunak@kde.org>
0046  * @short Handler for X errors
0047  */
0048 class KXErrorHandler
0049 {
0050 public:
0051     /**
0052      * Creates error handler that will set error flag after encountering
0053      * any X error.
0054      */
0055     explicit KXErrorHandler(Display *dpy = QX11Info::display());
0056     /**
0057      * This constructor takes pointer to a function whose prototype matches
0058      * the one that's used with the XSetErrorHandler() Xlib function.
0059      * NOTE: For the error flag to be set, the function must return a non-zero
0060      * value.
0061      */
0062     explicit KXErrorHandler(int (*handler)(Display *, XErrorEvent *), Display *dpy = QX11Info::display());
0063     /**
0064      * This function returns true if the error flag is set (i.e. no custom handler
0065      * function was used and there was any error, or the custom handler indicated
0066      * an error by its return value).
0067      *
0068      * @param sync if true, an explicit XSync() will be done. Not necessary
0069      *             when the last X request required a roundtrip.
0070      */
0071     bool error(bool sync) const;
0072     /**
0073      * This function returns the error event for the first X error that occurred.
0074      * The return value is useful only if error() returned true.
0075      * @since 4.0.1
0076      */
0077     XErrorEvent errorEvent() const;
0078     /**
0079      * Returns error message for the given error. The error message is not translated,
0080      * as it is meant for debugging.
0081      * @since 4.0.1
0082      */
0083     static QByteArray errorMessage(const XErrorEvent &e, Display *dpy = QX11Info::display());
0084     ~KXErrorHandler();
0085 
0086 private:
0087     void addHandler();
0088     int handle(Display *dpy, XErrorEvent *e);
0089     bool (*user_handler1)(int request, int error_code, unsigned long resource_id);
0090     int (*user_handler2)(Display *, XErrorEvent *);
0091     int (*old_handler)(Display *, XErrorEvent *);
0092     static int handler_wrapper(Display *, XErrorEvent *);
0093     static KXErrorHandler **handlers;
0094     static int pos;
0095     static int size;
0096     Q_DISABLE_COPY(KXErrorHandler)
0097     KXErrorHandlerPrivate *const d;
0098 };
0099 
0100 #endif // KWINDOWSYSTEM_HAVE_X11
0101 
0102 #endif