00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #if HAVE_USLEEP
00025 #include <unistd.h>
00026 #endif // HAVE_USLEEP
00027 #endif // HAVE_CONFIG_H
00028 #include "javaembed.h"
00029
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032
00033 #include <qapplication.h>
00034 #include <qevent.h>
00035 #include <X11/X.h>
00036 #include <X11/Xlib.h>
00037 #include <X11/Xutil.h>
00038 #include <X11/Xatom.h>
00039
00040 const int XFocusOut = FocusOut;
00041 const int XFocusIn = FocusIn;
00042 const int XKeyPress = KeyPress;
00043 const int XKeyRelease = KeyRelease;
00044 #undef KeyRelease
00045 #undef KeyPress
00046 #undef FocusOut
00047 #undef FocusIn
00048
00049 #include "kqeventutil.h"
00050 #include "kxeventutil.h"
00051 class KJavaEmbedPrivate
00052 {
00053 friend class KJavaEmbed;
00054 public:
00055 QPoint lastPos;
00056 };
00057
00060 bool KJavaEmbed::eventFilter( QObject* o, QEvent* e)
00061 {
00062 QEvent::Type t = e->type();
00063
00064 if( t != QEvent::MouseMove && t != QEvent::Timer && t <= QEvent::User )
00065 {
00066
00067 if( o == this )
00068 {
00069
00070 }
00071 switch ( e->type() )
00072 {
00073
00074 case QEvent::FocusIn:
00075 break;
00076
00077 case QEvent::FocusOut:
00078 break;
00079
00080 case QEvent::Leave:
00081
00082 break;
00083
00084 case QEvent::Enter:
00085 break;
00086
00087 case QEvent::WindowActivate:
00088 break;
00089
00090 case QEvent::WindowDeactivate:
00091 break;
00092
00093 case QEvent::Move:
00094 {
00095
00096
00097
00098
00099
00100 QPoint globalPos = mapToGlobal(QPoint(0,0));
00101 if (globalPos != d->lastPos) {
00102 d->lastPos = globalPos;
00103 sendSyntheticConfigureNotifyEvent();
00104 }
00105 }
00106 break;
00107
00108 default:
00109 break;
00110 }
00111
00112 }
00113
00114 return FALSE;
00115 }
00116
00123 KJavaEmbed::KJavaEmbed( QWidget *parent, const char *name, WFlags f )
00124 : QWidget( parent, name, f )
00125 {
00126 d = new KJavaEmbedPrivate;
00127
00128 setFocusPolicy( StrongFocus );
00129 setKeyCompression( FALSE );
00130 setAcceptDrops( TRUE );
00131
00132 window = 0;
00133
00134 XSelectInput(qt_xdisplay(), winId(),
00135 KeyPressMask | KeyReleaseMask |
00136 ButtonPressMask | ButtonReleaseMask |
00137 KeymapStateMask |
00138 ButtonMotionMask |
00139 PointerMotionMask |
00140 EnterWindowMask | LeaveWindowMask |
00141 FocusChangeMask |
00142 ExposureMask |
00143 StructureNotifyMask |
00144 SubstructureRedirectMask |
00145 SubstructureNotifyMask
00146 );
00147
00148 topLevelWidget()->installEventFilter( this );
00149 qApp->installEventFilter( this );
00150 }
00151
00155 KJavaEmbed::~KJavaEmbed()
00156 {
00157
00158 if ( window != 0 )
00159 {
00160 XUnmapWindow( qt_xdisplay(), window );
00161 QApplication::flushX();
00162 }
00163
00164 delete d;
00165 }
00166
00169 void KJavaEmbed::resizeEvent( QResizeEvent* e )
00170 {
00171
00172 QWidget::resizeEvent( e );
00173
00174 if ( window != 0 )
00175 XResizeWindow( qt_xdisplay(), window, e->size().width(), e->size().height() );
00176 }
00177
00178 bool KJavaEmbed::event( QEvent* e)
00179 {
00180
00181 switch( e->type() )
00182 {
00183 case QEvent::ShowWindowRequest:
00184 case QEvent::WindowActivate:
00185
00186 if (window != 0) {
00187 XMapRaised( qt_xdisplay(), window );
00188 QApplication::syncX();
00189 }
00190 break;
00191 default:
00192 break;
00193 }
00194 return QWidget::event( e );
00195 }
00196
00199 void KJavaEmbed::focusInEvent( QFocusEvent* )
00200 {
00201
00202
00203 if ( !window )
00204 return;
00205
00206 XEvent ev;
00207 memset( &ev, 0, sizeof( ev ) );
00208 ev.xfocus.type = XFocusIn;
00209 ev.xfocus.window = window;
00210
00211 XSendEvent( qt_xdisplay(), window, true, NoEventMask, &ev );
00212 }
00213
00216 void KJavaEmbed::focusOutEvent( QFocusEvent* )
00217 {
00218
00219
00220 if ( !window )
00221 return;
00222
00223 XEvent ev;
00224 memset( &ev, 0, sizeof( ev ) );
00225 ev.xfocus.type = XFocusOut;
00226 ev.xfocus.window = window;
00227 XSendEvent( qt_xdisplay(), window, true, NoEventMask, &ev );
00228 }
00229
00230 static bool wstate_withdrawn( WId winid )
00231 {
00232
00233 extern Atom qt_wm_state;
00234 Atom type;
00235 int format;
00236 unsigned long length, after;
00237 unsigned char *data;
00238 int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
00239 FALSE, AnyPropertyType, &type, &format,
00240 &length, &after, &data );
00241 bool withdrawn = TRUE;
00242 if ( r == Success && data && format == 32 ) {
00243 Q_UINT32 *wstate = (Q_UINT32*)data;
00244 withdrawn = (*wstate == WithdrawnState );
00245 XFree( (char *)data );
00246 }
00247 return withdrawn;
00248 }
00249
00261 void KJavaEmbed::embed( WId w )
00262 {
00263
00264
00265 if ( w == 0 )
00266 return;
00267
00268 window = w;
00269
00270
00271 QApplication::flushX();
00272 if (!wstate_withdrawn(window)) {
00273 int status = XWithdrawWindow( qt_xdisplay(), window, qt_xscreen() );
00274 if (status > 0) {
00275 unsigned long cnt = 0;
00276 unsigned long max = 1000;
00277 for (cnt = 0; !wstate_withdrawn(window) && cnt < max; cnt++) {
00278 #if HAVE_USLEEP
00279 usleep(1000);
00280 #endif
00281 }
00282 if (cnt < max) {
00283
00284
00285
00286 } else {
00287 kdDebug(6100)
00288 << "KJavaEmbed::embed: window still not withdrawn after "
00289 << cnt << " loops " << endl;
00290 }
00291 } else {
00292 kdDebug(6100) << "KJavaEmbed::embed: XWithdrawWindow returned status=" << status << endl;
00293 }
00294 }
00295
00296
00297
00298 XReparentWindow( qt_xdisplay(), window, winId(), 0, 0 );
00299 QApplication::syncX();
00300
00301
00302 XResizeWindow( qt_xdisplay(), window, width(), height() );
00303 XMapRaised( qt_xdisplay(), window );
00304
00305 }
00306
00309 bool KJavaEmbed::focusNextPrevChild( bool next )
00310 {
00311 if ( window )
00312 return FALSE;
00313 else
00314 return QWidget::focusNextPrevChild( next );
00315 }
00316
00319 bool KJavaEmbed::x11Event( XEvent* e)
00320 {
00321
00322 switch ( e->type )
00323 {
00324 case DestroyNotify:
00325 if ( e->xdestroywindow.window == window )
00326 {
00327 window = 0;
00328 }
00329 break;
00330 case ConfigureRequest:
00331 if (e->xconfigurerequest.window == window)
00332 {
00333 sendSyntheticConfigureNotifyEvent();
00334 }
00335 break;
00336 default:
00337 break;
00338 }
00339
00340 return false;
00341 }
00342
00343 void KJavaEmbed::sendSyntheticConfigureNotifyEvent() {
00344 QPoint globalPos = mapToGlobal(QPoint(0,0));
00345 if (window) {
00346
00347 XConfigureEvent c;
00348 memset(&c, 0, sizeof(c));
00349 c.type = ConfigureNotify;
00350 c.display = qt_xdisplay();
00351 c.send_event = True;
00352 c.event = window;
00353 c.window = winId();
00354 c.x = globalPos.x();
00355 c.y = globalPos.y();
00356 c.width = width();
00357 c.height = height();
00358 c.border_width = 0;
00359 c.above = None;
00360 c.override_redirect = 0;
00361 XSendEvent( qt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
00362
00363 }
00364 }
00365
00371 QSizePolicy KJavaEmbed::sizePolicy() const
00372 {
00373 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
00374 }
00375
00379 QSize KJavaEmbed::sizeHint() const
00380 {
00381 return minimumSizeHint();
00382 }
00383
00387 QSize KJavaEmbed::minimumSizeHint() const
00388 {
00389 if ( window )
00390 {
00391 kdDebug(6100) << "KJavaEmbed::minimumSizeHint, getting hints from window" << endl;
00392
00393 XSizeHints size;
00394 long msize;
00395 if( XGetWMNormalHints( qt_xdisplay(), window, &size, &msize ) &&
00396 ( size.flags & PMinSize) )
00397 {
00398 kdDebug(6100) << "XGetWMNormalHints succeeded, width = " << size.min_width
00399 << ", height = " << size.min_height << endl;
00400
00401 return QSize( size.min_width, size.min_height );
00402 }
00403 }
00404
00405 return QSize( 0, 0 );
00406 }
00407
00408
00409 #include "javaembed.moc"