File indexing completed on 2024-04-21 03:59:22

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