khtml Library API Documentation

javaembed.cpp

00001 /****************************************************************************
00002     Implementation of QXEmbed class
00003 
00004    Copyright (C) 1999-2000 Troll Tech AS
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA 02111-1307, USA.
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 // avoid name clashes between X and Qt
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         //kdDebug(6100) << "KJavaEmbed::eventFilter, event = " << KQEventUtil::getQtEventName( e ) << endl;
00067         if( o == this )
00068         {
00069             //kdDebug(6100) << "event is for me:)" << endl;
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                 /* check to see if we are entering the applet somehow... */
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                     // if the browser window is moved or the page scrolled,
00096                     // AWT buttons do not respond anymore (although they are
00097                     // visually updated!) and subframes of select boxes appear
00098                     // on completely wrong (old) positions.
00099                     // This fixes the problem by notifying the applet.
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     // we are interested in SubstructureNotify
00134     XSelectInput(qt_xdisplay(), winId(),
00135                  KeyPressMask | KeyReleaseMask |
00136                  ButtonPressMask | ButtonReleaseMask |
00137                  KeymapStateMask |
00138                  ButtonMotionMask |
00139                  PointerMotionMask | // may need this, too
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     //kdDebug(6100) << "~KJavaEmbed() window=" << window << endl;
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     //kdDebug(6100) << "KJavaEmbed::resizeEvent width=" << e->size().width() << " height=" << e->size().height() <<endl;
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     //kdDebug(6100) << "KJavaEmbed::event, event type = " << KQEventUtil::getQtEventName( e ) << endl;
00181     switch( e->type() )
00182     {
00183         case QEvent::ShowWindowRequest:
00184         case QEvent::WindowActivate:
00185             //kdDebug(6100) << "XMapRaised window=" << window << endl;
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     //kdDebug(6100) << "KJavaEmbed::focusInEvent" << endl;
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     //kdDebug(6100) << "KJavaEmbed::focusOutEvent" << endl;
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    // defined in qapplication_x11.cpp
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     //kdDebug(6100) << "KJavaEmbed::embed " << w << endl;
00264 
00265     if ( w == 0 )
00266         return;
00267 
00268     window = w;
00269 
00270     //first withdraw the window
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); // 1 ms 
00280 #endif
00281             }
00282             if (cnt < max) { 
00283                 //kdDebug(6100) 
00284                 //    << "KJavaEmbed::embed: window withdrawn after " 
00285                 //    << cnt << " loops" << endl;
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     //now reparent the window to be swallowed by the KJavaEmbed widget
00297     //kdDebug(6100) << "++++++++++++++ Reparent embedder=" << winId() << " applet=" << window << endl;
00298     XReparentWindow( qt_xdisplay(), window, winId(), 0, 0 );
00299     QApplication::syncX();
00300     
00301     //now resize it
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     // kdDebug(6100) << "KJavaEmbed::x11Event " << KXEventUtil::getX11EventInfo( e ) << endl;
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         // kdDebug(6100) << "*************** sendSyntheticConfigureNotify ******************" << endl;
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         //kdDebug(6100) << "SENT " << KXEventUtil::getX11EventInfo((XEvent*)&c) << endl;
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 // for KDE
00409 #include "javaembed.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:22:38 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001