• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • util
kxerrorhandler.cpp
Go to the documentation of this file.
1/*
2
3 Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22
23*/
24
25#include "kxerrorhandler.h"
26
27#ifdef Q_WS_X11 //FIXME
28
29#include "netwm_def.h"
30
31#include <stdio.h>
32
33class KXErrorHandlerPrivate
34{
35public:
36 KXErrorHandlerPrivate( Display* dpy ) :
37 first_request( XNextRequest( dpy )),
38 display( dpy ),
39 was_error( false )
40 {
41 }
42 unsigned long first_request;
43 Display* display;
44 bool was_error;
45 XErrorEvent error_event;
46};
47
48KXErrorHandler** KXErrorHandler::handlers = NULL;
49int KXErrorHandler::pos = 0;
50int KXErrorHandler::size = 0;
51
52KXErrorHandler::KXErrorHandler( Display* dpy )
53 : user_handler1( NULL ),
54 user_handler2( NULL ),
55 old_handler( XSetErrorHandler( handler_wrapper )),
56 d( new KXErrorHandlerPrivate(dpy) )
57 {
58 addHandler();
59 }
60
61#ifndef KDE_NO_DEPRECATED
62KXErrorHandler::KXErrorHandler( bool (*handler)( int request, int error_code, unsigned long resource_id ), Display* dpy )
63 : user_handler1( handler ),
64 user_handler2( NULL ),
65 old_handler( XSetErrorHandler( handler_wrapper )),
66 d( new KXErrorHandlerPrivate(dpy) )
67 {
68 addHandler();
69 }
70#endif
71
72KXErrorHandler::KXErrorHandler( int (*handler)( Display*, XErrorEvent* ), Display* dpy )
73 : user_handler1( NULL ),
74 user_handler2( handler ),
75 old_handler( XSetErrorHandler( handler_wrapper )),
76 d( new KXErrorHandlerPrivate(dpy) )
77 {
78 addHandler();
79 }
80
81KXErrorHandler::~KXErrorHandler()
82 {
83 XSetErrorHandler( old_handler );
84 Q_ASSERT_X( this == handlers[ pos-1 ], "KXErrorHandler", "out of order" );
85 --pos;
86 delete d;
87 }
88
89void KXErrorHandler::addHandler()
90 {
91 if( size == pos )
92 {
93 size += 16;
94 handlers = static_cast< KXErrorHandler** >( qRealloc( handlers, size * sizeof( KXErrorHandler* )));
95 }
96 handlers[ pos++ ] = this;
97 }
98
99bool KXErrorHandler::error( bool sync ) const
100 {
101 if( sync )
102 XSync( d->display, False );
103 return d->was_error;
104 }
105
106XErrorEvent KXErrorHandler::errorEvent() const
107 {
108 return d->error_event;
109 }
110
111int KXErrorHandler::handler_wrapper( Display* dpy, XErrorEvent* e )
112 {
113 --pos;
114 int ret = handlers[ pos ]->handle( dpy, e );
115 ++pos;
116 return ret;
117 }
118
119int KXErrorHandler::handle( Display* dpy, XErrorEvent* e )
120 {
121 if( dpy == d->display
122 // e->serial >= d->first_request , compare like X timestamps to handle wrapping
123 && NET::timestampCompare( e->serial, d->first_request ) >= 0 )
124 { // it's for us
125 //qDebug( "Handling: %p", static_cast< void* >( this ));
126 bool error = false;
127 if( user_handler1 != NULL )
128 {
129 if( user_handler1( e->request_code, e->error_code, e->resourceid ))
130 error = true;
131 }
132 else if( user_handler2 != NULL )
133 {
134 if( user_handler2( dpy, e ) != 0 )
135 error = true;
136 }
137 else // no handler set, simply set that there was an error
138 error = true;
139 if( error && !d->was_error )
140 { // only remember the first
141 d->was_error = true;
142 d->error_event = *e;
143 }
144 return 0;
145 }
146 //qDebug( "Going deeper: %p", static_cast< void* >( this ));
147 return old_handler( dpy, e );
148 }
149
150QByteArray KXErrorHandler::errorMessage( const XErrorEvent& event, Display* dpy )
151 { // "Error: <error> (<value>), Request: <request>(<value>), Resource: <value>"
152 QByteArray ret;
153 char tmp[ 256 ];
154 char num[ 256 ];
155#if 0 // see below
156 if( event.request_code < 128 ) // core request
157#endif
158 {
159 XGetErrorText( dpy, event.error_code, tmp, 255 );
160 if( char* paren = strchr( tmp, '(' )) // the explanation in parentheses just makes
161 *paren = '\0'; // it more verbose and is not really useful
162 // the various casts are to get overloads non-ambiguous :-/
163 ret = QByteArray( "error: " ) + (const char*)tmp + '[' + QByteArray::number( event.error_code ) + ']';
164 sprintf( num, "%d", event.request_code );
165 XGetErrorDatabaseText( dpy, "XRequest", num, "<unknown>", tmp, 256 );
166 ret += QByteArray( ", request: " ) + (const char*)tmp + '[' + QByteArray::number( event.request_code ) + ']';
167 if( event.resourceid != 0 )
168 ret += QByteArray( ", resource: 0x" ) + QByteArray::number( (qlonglong)event.resourceid, 16 );
169 }
170#if 0
171 else // extensions
172 {
173 // XGetErrorText() currently has a bug that makes it fail to find text
174 // for some errors (when error==error_base), also XGetErrorDatabaseText()
175 // requires the right extension name, so it is needed to get info about
176 // all extensions. However that is almost impossible:
177 // - Xlib itself has it, but in internal data.
178 // - Opening another X connection now can cause deadlock with server grabs.
179 // - Fetching it at startup means a bunch of roundtrips.
180 // So if this becomes more useful in the future, do the roundtrips at startup,
181 // or fetch it in kded and export as an env.var or something.
182 Display* dpy2 = XOpenDisplay( XDisplayString( dpy ));
183 int nextensions;
184 char** extensions = XListExtensions( dpy2, &nextensions );
185 int* majors = NULL;
186 int* error_bases = NULL;
187 if( extensions == NULL )
188 nextensions = 0;
189 else
190 {
191 majors = new int[ nextensions ];
192 error_bases = new int[ nextensions ];
193 for( int i = 0;
194 i < nextensions;
195 ++i )
196 {
197 int dummy;
198 if( !XQueryExtension( dpy2, extensions[ i ], &majors[ i ], &dummy, &error_bases[ i ] ))
199 {
200 majors[ i ] = 0;
201 error_bases[ i ] = 0;
202 }
203 }
204 }
205 XGetErrorText( dpy, event.error_code, tmp, 255 );
206 int index = -1;
207 int base = 0;
208 for( int i = 0;
209 i < nextensions;
210 ++i )
211 if( error_bases[ i ] != 0
212 && event.error_code >= error_bases[ i ] && ( index == -1 || error_bases[ i ] > base ))
213 {
214 index = i;
215 base = error_bases[ i ];
216 }
217 if( tmp == QString::number( event.error_code )) // XGetErrorText() failed,
218 { // or it has a bug that causes not finding all errors, check ourselves
219 if( index != -1 )
220 {
221 snprintf( num, 255, "%s.%d", extensions[ index ], event.error_code - base );
222 XGetErrorDatabaseText( dpy, "XProtoError", num, "<unknown>", tmp, 255 );
223 }
224 else
225 strcpy( tmp, "<unknown>" );
226 }
227 if( char* paren = strchr( tmp, '(' ))
228 *paren = '\0';
229 if( index != -1 )
230 ret = QByteArray( "error: " ) + (const char*)tmp + '[' + (const char*)extensions[ index ]
231 + '+' + QByteArray::number( event.error_code - base ) + ']';
232 else
233 ret = QByteArray( "error: " ) + (const char*)tmp + '[' + QByteArray::number( event.error_code ) + ']';
234 tmp[ 0 ] = '\0';
235 for( int i = 0;
236 i < nextensions;
237 ++i )
238 if( majors[ i ] == event.request_code )
239 {
240 snprintf( num, 255, "%s.%d", extensions[ i ], event.minor_code );
241 XGetErrorDatabaseText( dpy, "XRequest", num, "<unknown>", tmp, 255 );
242 ret += QByteArray( ", request: " ) + (const char*)tmp + '[' + (const char*)extensions[ i ] + '+'
243 + QByteArray::number( event.minor_code ) + ']';
244 }
245 if( tmp[ 0 ] == '\0' ) // not found???
246 ret += QByteArray( ", request <unknown> [" ) + QByteArray::number( event.request_code ) + ':'
247 + QByteArray::number( event.minor_code ) + ']';
248 if( event.resourceid != 0 )
249 ret += QByteArray( ", resource: 0x" ) + QByteArray::number( (qlonglong)event.resourceid, 16 );
250 if( extensions != NULL )
251 XFreeExtensionList( extensions );
252 delete[] majors;
253 delete[] error_bases;
254 XCloseDisplay( dpy2 );
255 }
256#endif
257 return ret;
258 }
259
260#endif
KXErrorHandler
This class simplifies handling of X errors.
Definition: kxerrorhandler.h:63
KXErrorHandler::KXErrorHandler
KXErrorHandler(Display *dpy=QX11Info::display())
Creates error handler that will set error flag after encountering any X error.
Definition: kxerrorhandler.cpp:52
KXErrorHandler::errorEvent
XErrorEvent errorEvent() const
This function returns the error event for the first X error that occurred.
Definition: kxerrorhandler.cpp:106
KXErrorHandler::errorMessage
static QByteArray errorMessage(const XErrorEvent &e, Display *dpy=QX11Info::display())
Returns error message for the given error.
Definition: kxerrorhandler.cpp:150
KXErrorHandler::error
bool error(bool sync) const
This function returns true if the error flag is set (i.e.
Definition: kxerrorhandler.cpp:99
KXErrorHandler::~KXErrorHandler
~KXErrorHandler()
Definition: kxerrorhandler.cpp:81
NET::timestampCompare
static int timestampCompare(unsigned long time1, unsigned long time2)
Compares two X timestamps, taking into account wrapping and 64bit architectures.
Definition: netwm.cpp:4735
kxerrorhandler.h
paren
paren
netwm_def.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal