• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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 #ifndef KDE_NO_DEPRECATED
00062 KXErrorHandler::KXErrorHandler( bool (*handler)( int request, int error_code, unsigned long resource_id ), Display* dpy )
00063     :   user_handler1( handler ),
00064         user_handler2( NULL ),
00065         old_handler( XSetErrorHandler( handler_wrapper )),
00066         d( new KXErrorHandlerPrivate(dpy) )
00067     {
00068     addHandler();
00069     }
00070 #endif
00071 
00072 KXErrorHandler::KXErrorHandler( int (*handler)( Display*, XErrorEvent* ), Display* dpy )
00073     :   user_handler1( NULL ),
00074         user_handler2( handler ),
00075         old_handler( XSetErrorHandler( handler_wrapper )),
00076         d( new KXErrorHandlerPrivate(dpy) )
00077     {
00078     addHandler();
00079     }
00080 
00081 KXErrorHandler::~KXErrorHandler()
00082     {
00083     XSetErrorHandler( old_handler );
00084     Q_ASSERT_X( this == handlers[ pos-1 ], "KXErrorHandler", "out of order" );
00085     --pos;
00086     delete d;
00087     }
00088 
00089 void KXErrorHandler::addHandler()
00090     {
00091     if( size == pos )
00092         {
00093         size += 16;
00094         handlers = static_cast< KXErrorHandler** >( qRealloc( handlers, size * sizeof( KXErrorHandler* )));
00095         }
00096     handlers[ pos++ ] = this;
00097     }
00098 
00099 bool KXErrorHandler::error( bool sync ) const
00100     {
00101     if( sync )
00102         XSync( d->display, False );
00103     return d->was_error;
00104     }
00105 
00106 XErrorEvent KXErrorHandler::errorEvent() const
00107     {
00108     return d->error_event;
00109     }
00110 
00111 int KXErrorHandler::handler_wrapper( Display* dpy, XErrorEvent* e )
00112     {
00113     --pos;
00114     int ret = handlers[ pos ]->handle( dpy, e );
00115     ++pos;
00116     return ret;
00117     }
00118 
00119 int KXErrorHandler::handle( Display* dpy, XErrorEvent* e )
00120     {
00121     if( dpy == d->display
00122         // e->serial >= d->first_request , compare like X timestamps to handle wrapping
00123         && NET::timestampCompare( e->serial, d->first_request ) >= 0 )
00124         { // it's for us
00125         //qDebug( "Handling: %p", static_cast< void* >( this ));
00126         bool error = false;
00127         if( user_handler1 != NULL )
00128             {
00129             if( user_handler1( e->request_code, e->error_code, e->resourceid ))
00130                 error = true;
00131             }
00132         else if( user_handler2 != NULL )
00133             {
00134             if( user_handler2( dpy, e ) != 0 )
00135                 error = true;
00136             }
00137         else // no handler set, simply set that there was an error
00138             error = true;
00139         if( error && !d->was_error )
00140             { // only remember the first
00141             d->was_error = true;
00142             d->error_event = *e;
00143             }
00144         return 0;
00145         }
00146     //qDebug( "Going deeper: %p", static_cast< void* >( this ));
00147     return old_handler( dpy, e );
00148     }
00149 
00150 QByteArray KXErrorHandler::errorMessage( const XErrorEvent& event, Display* dpy )
00151     { // "Error: <error> (<value>), Request: <request>(<value>), Resource: <value>"
00152     QByteArray ret;
00153     char tmp[ 256 ];
00154     char num[ 256 ];
00155 #if 0 // see below
00156     if( event.request_code < 128 ) // core request
00157 #endif
00158         {
00159         XGetErrorText( dpy, event.error_code, tmp, 255 );
00160         if( char* paren = strchr( tmp, '(' )) // the explanation in parentheses just makes
00161             *paren = '\0';                     // it more verbose and is not really useful
00162         // the various casts are to get overloads non-ambiguous :-/
00163         ret = QByteArray( "error: " ) + (const char*)tmp + '[' + QByteArray::number( event.error_code ) + ']';
00164         sprintf( num, "%d", event.request_code );
00165         XGetErrorDatabaseText( dpy, "XRequest", num, "<unknown>", tmp, 256 );
00166         ret += QByteArray( ", request: " ) + (const char*)tmp + '[' + QByteArray::number( event.request_code ) + ']';
00167         if( event.resourceid != 0 )
00168             ret += QByteArray( ", resource: 0x" ) + QByteArray::number( (qlonglong)event.resourceid, 16 );
00169         }
00170 #if 0
00171     else // extensions
00172         {
00173         // XGetErrorText() currently has a bug that makes it fail to find text
00174         // for some errors (when error==error_base), also XGetErrorDatabaseText()
00175         // requires the right extension name, so it is needed to get info about
00176         // all extensions. However that is almost impossible:
00177         // - Xlib itself has it, but in internal data.
00178         // - Opening another X connection now can cause deadlock with server grabs.
00179         // - Fetching it at startup means a bunch of roundtrips.
00180         // So if this becomes more useful in the future, do the roundtrips at startup,
00181         // or fetch it in kded and export as an env.var or something.
00182         Display* dpy2 = XOpenDisplay( XDisplayString( dpy ));
00183         int nextensions;
00184         char** extensions = XListExtensions( dpy2, &nextensions );
00185         int* majors = NULL;
00186         int* error_bases = NULL;
00187         if( extensions == NULL )
00188             nextensions = 0;
00189         else
00190             {
00191             majors = new int[ nextensions ];
00192             error_bases = new int[ nextensions ];
00193             for( int i = 0;
00194                  i < nextensions;
00195                  ++i )
00196                 {
00197                 int dummy;
00198                 if( !XQueryExtension( dpy2, extensions[ i ], &majors[ i ], &dummy, &error_bases[ i ] ))
00199                     {
00200                     majors[ i ] = 0;
00201                     error_bases[ i ] = 0;
00202                     }
00203                 }
00204             }
00205         XGetErrorText( dpy, event.error_code, tmp, 255 );
00206         int index = -1;
00207         int base = 0;
00208         for( int i = 0;
00209              i < nextensions;
00210              ++i )
00211             if( error_bases[ i ] != 0
00212                 && event.error_code >= error_bases[ i ] && ( index == -1 || error_bases[ i ] > base ))
00213                 {
00214                 index = i;
00215                 base = error_bases[ i ];
00216                 }
00217         if( tmp == QString::number( event.error_code )) // XGetErrorText() failed,
00218             { // or it has a bug that causes not finding all errors, check ourselves
00219             if( index != -1 )
00220                 {
00221                 snprintf( num, 255, "%s.%d", extensions[ index ], event.error_code - base );
00222                 XGetErrorDatabaseText( dpy, "XProtoError", num, "<unknown>", tmp, 255 );
00223                 }
00224             else
00225                 strcpy( tmp, "<unknown>" );
00226             }
00227         if( char* paren = strchr( tmp, '(' ))
00228             *paren = '\0';
00229         if( index != -1 )
00230             ret = QByteArray( "error: " ) + (const char*)tmp + '[' + (const char*)extensions[ index ]
00231                 + '+' + QByteArray::number( event.error_code - base ) + ']';
00232         else
00233             ret = QByteArray( "error: " ) + (const char*)tmp + '[' + QByteArray::number( event.error_code ) + ']';
00234         tmp[ 0 ] = '\0';
00235         for( int i = 0;
00236              i < nextensions;
00237              ++i )
00238             if( majors[ i ] == event.request_code )
00239                 {
00240                 snprintf( num, 255, "%s.%d", extensions[ i ], event.minor_code );
00241                 XGetErrorDatabaseText( dpy, "XRequest", num, "<unknown>", tmp, 255 );
00242                 ret += QByteArray( ", request: " ) + (const char*)tmp + '[' + (const char*)extensions[ i ] + '+'
00243                     + QByteArray::number( event.minor_code ) + ']';
00244                 }
00245         if( tmp[ 0 ] == '\0' ) // not found???
00246             ret += QByteArray( ", request <unknown> [" ) + QByteArray::number( event.request_code ) + ':'
00247                 + QByteArray::number( event.minor_code ) + ']';
00248         if( event.resourceid != 0 )
00249             ret += QByteArray( ", resource: 0x" ) + QByteArray::number( (qlonglong)event.resourceid, 16 );
00250         if( extensions != NULL )
00251             XFreeExtensionList( extensions );
00252         delete[] majors;
00253         delete[] error_bases;
00254         XCloseDisplay( dpy2 );
00255         }
00256 #endif
00257     return ret;
00258     }
00259 
00260 #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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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