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