• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kxerrorhandler.cpp

Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
00004 
00005   Permission is hereby granted, free of charge, to any person obtaining a
00006   copy of this software and associated documentation files (the "Software"),
00007   to deal in the Software without restriction, including without limitation
00008   the rights to use, copy, modify, merge, publish, distribute, sublicense,
00009   and/or sell copies of the Software, and to permit persons to whom the
00010   Software is furnished to do so, subject to the following conditions:
00011 
00012   The above copyright notice and this permission notice shall be included in
00013   all copies or substantial portions of the Software.
00014 
00015   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00020   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00021   DEALINGS IN THE SOFTWARE.
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         // e->serial >= d->first_request , compare like X timestamps to handle wrapping
00121         && NET::timestampCompare( e->serial, d->first_request ) >= 0 )
00122         { // it's for us
00123         //qDebug( "Handling: %p", static_cast< void* >( this ));
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 // no handler set, simply set that there was an error
00136             error = true;
00137         if( error && !d->was_error )
00138             { // only remember the first
00139             d->was_error = true;
00140             d->error_event = *e;
00141             }
00142         return 0;
00143         }
00144     //qDebug( "Going deeper: %p", static_cast< void* >( this ));
00145     return old_handler( dpy, e );
00146     }
00147 
00148 QByteArray KXErrorHandler::errorMessage( const XErrorEvent& event, Display* dpy )
00149     { // "Error: <error> (<value>), Request: <request>(<value>), Resource: <value>"
00150     QByteArray ret;
00151     char tmp[ 256 ];
00152     char num[ 256 ];
00153 #if 0 // see below
00154     if( event.request_code < 128 ) // core request
00155 #endif
00156         {
00157         XGetErrorText( dpy, event.error_code, tmp, 255 );
00158         if( char* paren = strchr( tmp, '(' )) // the explanation in parentheses just makes
00159             *paren = '\0';                     // it more verbose and is not really useful
00160         // the various casts are to get overloads non-ambiguous :-/
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 // extensions
00170         {
00171         // XGetErrorText() currently has a bug that makes it fail to find text
00172         // for some errors (when error==error_base), also XGetErrorDatabaseText()
00173         // requires the right extension name, so it is needed to get info about
00174         // all extensions. However that is almost impossible:
00175         // - Xlib itself has it, but in internal data.
00176         // - Opening another X connection now can cause deadlock with server grabs.
00177         // - Fetching it at startup means a bunch of roundtrips.
00178         // So if this becomes more useful in the future, do the roundtrips at startup,
00179         // or fetch it in kded and export as an env.var or something.
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 )) // XGetErrorText() failed,
00216             { // or it has a bug that causes not finding all errors, check ourselves
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' ) // not found???
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

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal