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 "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
00045 const long BROADCAST_MASK = PropertyChangeMask;
00046
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();
00055 kapp->installX11EventFilter( this );
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();
00073 kapp->installX11EventFilter( this );
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;
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;
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 ];
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
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;
00213 d->incoming_messages[ ev_P->xclient.window ] = buf;
00214 }
00215 if( i < 20 )
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;
00221 }
00222
00223 #include "kxmessages.moc"
00224 #endif