KDEUI
kxmessages.cpp
Go to the documentation of this file.
00001 /**************************************************************************** 00002 00003 Copyright (C) 2001-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 "kxmessages.h" 00026 00027 #ifdef Q_WS_X11 // FIXME(E): Figure out what parts we can/should emulate in QT/E 00028 00029 #include <qx11info_x11.h> 00030 #include <X11/Xlib.h> 00031 #include <fixx11h.h> 00032 #include <kapplication.h> 00033 00034 class KXMessagesPrivate 00035 { 00036 public: 00037 QWidget* handle; 00038 Atom accept_atom2; 00039 Atom accept_atom1; 00040 QMap< WId, QByteArray > incoming_messages; 00041 }; 00042 00043 00044 // for broadcasting 00045 const long BROADCAST_MASK = PropertyChangeMask; 00046 // CHECKME 00047 00048 KXMessages::KXMessages( const char* accept_broadcast_P, QWidget* parent_P ) 00049 : QWidget( parent_P ) 00050 , d( new KXMessagesPrivate ) 00051 { 00052 if( accept_broadcast_P != NULL ) 00053 { 00054 ( void ) qApp->desktop(); //trigger desktop widget creation to select root window events 00055 kapp->installX11EventFilter( this ); // i.e. PropertyChangeMask 00056 d->accept_atom1 = XInternAtom( QX11Info::display(), accept_broadcast_P, false ); 00057 d->accept_atom2 = d->accept_atom1; 00058 } 00059 else 00060 { 00061 d->accept_atom1 = d->accept_atom2 = None; 00062 } 00063 d->handle = new QWidget( this ); 00064 } 00065 00066 KXMessages::KXMessages( const char* accept_broadcast_P, QWidget* parent_P, bool obsolete_P ) 00067 : QWidget( parent_P ) 00068 , d( new KXMessagesPrivate ) 00069 { 00070 if( accept_broadcast_P != NULL ) 00071 { 00072 ( void ) qApp->desktop(); //trigger desktop widget creation to select root window events 00073 kapp->installX11EventFilter( this ); // i.e. PropertyChangeMask 00074 d->accept_atom2 = XInternAtom( QX11Info::display(), accept_broadcast_P, false ); 00075 d->accept_atom1 = obsolete_P ? d->accept_atom2 00076 : XInternAtom( QX11Info::display(), QByteArray( accept_broadcast_P ) + "_BEGIN", false ); 00077 } 00078 else 00079 { 00080 d->accept_atom1 = d->accept_atom2 = None; 00081 } 00082 d->handle = new QWidget( this ); 00083 } 00084 00085 KXMessages::~KXMessages() 00086 { 00087 delete d; 00088 } 00089 00090 00091 void KXMessages::broadcastMessage( const char* msg_type_P, const QString& message_P ) 00092 { 00093 broadcastMessage( msg_type_P, message_P, -1, true ); 00094 } 00095 00096 void KXMessages::broadcastMessage( const char* msg_type_P, const QString& message_P, 00097 int screen_P, bool obsolete_P ) 00098 { 00099 Atom a2 = XInternAtom( QX11Info::display(), msg_type_P, false ); 00100 Atom a1 = obsolete_P ? a2 : XInternAtom( QX11Info::display(), QByteArray( msg_type_P ) + "_BEGIN", false ); 00101 Window root = screen_P == -1 ? QX11Info::appRootWindow() : QX11Info::appRootWindow( screen_P ); 00102 send_message_internal( root, message_P, BROADCAST_MASK, QX11Info::display(), 00103 a1, a2, d->handle->winId()); 00104 } 00105 00106 void KXMessages::sendMessage( WId w_P, const char* msg_type_P, const QString& message_P ) 00107 { 00108 sendMessage( w_P, msg_type_P, message_P, true ); 00109 } 00110 00111 void KXMessages::sendMessage( WId w_P, const char* msg_type_P, const QString& message_P, 00112 bool obsolete_P ) 00113 { 00114 Atom a2 = XInternAtom( QX11Info::display(), msg_type_P, false ); 00115 Atom a1 = obsolete_P ? a2 : XInternAtom( QX11Info::display(), QByteArray( msg_type_P ) + "_BEGIN", false ); 00116 send_message_internal( w_P, message_P, 0, QX11Info::display(), a1, a2, d->handle->winId()); 00117 } 00118 00119 bool KXMessages::broadcastMessageX( Display* disp, const char* msg_type_P, 00120 const QString& message_P ) 00121 { 00122 return broadcastMessageX( disp, msg_type_P, message_P, -1, true ); 00123 } 00124 00125 bool KXMessages::broadcastMessageX( Display* disp, const char* msg_type_P, 00126 const QString& message_P, int screen_P, bool obsolete_P ) 00127 { 00128 if( disp == NULL ) 00129 return false; 00130 Atom a2 = XInternAtom( disp, msg_type_P, false ); 00131 Atom a1 = obsolete_P ? a2 : XInternAtom( disp, QByteArray( msg_type_P ) + "_BEGIN", false ); 00132 Window root = screen_P == -1 ? DefaultRootWindow( disp ) : RootWindow( disp, screen_P ); 00133 Window win = XCreateSimpleWindow( disp, root, 0, 0, 1, 1, 00134 0, BlackPixel( disp, screen_P == -1 ? DefaultScreen( disp ) : screen_P ), 00135 BlackPixel( disp, screen_P == -1 ? DefaultScreen( disp ) : screen_P )); 00136 send_message_internal( root, message_P, BROADCAST_MASK, disp, 00137 a1, a2, win ); 00138 XDestroyWindow( disp, win ); 00139 return true; 00140 } 00141 00142 bool KXMessages::sendMessageX( Display* disp, WId w_P, const char* msg_type_P, 00143 const QString& message_P ) 00144 { 00145 return sendMessageX( disp, w_P, msg_type_P, message_P, true ); 00146 } 00147 00148 bool KXMessages::sendMessageX( Display* disp, WId w_P, const char* msg_type_P, 00149 const QString& message_P, bool obsolete_P ) 00150 { 00151 if( disp == NULL ) 00152 return false; 00153 Atom a2 = XInternAtom( disp, msg_type_P, false ); 00154 Atom a1 = obsolete_P ? a2 : XInternAtom( disp, QByteArray( msg_type_P ) + "_BEGIN", false ); 00155 Window win = XCreateSimpleWindow( disp, DefaultRootWindow( disp ), 0, 0, 1, 1, 00156 0, BlackPixelOfScreen( DefaultScreenOfDisplay( disp )), 00157 BlackPixelOfScreen( DefaultScreenOfDisplay( disp ))); 00158 send_message_internal( w_P, message_P, 0, disp, a1, a2, win ); 00159 XDestroyWindow( disp, win ); 00160 return true; 00161 } 00162 00163 void KXMessages::send_message_internal( WId w_P, const QString& msg_P, long mask_P, 00164 Display* disp, Atom atom1_P, Atom atom2_P, Window handle_P ) 00165 { 00166 unsigned int pos = 0; 00167 QByteArray msg = msg_P.toUtf8(); 00168 unsigned int len = strlen( msg ); 00169 XEvent e; 00170 e.xclient.type = ClientMessage; 00171 e.xclient.message_type = atom1_P; // leading message 00172 e.xclient.display = disp; 00173 e.xclient.window = handle_P; 00174 e.xclient.format = 8; 00175 do 00176 { 00177 unsigned int i; 00178 for( i = 0; 00179 i < 20 && i + pos <= len; 00180 ++i ) 00181 e.xclient.data.b[ i ] = msg[ i + pos ]; 00182 XSendEvent( disp, w_P, false, mask_P, &e ); 00183 e.xclient.message_type = atom2_P; // following messages 00184 pos += i; 00185 } while( pos <= len ); 00186 XFlush( disp ); 00187 } 00188 00189 bool KXMessages::x11Event( XEvent* ev_P ) 00190 { 00191 if( ev_P->type != ClientMessage || ev_P->xclient.format != 8 ) 00192 return QWidget::x11Event( ev_P ); 00193 if( ev_P->xclient.message_type != d->accept_atom1 && ev_P->xclient.message_type != d->accept_atom2 ) 00194 return QWidget::x11Event( ev_P ); 00195 char buf[ 21 ]; // can't be longer 00196 int i; 00197 for( i = 0; 00198 i < 20 && ev_P->xclient.data.b[ i ] != '\0'; 00199 ++i ) 00200 buf[ i ] = ev_P->xclient.data.b[ i ]; 00201 buf[ i ] = '\0'; 00202 if( d->incoming_messages.contains( ev_P->xclient.window )) 00203 { 00204 if( ev_P->xclient.message_type == d->accept_atom1 && d->accept_atom1 != d->accept_atom2 ) 00205 // two different messages on the same window at the same time shouldn't happen anyway 00206 d->incoming_messages[ ev_P->xclient.window ] = QByteArray(); 00207 d->incoming_messages[ ev_P->xclient.window ] += buf; 00208 } 00209 else 00210 { 00211 if( ev_P->xclient.message_type == d->accept_atom2 && d->accept_atom1 != d->accept_atom2 ) 00212 return false; // middle of message, but we don't have the beginning 00213 d->incoming_messages[ ev_P->xclient.window ] = buf; 00214 } 00215 if( i < 20 ) // last message fragment 00216 { 00217 emit gotMessage( QString::fromUtf8( d->incoming_messages[ ev_P->xclient.window ] )); 00218 d->incoming_messages.remove( ev_P->xclient.window ); 00219 } 00220 return false; // lets other KXMessages instances get the event too 00221 } 00222 00223 #include "kxmessages.moc" 00224 #endif
KDE 4.6 API Reference