00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "kxerrorhandler.h"
00026
00027 #ifdef Q_WS_X11 //FIXME
00028
00029 #include "netwm_def.h"
00030
00031 #include <stdio.h>
00032
00033 class KXErrorHandlerPrivate
00034 {
00035 public:
00036 KXErrorHandlerPrivate( Display* dpy ) :
00037 first_request( XNextRequest( dpy )),
00038 display( dpy ),
00039 was_error( false )
00040 {
00041 }
00042 unsigned long first_request;
00043 Display* display;
00044 bool was_error;
00045 XErrorEvent error_event;
00046 };
00047
00048 KXErrorHandler** KXErrorHandler::handlers = NULL;
00049 int KXErrorHandler::pos = 0;
00050 int KXErrorHandler::size = 0;
00051
00052 KXErrorHandler::KXErrorHandler( Display* dpy )
00053 : user_handler1( NULL ),
00054 user_handler2( NULL ),
00055 old_handler( XSetErrorHandler( handler_wrapper )),
00056 d( new KXErrorHandlerPrivate(dpy) )
00057 {
00058 addHandler();
00059 }
00060
00061 KXErrorHandler::KXErrorHandler( bool (*handler)( int request, int error_code, unsigned long resource_id ), Display* dpy )
00062 : user_handler1( handler ),
00063 user_handler2( NULL ),
00064 old_handler( XSetErrorHandler( handler_wrapper )),
00065 d( new KXErrorHandlerPrivate(dpy) )
00066 {
00067 addHandler();
00068 }
00069
00070 KXErrorHandler::KXErrorHandler( int (*handler)( Display*, XErrorEvent* ), Display* dpy )
00071 : user_handler1( NULL ),
00072 user_handler2( handler ),
00073 old_handler( XSetErrorHandler( handler_wrapper )),
00074 d( new KXErrorHandlerPrivate(dpy) )
00075 {
00076 addHandler();
00077 }
00078
00079 KXErrorHandler::~KXErrorHandler()
00080 {
00081 XSetErrorHandler( old_handler );
00082 Q_ASSERT_X( this == handlers[ pos-1 ], "KXErrorHandler", "out of order" );
00083 --pos;
00084 delete d;
00085 }
00086
00087 void KXErrorHandler::addHandler()
00088 {
00089 if( size == pos )
00090 {
00091 size += 16;
00092 handlers = static_cast< KXErrorHandler** >( qRealloc( handlers, size * sizeof( KXErrorHandler* )));
00093 }
00094 handlers[ pos++ ] = this;
00095 }
00096
00097 bool KXErrorHandler::error( bool sync ) const
00098 {
00099 if( sync )
00100 XSync( d->display, False );
00101 return d->was_error;
00102 }
00103
00104 XErrorEvent KXErrorHandler::errorEvent() const
00105 {
00106 return d->error_event;
00107 }
00108
00109 int KXErrorHandler::handler_wrapper( Display* dpy, XErrorEvent* e )
00110 {
00111 --pos;
00112 int ret = handlers[ pos ]->handle( dpy, e );
00113 ++pos;
00114 return ret;
00115 }
00116
00117 int KXErrorHandler::handle( Display* dpy, XErrorEvent* e )
00118 {
00119 if( dpy == d->display
00120
00121 && NET::timestampCompare( e->serial, d->first_request ) >= 0 )
00122 {
00123
00124 bool error = false;
00125 if( user_handler1 != NULL )
00126 {
00127 if( user_handler1( e->request_code, e->error_code, e->resourceid ))
00128 error = true;
00129 }
00130 else if( user_handler2 != NULL )
00131 {
00132 if( user_handler2( dpy, e ) != 0 )
00133 error = true;
00134 }
00135 else
00136 error = true;
00137 if( error && !d->was_error )
00138 {
00139 d->was_error = true;
00140 d->error_event = *e;
00141 }
00142 return 0;
00143 }
00144
00145 return old_handler( dpy, e );
00146 }
00147
00148 QByteArray KXErrorHandler::errorMessage( const XErrorEvent& event, Display* dpy )
00149 {
00150 QByteArray ret;
00151 char tmp[ 256 ];
00152 char num[ 256 ];
00153 #if 0 // see below
00154 if( event.request_code < 128 )
00155 #endif
00156 {
00157 XGetErrorText( dpy, event.error_code, tmp, 255 );
00158 if( char* paren = strchr( tmp, '(' ))
00159 *paren = '\0';
00160
00161 ret = QByteArray( "error: " ) + (const char*)tmp + '[' + QByteArray::number( event.error_code ) + ']';
00162 sprintf( num, "%d", event.request_code );
00163 XGetErrorDatabaseText( dpy, "XRequest", num, "<unknown>", tmp, 256 );
00164 ret += QByteArray( ", request: " ) + (const char*)tmp + '[' + QByteArray::number( event.request_code ) + ']';
00165 if( event.resourceid != 0 )
00166 ret += QByteArray( ", resource: 0x" ) + QByteArray::number( (qlonglong)event.resourceid, 16 );
00167 }
00168 #if 0
00169 else
00170 {
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 Display* dpy2 = XOpenDisplay( XDisplayString( dpy ));
00181 int nextensions;
00182 char** extensions = XListExtensions( dpy2, &nextensions );
00183 int* majors = NULL;
00184 int* error_bases = NULL;
00185 if( extensions == NULL )
00186 nextensions = 0;
00187 else
00188 {
00189 majors = new int[ nextensions ];
00190 error_bases = new int[ nextensions ];
00191 for( int i = 0;
00192 i < nextensions;
00193 ++i )
00194 {
00195 int dummy;
00196 if( !XQueryExtension( dpy2, extensions[ i ], &majors[ i ], &dummy, &error_bases[ i ] ))
00197 {
00198 majors[ i ] = 0;
00199 error_bases[ i ] = 0;
00200 }
00201 }
00202 }
00203 XGetErrorText( dpy, event.error_code, tmp, 255 );
00204 int index = -1;
00205 int base = 0;
00206 for( int i = 0;
00207 i < nextensions;
00208 ++i )
00209 if( error_bases[ i ] != 0
00210 && event.error_code >= error_bases[ i ] && ( index == -1 || error_bases[ i ] > base ))
00211 {
00212 index = i;
00213 base = error_bases[ i ];
00214 }
00215 if( tmp == QString::number( event.error_code ))
00216 {
00217 if( index != -1 )
00218 {
00219 snprintf( num, 255, "%s.%d", extensions[ index ], event.error_code - base );
00220 XGetErrorDatabaseText( dpy, "XProtoError", num, "<unknown>", tmp, 255 );
00221 }
00222 else
00223 strcpy( tmp, "<unknown>" );
00224 }
00225 if( char* paren = strchr( tmp, '(' ))
00226 *paren = '\0';
00227 if( index != -1 )
00228 ret = QByteArray( "error: " ) + (const char*)tmp + '[' + (const char*)extensions[ index ]
00229 + '+' + QByteArray::number( event.error_code - base ) + ']';
00230 else
00231 ret = QByteArray( "error: " ) + (const char*)tmp + '[' + QByteArray::number( event.error_code ) + ']';
00232 tmp[ 0 ] = '\0';
00233 for( int i = 0;
00234 i < nextensions;
00235 ++i )
00236 if( majors[ i ] == event.request_code )
00237 {
00238 snprintf( num, 255, "%s.%d", extensions[ i ], event.minor_code );
00239 XGetErrorDatabaseText( dpy, "XRequest", num, "<unknown>", tmp, 255 );
00240 ret += QByteArray( ", request: " ) + (const char*)tmp + '[' + (const char*)extensions[ i ] + '+'
00241 + QByteArray::number( event.minor_code ) + ']';
00242 }
00243 if( tmp[ 0 ] == '\0' )
00244 ret += QByteArray( ", request <unknown> [" ) + QByteArray::number( event.request_code ) + ':'
00245 + QByteArray::number( event.minor_code ) + ']';
00246 if( event.resourceid != 0 )
00247 ret += QByteArray( ", resource: 0x" ) + QByteArray::number( (qlonglong)event.resourceid, 16 );
00248 if( extensions != NULL )
00249 XFreeExtensionList( extensions );
00250 delete[] majors;
00251 delete[] error_bases;
00252 XCloseDisplay( dpy2 );
00253 }
00254 #endif
00255 return ret;
00256 }
00257
00258 #endif