kdeui Library API Documentation

qxembed.cpp

00001 /****************************************************************************
00002     Implementation of QXEmbed class
00003 
00004     Copyright (C) 1999-2002 Trolltech 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 #include <qapplication.h>
00023 #include <qptrlist.h>
00024 #include <qptrdict.h>
00025 #include <qguardedptr.h>
00026 #include <qwhatsthis.h>
00027 #include <qfocusdata.h>
00028 #ifdef Q_WS_X11
00029 #include <X11/X.h>
00030 #include <X11/Xlib.h>
00031 #include <X11/Xutil.h>
00032 #include <X11/Xatom.h>
00033 #define XK_MISCELLANY
00034 #define XK_LATIN1
00035 #include <X11/keysymdef.h>
00036 #include <kdebug.h>
00037 //#include <kxeventutil.h>
00038 //#include <kqeventutil.h>
00039 #include <config.h>
00040 
00041 #ifdef HAVE_UNISTD_H
00042 #include <unistd.h>
00043 #ifdef HAVE_USLEEP
00044 #define USLEEP(x) usleep(x)
00045 #else
00046 #define USLEEP(x) sleep(0)
00047 #endif // HAVE_USLEEP
00048 #else
00049 #define USLEEP(x) sleep(0)
00050 #endif // HAVE_UNISTD_H
00051 
00052 #include "qxembed.h"
00053 
00054 #ifndef XK_ISO_Left_Tab
00055 #define XK_ISO_Left_Tab                                 0xFE20
00056 #endif
00057 const int XFocusOut = FocusOut;
00058 const int XFocusIn = FocusIn;
00059 const int XKeyPress = KeyPress;
00060 const int XKeyRelease = KeyRelease;
00061 #undef KeyRelease
00062 #undef KeyPress
00063 #undef FocusOut
00064 #undef FocusIn
00065 
00066 // defined in qapplication_x11.cpp
00067 extern Atom qt_wm_protocols;
00068 extern Atom qt_wm_delete_window;
00069 extern Atom qt_wm_take_focus;
00070 extern Time qt_x_time;
00071 extern Atom qt_wm_state;
00072 
00073 static Atom xembed = 0;
00074 static Atom context_help = 0;
00075 
00076 // xembed messages
00077 #define XEMBED_EMBEDDED_NOTIFY  0
00078 #define XEMBED_WINDOW_ACTIVATE          1
00079 #define XEMBED_WINDOW_DEACTIVATE        2
00080 #define XEMBED_REQUEST_FOCUS            3
00081 #define XEMBED_FOCUS_IN                 4
00082 #define XEMBED_FOCUS_OUT                5
00083 #define XEMBED_FOCUS_NEXT               6
00084 #define XEMBED_FOCUS_PREV               7
00085 
00086 // xembed details
00087 
00088 // XEMBED_FOCUS_IN:
00089 #define XEMBED_FOCUS_CURRENT    0
00090 #define XEMBED_FOCUS_FIRST              1
00091 #define XEMBED_FOCUS_LAST               2
00092 
00093 
00094 
00095 class QXEmbedData
00096 {
00097 public:
00098     QXEmbedData(){ 
00099         autoDelete = TRUE;
00100         lastPos = QPoint(0,0);
00101     }
00102     ~QXEmbedData(){};
00103 
00104     
00105     bool autoDelete;
00106     QWidget* focusProxy;
00107     QPoint lastPos;
00108     
00109 };
00110 
00111 class QXEmbedAppFilter : public QObject
00112 {
00113 public:
00114     QXEmbedAppFilter(){ qApp->installEventFilter( this ); }
00115     ~QXEmbedAppFilter(){};
00116     bool eventFilter( QObject *, QEvent * );
00117 };
00118 
00119 
00120 static QXEmbedAppFilter* filter = 0;
00121 static QPtrDict<QGuardedPtr<QWidget> > *focusMap = 0;
00122 
00123 static XKeyEvent last_key_event;
00124 static bool tabForward = TRUE;
00125 
00126 
00127 class QPublicWidget : public QWidget
00128 {
00129 public:
00130     QTLWExtra* topData() { return QWidget::topData(); };
00131     QFocusData *focusData(){ return QWidget::focusData(); };
00132 };
00133 
00134 typedef int (*QX11EventFilter) (XEvent*);
00135 extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter);
00136 static QX11EventFilter oldFilter = 0;
00137 
00138 
00139 static void send_xembed_message( WId window, long message, long detail = 0,
00140                                  long data1 = 0, long data2 = 0)
00141 {
00142     XEvent ev;
00143     memset(&ev, 0, sizeof(ev));
00144     ev.xclient.type = ClientMessage;
00145     ev.xclient.window = window;
00146     ev.xclient.message_type = xembed;
00147     ev.xclient.format = 32;
00148     ev.xclient.data.l[0] = qt_x_time;
00149     ev.xclient.data.l[1] = message;
00150     ev.xclient.data.l[2] = detail;
00151     ev.xclient.data.l[3] = data1;
00152     ev.xclient.data.l[4] = data2;
00153     XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev);
00154 }
00155 
00156 static void sendClientMessage(Window window, Atom a, long x){
00157   XEvent ev;
00158   memset(&ev, 0, sizeof(ev));
00159   ev.xclient.type = ClientMessage;
00160   ev.xclient.window = window;
00161   ev.xclient.message_type = a;
00162   ev.xclient.format = 32;
00163   ev.xclient.data.l[0] = x;
00164   ev.xclient.data.l[1] = qt_x_time;
00165   XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev);
00166 }
00167 
00168 
00169 bool QXEmbedAppFilter::eventFilter( QObject *o, QEvent * e)
00170 {
00171     static bool obeyFocus = FALSE;
00172     switch ( e->type() ) {
00173     case QEvent::MouseButtonPress:
00174         if ( !((QWidget*)o)->isActiveWindow() )
00175             obeyFocus = TRUE;
00176         break;
00177     case QEvent::FocusIn:
00178         if ( qApp->focusWidget() == o &&
00179              ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
00180             QFocusEvent* fe = (QFocusEvent*) e;
00181 
00182             if ( obeyFocus || fe->reason() == QFocusEvent::Mouse ||
00183                  fe->reason() == QFocusEvent::Shortcut ) {
00184                 WId window = ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->parentWinId;
00185                 focusMap->remove( qApp->focusWidget()->topLevelWidget() );
00186                 send_xembed_message( window, XEMBED_REQUEST_FOCUS );
00187             } else if ( fe->reason() == QFocusEvent::ActiveWindow ) {
00188                 focusMap->remove( qApp->focusWidget()->topLevelWidget() );
00189                 focusMap->insert( qApp->focusWidget()->topLevelWidget(),
00190                                   new QGuardedPtr<QWidget>(qApp->focusWidget()->topLevelWidget()->focusWidget() ) );
00191                 qApp->focusWidget()->clearFocus();
00192             }
00193             obeyFocus = FALSE;
00194         }
00195         break;
00196     default:
00197         break;
00198     }
00199     return FALSE;
00200 }
00201 
00202 
00203 static int qxembed_x11_event_filter( XEvent* e)
00204 {
00205     //kdDebug() << "qxembed_x11_event_filter " << KXEventUtil::getX11EventInfo(e) << endl;
00206 
00207     switch ( e->type ) {
00208     case XKeyPress: {
00209         int kc = XKeycodeToKeysym(qt_xdisplay(), e->xkey.keycode, 0);
00210         if ( kc == XK_Tab || kc == XK_ISO_Left_Tab ) {
00211             tabForward = (e->xkey.state & ShiftMask) == 0;
00212             QWidget* w = QWidget::find( e->xkey.window );
00213             if ( w && w->isActiveWindow() && qApp->focusWidget() &&
00214                  qApp->focusWidget()->topLevelWidget() == w->topLevelWidget() &&
00215                  ((QPublicWidget*)w->topLevelWidget())->topData()->embedded ) {
00216                 WId window = ((QPublicWidget*)w->topLevelWidget())->topData()->parentWinId;
00217                 QFocusData *fd = ((QPublicWidget*)w)->focusData();
00218                 while ( fd->next() != w->topLevelWidget() )
00219                     ;
00220                 QWidget* first = fd->next();
00221                 QWidget* last = fd->prev(); last = fd->prev();
00222                 if ( !tabForward && fd->focusWidget() == first ) {
00223                     send_xembed_message( window, XEMBED_FOCUS_PREV );
00224                     return TRUE;
00225                 } else if ( tabForward && fd->focusWidget() == last ) {
00226                     send_xembed_message( window, XEMBED_FOCUS_NEXT );
00227                     return TRUE;
00228                 }
00229             }
00230         } else
00231             last_key_event = e->xkey;
00232     }
00233     // FALL THROUGH
00234     case XKeyRelease: {
00235         last_key_event = e->xkey;
00236         break;
00237     }
00238     case ClientMessage:
00239         if ( e->xclient.message_type == xembed ) {
00240             Time msgtime = (Time) e->xclient.data.l[0];
00241             long message = e->xclient.data.l[1];
00242             long detail = e->xclient.data.l[2];
00243             if ( msgtime > qt_x_time )
00244                 qt_x_time = msgtime;
00245             QWidget* w = QWidget::find( e->xclient.window );
00246             if ( !w )
00247                 break;
00248             switch ( message) {
00249             case XEMBED_EMBEDDED_NOTIFY:
00250                 ((QPublicWidget*)w->topLevelWidget())->topData()->embedded = 1;
00251                 w->topLevelWidget()->show();
00252                 break;
00253             case XEMBED_WINDOW_ACTIVATE: {
00254                 // fake focus in
00255                 XEvent ev;
00256                 memset(&ev, 0, sizeof(ev));
00257                 ev.xfocus.display = qt_xdisplay();
00258                 ev.xfocus.type = XFocusIn;
00259                 ev.xfocus.window = w->topLevelWidget()->winId();
00260                 ev.xfocus.mode = NotifyNormal;
00261                 ev.xfocus.detail = NotifyAncestor;
00262                 qApp->x11ProcessEvent( &ev );
00263             }
00264             break;
00265             case XEMBED_WINDOW_DEACTIVATE: {
00266                 // fake focus out
00267                 XEvent ev;
00268                 memset(&ev, 0, sizeof(ev));
00269                 ev.xfocus.display = qt_xdisplay();
00270                 ev.xfocus.type = XFocusOut;
00271                 ev.xfocus.window = w->topLevelWidget()->winId();
00272                 ev.xfocus.mode = NotifyNormal;
00273                 ev.xfocus.detail = NotifyAncestor;
00274                 qApp->x11ProcessEvent( &ev );
00275             }
00276             break;
00277             case XEMBED_FOCUS_IN:
00278                 {
00279                     QWidget* focusCurrent = 0;
00280                     QGuardedPtr<QWidget>* fw = focusMap->find( w->topLevelWidget() );
00281                     if ( fw ) {
00282                         focusCurrent = *fw;
00283                         focusMap->remove( w->topLevelWidget() );
00284                     }
00285                     switch ( detail ) {
00286                     case XEMBED_FOCUS_CURRENT:
00287                         if ( focusCurrent )
00288                             focusCurrent->setFocus();
00289                         else if ( !w->topLevelWidget()->focusWidget() )
00290                             w->topLevelWidget()->setFocus();
00291                         break;
00292                     case XEMBED_FOCUS_FIRST:
00293                         {
00294                             QFocusData *fd = ((QPublicWidget*)w)->focusData();
00295                             while ( fd->next() != w->topLevelWidget() )
00296                                 ;
00297                             QWidget* fw = fd->next();
00298                             QFocusEvent::setReason( QFocusEvent::Tab );
00299                             if ( w )
00300                                 fw->setFocus();
00301                             else
00302                                 w->topLevelWidget()->setFocus();
00303                             QFocusEvent::resetReason();
00304                         }
00305                         break;
00306                     case XEMBED_FOCUS_LAST:
00307                         {
00308                             QFocusData *fd = ((QPublicWidget*)w)->focusData();
00309                             while ( fd->next() != w->topLevelWidget() )
00310                                 ;
00311                             QWidget* fw = fd->prev();
00312                             QFocusEvent::setReason( QFocusEvent::Tab );
00313                             if ( w )
00314                                 fw->setFocus();
00315                             else
00316                                 w->topLevelWidget()->setFocus();
00317                             QFocusEvent::resetReason();
00318                         }
00319                         break;
00320                     default:
00321                         break;
00322                     }
00323                 }
00324                 break;
00325             case XEMBED_FOCUS_OUT:
00326                 if ( w->topLevelWidget()->focusWidget() ) {
00327                     focusMap->insert( w->topLevelWidget(),
00328                                       new QGuardedPtr<QWidget>(w->topLevelWidget()->focusWidget() ) );
00329                     w->topLevelWidget()->focusWidget()->clearFocus();
00330                 }
00331             break;
00332             default:
00333                 break;
00334             }
00335         } else if ( e->xclient.format == 32 && e->xclient.message_type ) {
00336             if ( e->xclient.message_type == qt_wm_protocols ) {
00337                 QWidget* w = QWidget::find( e->xclient.window );
00338                 if ( !w )
00339                     break;
00340                 Atom a = e->xclient.data.l[0];
00341                 if ( a == qt_wm_take_focus ) {
00342                     if ( (ulong) e->xclient.data.l[1] > qt_x_time )
00343                         qt_x_time = e->xclient.data.l[1];
00344                     if ( w->isActiveWindow() ) {
00345                         // send another WindowActivate. The QXEmbed
00346                         // widget will filter it and pass the focus to
00347                         // the proxy
00348                         QEvent e( QEvent::WindowActivate );
00349                         QApplication::sendEvent( w, &e );
00350                     }
00351                 }
00352             }
00353         }
00354         break;
00355     default:
00356         break;
00357     }
00358 
00359     if ( oldFilter )
00360         return oldFilter( e );
00361     return FALSE;
00362 }
00363 
00372 void QXEmbed::initialize()
00373 {
00374     static bool is_initialized = FALSE;
00375     if ( is_initialized )
00376         return;
00377     xembed = XInternAtom( qt_xdisplay(), "_XEMBED", FALSE );
00378     oldFilter = qt_set_x11_event_filter( qxembed_x11_event_filter );
00379 
00380     focusMap = new QPtrDict<QGuardedPtr<QWidget> >;
00381     focusMap->setAutoDelete( TRUE );
00382 
00383     filter = new QXEmbedAppFilter;
00384 
00385     is_initialized = TRUE;
00386 }
00387 
00388 
00427 QXEmbed::QXEmbed(QWidget *parent, const char *name, WFlags f)
00428   : QWidget(parent, name, f)
00429 {
00430     d = new QXEmbedData;
00431     d->focusProxy = new QWidget( this, "xembed_focus" );
00432     d->focusProxy->setGeometry( -1, -1, 1, 1 );
00433     initialize();
00434     window = 0;
00435     setFocusPolicy(StrongFocus);
00436     setKeyCompression( FALSE );
00437 
00438     //trick to create extraData();
00439     (void) topData();
00440 
00441     // we are interested in SubstructureNotify
00442     XSelectInput(qt_xdisplay(), winId(),
00443                  KeyPressMask | KeyReleaseMask |
00444                  ButtonPressMask | ButtonReleaseMask |
00445                  KeymapStateMask |
00446                  ButtonMotionMask |
00447                  PointerMotionMask | // may need this, too
00448                  EnterWindowMask | LeaveWindowMask |
00449                  FocusChangeMask |
00450                  ExposureMask |
00451                  StructureNotifyMask |
00452                  SubstructureRedirectMask |
00453                  SubstructureNotifyMask
00454                  );
00455 
00456     topLevelWidget()->installEventFilter( this );
00457     qApp->installEventFilter( this );
00458 
00459     setAcceptDrops( TRUE );
00460 }
00461 
00465 QXEmbed::~QXEmbed()
00466 {
00467 
00468     if ( window != 0 ) {
00469         if ( autoDelete() )
00470             XUnmapWindow( qt_xdisplay(), window );
00471 
00472         XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0);
00473         XSync(qt_xdisplay(), FALSE);
00474 
00475         if ( autoDelete() ) {
00476             XEvent ev;
00477             memset(&ev, 0, sizeof(ev));
00478             ev.xclient.type = ClientMessage;
00479             ev.xclient.window = window;
00480             ev.xclient.message_type = qt_wm_protocols;
00481             ev.xclient.format = 32;
00482             ev.xclient.data.s[0] = qt_wm_delete_window;
00483             XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev);
00484         }
00485         XFlush( qt_xdisplay() );
00486      }
00487     window = 0;
00488 
00489     delete d;
00490 }
00491 
00492 
00495 void QXEmbed::resizeEvent(QResizeEvent*)
00496 {
00497     if (window != 0)
00498         XResizeWindow(qt_xdisplay(), window, width(), height());
00499 }
00500 
00503 void QXEmbed::showEvent(QShowEvent*)
00504 {
00505     if (window != 0)
00506         XMapRaised(qt_xdisplay(), window);
00507 
00508 }
00509 
00510 
00513 bool QXEmbed::eventFilter( QObject *o, QEvent * e)
00514 {
00515 
00516     switch ( e->type() ) {
00517     case QEvent::WindowActivate:
00518         if ( o == topLevelWidget() ) {
00519             if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
00520                 XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), RevertToParent, qt_x_time );
00521             send_xembed_message( window, XEMBED_WINDOW_ACTIVATE );
00522         }
00523         break;
00524     case QEvent::WindowDeactivate:
00525         if ( o == topLevelWidget() )
00526             send_xembed_message( window, XEMBED_WINDOW_DEACTIVATE );
00527         break;
00528     case QEvent::Move:
00529         {
00530             QPoint globalPos = mapToGlobal(QPoint(0,0));
00531             if (globalPos != d->lastPos) {
00532                 d->lastPos = globalPos;
00533                 sendSyntheticConfigureNotifyEvent();
00534             }
00535         }                    
00536         break;
00537     default:
00538         break;
00539    }
00540    return FALSE;
00541 }
00542 
00543 
00544 bool  QXEmbed::event( QEvent * e)
00545 {
00546     return QWidget::event( e );
00547 }
00548 
00551 void QXEmbed::keyPressEvent( QKeyEvent *)
00552 {
00553     if (!window)
00554         return;
00555     last_key_event.window = window;
00556     XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, (XEvent*)&last_key_event);
00557 
00558 }
00559 
00562 void QXEmbed::keyReleaseEvent( QKeyEvent *)
00563 {
00564     if (!window)
00565         return;
00566     last_key_event.window = window;
00567     XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, (XEvent*)&last_key_event);
00568 }
00569 
00572 void QXEmbed::focusInEvent( QFocusEvent * e ){
00573     if (!window)
00574         return;
00575     int detail = XEMBED_FOCUS_CURRENT;
00576     if ( e->reason() == QFocusEvent::Tab )
00577         detail = tabForward?XEMBED_FOCUS_FIRST:XEMBED_FOCUS_LAST;
00578     send_xembed_message( window, XEMBED_FOCUS_IN, detail);
00579 }
00580 
00583 void QXEmbed::focusOutEvent( QFocusEvent * ){
00584     if (!window)
00585         return;
00586     send_xembed_message( window, XEMBED_FOCUS_OUT );
00587 }
00588 
00589 
00590 
00591 static bool wstate_withdrawn( WId winid )
00592 {
00593     Atom type;
00594     int format;
00595     unsigned long length, after;
00596     unsigned char *data;
00597     int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
00598                                 FALSE, AnyPropertyType, &type, &format,
00599                                 &length, &after, &data );
00600     bool withdrawn = TRUE;
00601     if ( r == Success && data && format == 32 ) {
00602         Q_UINT32 *wstate = (Q_UINT32*)data;
00603         withdrawn  = (*wstate == WithdrawnState );
00604         XFree( (char *)data );
00605     }
00606     return withdrawn;
00607 }
00608 
00609 static int get_parent(WId winid, Window *out_parent)
00610 {
00611     Window root, *children=0;
00612     unsigned int nchildren;
00613     int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
00614     if (st) {
00615         if (children) {
00616             XFree(children);
00617         }
00618         return st;
00619     } else {
00620         // kdDebug() << QString("**** FAILED **** XQueryTree returns status %1").arg(st) << endl;
00621     }
00622     return st;
00623 }
00624 #include <unistd.h>
00637 void QXEmbed::embed(WId w)
00638 {
00639     kdDebug() << "************************** Embed "<< QString("0x%1").arg(w, 0, 16) << " into " << QString("0x%1").arg(winId(), 0, 16) << " window=" << QString("0x%1").arg(window, 0, 16) << " **********" << endl; 
00640     if (!w)
00641         return;
00642     XAddToSaveSet( qt_xdisplay(), w );
00643     bool has_window =  w == window;
00644     window = w;
00645     if ( !has_window ) {
00646         if ( !wstate_withdrawn(window) ) {
00647             XWithdrawWindow(qt_xdisplay(), window, qt_xscreen());
00648             QApplication::flushX();
00649             while (!wstate_withdrawn(window))
00650                 ;
00651         }
00652         Window parent;
00653         get_parent(w, &parent);
00654         kdDebug() << QString(">>> before reparent: parent=0x%1").arg(parent, 0, 16) << endl;
00655         for (int i = 0; i < 50; i++) {
00656             Window parent = 0;
00657             XReparentWindow(qt_xdisplay(), w, winId(), 0, 0);
00658             if (get_parent(w, &parent) && parent == winId()) {
00659                kdDebug() << QString(">>> Loop %1: reparent of 0x%2 into 0x%3 successful").arg(i).arg(w, 0, 16).arg(winId(), 0, 16) << endl;
00660                break;
00661             }
00662             kdDebug() << QString(">>> Loop %1: reparent of 0x%2 into 0x%3 failed").arg(i).arg(w, 0, 16).arg(winId(), 0, 16) << endl;
00663             USLEEP(1000);
00664         }
00665         QApplication::syncX();
00666     }
00667 
00668     XResizeWindow(qt_xdisplay(), w, width(), height());
00669     XMapRaised(qt_xdisplay(), window);
00670     sendSyntheticConfigureNotifyEvent();
00671     extraData()->xDndProxy = w;
00672 
00673     if ( parent() ) {
00674         QEvent * layoutHint = new QEvent( QEvent::LayoutHint );
00675         QApplication::postEvent( parent(), layoutHint );
00676     }
00677     windowChanged( window );
00678     send_xembed_message( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
00679     send_xembed_message( window, isActiveWindow() ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE );
00680     if ( hasFocus() )
00681         send_xembed_message( window, XEMBED_FOCUS_IN );
00682 }
00683 
00684 
00689 WId QXEmbed::embeddedWinId() const
00690 {
00691     return window;
00692 }
00693 
00694 
00697 bool QXEmbed::focusNextPrevChild( bool next )
00698 {
00699     if ( window )
00700         return FALSE;
00701     else
00702         return QWidget::focusNextPrevChild( next );
00703 }
00704 
00705 
00708 bool QXEmbed::x11Event( XEvent* e)
00709 {
00710     //kdDebug() << "x11Event " << KXEventUtil::getX11EventInfo(e) << endl;
00711     switch ( e->type ) {
00712     case DestroyNotify:
00713         if ( e->xdestroywindow.window == window ) {
00714             window = 0;
00715             windowChanged( window );
00716             emit embeddedWindowDestroyed();
00717         }
00718         break;
00719     case ReparentNotify:
00720         if ( e->xreparent.window == d->focusProxy->winId() )
00721             break; // ignore proxy
00722         if ( window && e->xreparent.window == window &&
00723              e->xreparent.parent != winId() ) {
00724             // we lost the window
00725             window = 0;
00726             windowChanged( window );
00727         } else if ( e->xreparent.parent == winId() ){
00728             // we got a window
00729             window = e->xreparent.window;
00730             embed( window );
00731         }
00732         break;
00733     case MapRequest:
00734         if ( window && e->xmaprequest.window == window )
00735             XMapRaised(qt_xdisplay(), window );
00736         break;
00737     case ClientMessage:
00738         if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
00739             long message = e->xclient.data.l[1];
00740 //          long detail = e->xclient.data.l[2];
00741             switch ( message ) {
00742             case XEMBED_FOCUS_NEXT:
00743                 QWidget::focusNextPrevChild( TRUE );
00744                 break;
00745             case XEMBED_FOCUS_PREV:
00746                 QWidget::focusNextPrevChild( FALSE );
00747                 break;
00748             case XEMBED_REQUEST_FOCUS:
00749                 QFocusEvent::setReason( QFocusEvent::Mouse );
00750                 setFocus();
00751                 QFocusEvent::resetReason();
00752                 break;
00753             default:
00754                 break;
00755             }
00756         }
00757     break;
00758 
00759     case ConfigureRequest:
00760         if (e->xconfigurerequest.window == window) 
00761         {
00762              sendSyntheticConfigureNotifyEvent();
00763         }
00764         break;
00765     case MotionNotify: 
00766     // fall through, workaround for Qt 3.0 < 3.0.3
00767     case EnterNotify:
00768         if ( QWhatsThis::inWhatsThisMode() )
00769             enterWhatsThisMode();
00770         break;
00771     default:
00772         break;
00773     }
00774     return FALSE;
00775 }
00776 
00777  // temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000  )
00778 void QXEmbed::enterWhatsThisMode()
00779 {
00780     QWhatsThis::leaveWhatsThisMode();
00781     if ( !context_help )
00782         context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", FALSE );
00783     sendClientMessage(window , qt_wm_protocols, context_help );
00784 }
00785 
00786 
00792 void QXEmbed::windowChanged( WId )
00793 {
00794 }
00795 
00796 
00807 bool QXEmbed::processClientCmdline( QWidget* client, int& argc, char ** argv )
00808 {
00809     int myargc = argc;
00810     WId window = 0;
00811     int i, j;
00812 
00813     j = 1;
00814     for ( i=1; i<myargc; i++ ) {
00815         if ( argv[i] && *argv[i] != '-' ) {
00816             argv[j++] = argv[i];
00817             continue;
00818         }
00819         QCString arg = argv[i];
00820         if ( strcmp(arg,"-embed") == 0 && i < myargc-1 ) {
00821             QCString s = argv[++i];
00822             window = s.toInt();
00823         } else
00824             argv[j++] = argv[i];
00825     }
00826     argc = j;
00827 
00828     if ( window != 0 ) {
00829         embedClientIntoWindow( client, window );
00830         return TRUE;
00831     }
00832 
00833     return FALSE;
00834 }
00835 
00836 
00845 void QXEmbed::embedClientIntoWindow(QWidget* client, WId window)
00846 {
00847     initialize();
00848     XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0);
00849     ((QXEmbed*)client)->topData()->embedded = TRUE;
00850     ((QXEmbed*)client)->topData()->parentWinId = window;
00851     client->show();
00852 }
00853 
00854 
00855 
00861 QSizePolicy QXEmbed::sizePolicy() const
00862 {
00863     return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
00864 }
00865 
00866 
00870 QSize QXEmbed::sizeHint() const
00871 {
00872     return minimumSizeHint();
00873 }
00874 
00887 QSize QXEmbed::minimumSizeHint() const
00888 {
00889     int minw = 0;
00890     int minh = 0;
00891     if ( window ) {
00892         XSizeHints size;
00893         long msize;
00894         if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize)
00895             && ( size.flags & PMinSize) ) {
00896             minw = size.min_width;
00897             minh = size.min_height;
00898         }
00899     }
00900 
00901     return QSize( minw, minh );
00902 }
00903 
00904 void QXEmbed::setAutoDelete( bool b)
00905 {
00906     d->autoDelete = b;
00907 }
00908 
00909 bool QXEmbed::autoDelete() const
00910 {
00911     return d->autoDelete;
00912 }
00913 
00916 bool QXEmbed::customWhatsThis() const
00917 {
00918     return TRUE;
00919 }
00920 
00921 void QXEmbed::sendSyntheticConfigureNotifyEvent() {
00922     QPoint globalPos = mapToGlobal(QPoint(0,0));
00923     if (window) {
00924         // kdDebug(6100) << "*************** sendSyntheticConfigureNotify ******************" << endl;
00925         XConfigureEvent c;
00926         memset(&c, 0, sizeof(c));
00927         c.type = ConfigureNotify;
00928         c.display = qt_xdisplay();
00929         c.send_event = True;
00930         c.event = window;
00931         c.window = winId();
00932         c.x = globalPos.x();
00933         c.y = globalPos.y();
00934         c.width = width();
00935         c.height = height();
00936         c.border_width = 0;
00937         c.above = None;
00938         c.override_redirect = 0;
00939         XSendEvent( qt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
00940         //kdDebug(6100) << "SENT " << KXEventUtil::getX11EventInfo((XEvent*)&c) << endl;
00941     }
00942 }
00943 
00944 // for KDE
00945 #include "qxembed.moc"
00946 #endif
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:21:02 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001