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