| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org> |
| 3 | |
| 4 | SPDX-License-Identifier: MIT |
| 5 | */ |
| 6 | |
| 7 | #ifndef KXERRORHANDLER_H |
| 8 | #define KXERRORHANDLER_H |
| 9 | #include <config-kwindowsystem.h> |
| 10 | |
| 11 | #include <mutex> |
| 12 | |
| 13 | #include <QtGlobal> |
| 14 | |
| 15 | #include <private/qtx11extras_p.h> |
| 16 | |
| 17 | #include <X11/Xlib.h> |
| 18 | |
| 19 | class KXErrorHandlerPrivate; |
| 20 | /*! |
| 21 | * This class simplifies handling of X errors. It shouldn't be necessary to use |
| 22 | * with Qt classes, as the toolkit should handle X errors itself, so this |
| 23 | * class will be mainly used with direct Xlib usage, and some lowlevel classes |
| 24 | * like NETWinInfo. |
| 25 | * |
| 26 | * The usual usage is to create a KXErrorHandler instance right before starting |
| 27 | * operations that might cause X errors, and checking if there was an error |
| 28 | * by calling error() after the operations are finished. The handlers |
| 29 | * may be nested, but must be destroyed in reverse order they were created. |
| 30 | * |
| 31 | * There's no need to do X sync before creating an instance, every instance |
| 32 | * will handle only errors for request issued after the instance was created. |
| 33 | * Errors for older requests will be passed to previous error handler. |
| 34 | * When checking for error by calling error() at the end, it is necessary |
| 35 | * to sync with X, to catch all errors that were caused by requests issued |
| 36 | * before the call to error(). This can be done by passing true to error() |
| 37 | * to cause explicit XSync(), however, if the last X request needed a roundtrip |
| 38 | * (e.g. XGetWindowAttributes(), XGetGeometry(), etc.), it is not required |
| 39 | * to do an explicit sync. |
| 40 | * |
| 41 | * \internal |
| 42 | */ |
| 43 | class KXErrorHandler |
| 44 | { |
| 45 | public: |
| 46 | /*! |
| 47 | * Creates error handler that will set error flag after encountering |
| 48 | * any X error. |
| 49 | */ |
| 50 | explicit KXErrorHandler(Display *dpy = QX11Info::display()); |
| 51 | /*! |
| 52 | * This constructor takes pointer to a function whose prototype matches |
| 53 | * the one that's used with the XSetErrorHandler() Xlib function. |
| 54 | * NOTE: For the error flag to be set, the function must return a non-zero |
| 55 | * value. |
| 56 | */ |
| 57 | explicit KXErrorHandler(int (*handler)(Display *, XErrorEvent *), Display *dpy = QX11Info::display()); |
| 58 | /*! |
| 59 | * This function returns true if the error flag is set (i.e. no custom handler |
| 60 | * function was used and there was any error, or the custom handler indicated |
| 61 | * an error by its return value). |
| 62 | * |
| 63 | * \a sync if true, an explicit XSync() will be done. Not necessary |
| 64 | * when the last X request required a roundtrip. |
| 65 | */ |
| 66 | bool error(bool sync) const; |
| 67 | /*! |
| 68 | * This function returns the error event for the first X error that occurred. |
| 69 | * The return value is useful only if error() returned true. |
| 70 | * \since 4.0.1 |
| 71 | */ |
| 72 | XErrorEvent errorEvent() const; |
| 73 | /*! |
| 74 | * Returns error message for the given error. The error message is not translated, |
| 75 | * as it is meant for debugging. |
| 76 | * \since 4.0.1 |
| 77 | */ |
| 78 | static QByteArray errorMessage(const XErrorEvent &e, Display *dpy = QX11Info::display()); |
| 79 | ~KXErrorHandler(); |
| 80 | |
| 81 | private: |
| 82 | void addHandler(); |
| 83 | int handle(Display *dpy, XErrorEvent *e); |
| 84 | bool (*user_handler1)(int request, int error_code, unsigned long resource_id); |
| 85 | int (*user_handler2)(Display *, XErrorEvent *); |
| 86 | int (*old_handler)(Display *, XErrorEvent *); |
| 87 | static int handler_wrapper(Display *, XErrorEvent *); |
| 88 | static std::mutex s_lock; |
| 89 | static KXErrorHandler **handlers; |
| 90 | static int pos; |
| 91 | static int size; |
| 92 | Q_DISABLE_COPY(KXErrorHandler) |
| 93 | KXErrorHandlerPrivate *const d; |
| 94 | }; |
| 95 | |
| 96 | #endif |
| 97 | |