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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • 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 
33 class KXErrorHandlerPrivate
34 {
35 public:
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 
48 KXErrorHandler** KXErrorHandler::handlers = NULL;
49 int KXErrorHandler::pos = 0;
50 int KXErrorHandler::size = 0;
51 
52 KXErrorHandler::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
62 KXErrorHandler::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 
72 KXErrorHandler::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 
81 KXErrorHandler::~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 
89 void 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 
99 bool KXErrorHandler::error( bool sync ) const
100  {
101  if( sync )
102  XSync( d->display, False );
103  return d->was_error;
104  }
105 
106 XErrorEvent KXErrorHandler::errorEvent() const
107  {
108  return d->error_event;
109  }
110 
111 int 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 
119 int 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 
150 QByteArray 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::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
QByteArray
paren
KXErrorHandler::errorEvent
XErrorEvent errorEvent() const
This function returns the error event for the first X error that occurred.
Definition: kxerrorhandler.cpp:106
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
QString::number
QString number(int n, int base)
QByteArray::number
QByteArray number(int n, int base)
KXErrorHandler
This class simplifies handling of X errors.
Definition: kxerrorhandler.h:62
kxerrorhandler.h
KXErrorHandler::errorMessage
static QByteArray errorMessage(const XErrorEvent &e, Display *dpy=QX11Info::display())
Returns error message for the given error.
Definition: kxerrorhandler.cpp:150
netwm_def.h
KXErrorHandler::KXErrorHandler
KXErrorHandler(Display *dpy=QX11Info::display())
Creates error handler that will set error flag after encountering any X error.
Definition: kxerrorhandler.cpp:52
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:00 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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