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 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 #include <qapplication.h>
00050 #include <qptrlist.h>
00051 #include <qptrdict.h>
00052 #include <qguardedptr.h>
00053 #include <qwhatsthis.h>
00054 #include <qfocusdata.h>
00055 
00056 
00057 #ifdef Q_WS_X11
00058 
00059 # include <X11/X.h>
00060 # include <X11/Xlib.h>
00061 # include <X11/Xutil.h>
00062 # include <X11/Xatom.h>
00063 # define XK_MISCELLANY
00064 # define XK_LATIN1
00065 # include <X11/keysymdef.h>
00066 # include <kdebug.h>
00067 
00068 
00069 # include <config.h>
00070 # ifdef HAVE_UNISTD_H
00071 #  include <unistd.h>
00072 #  ifdef HAVE_USLEEP
00073 #   define USLEEP(x) usleep(x)
00074 #  else
00075 #   define USLEEP(x) sleep(0)
00076 #  endif
00077 # else
00078 #  define USLEEP(x) sleep(0)
00079 # endif
00080 
00081 # include "qxembed.h"
00082 
00083 
00084 # ifndef XK_ISO_Left_Tab
00085 #  define XK_ISO_Left_Tab 0xFE20
00086 # endif
00087 
00088 
00089 const int XFocusOut = FocusOut;
00090 const int XFocusIn = FocusIn;
00091 const int XKeyPress = KeyPress;
00092 const int XKeyRelease = KeyRelease;
00093 # undef KeyRelease
00094 # undef KeyPress
00095 # undef FocusOut
00096 # undef FocusIn
00097 
00098 
00099 extern Atom qt_wm_protocols;
00100 extern Atom qt_wm_delete_window;
00101 extern Atom qt_wm_take_focus;
00102 extern Atom qt_wm_state;
00103 extern Time qt_x_time;
00104 
00105 
00106 static Atom xembed = 0;
00107 static Atom context_help = 0;
00108 
00109 
00110 #define XEMBED_EMBEDDED_NOTIFY          0
00111 #define XEMBED_WINDOW_ACTIVATE          1
00112 #define XEMBED_WINDOW_DEACTIVATE        2
00113 #define XEMBED_REQUEST_FOCUS            3
00114 #define XEMBED_FOCUS_IN                 4
00115 #define XEMBED_FOCUS_OUT                5
00116 #define XEMBED_FOCUS_NEXT               6
00117 #define XEMBED_FOCUS_PREV               7
00118 
00119 
00120 
00121 #define XEMBED_FOCUS_CURRENT            0
00122 #define XEMBED_FOCUS_FIRST              1
00123 #define XEMBED_FOCUS_LAST               2
00124 
00125 
00126 
00127 
00128 class QXEmbedData
00129 {
00130 public:
00131     QXEmbedData(){ 
00132         autoDelete = true;
00133         xplain = false;
00134         xgrab = false;
00135         mapAfterRelease = false;
00136         lastPos = QPoint(0,0);
00137     }
00138     ~QXEmbedData(){};
00139 
00140     bool autoDelete;      
00141     bool xplain;          
00142     bool xgrab;           
00143     bool mapAfterRelease;
00144     QWidget* focusProxy;  
00145     QPoint lastPos;       
00146 };
00147 
00148 namespace
00149 {
00150     
00151     
00152     class QXEmbedAppFilter : public QObject
00153     {
00154     public:
00155         QXEmbedAppFilter()  { qApp->installEventFilter( this ); } 
00156         ~QXEmbedAppFilter() { };
00157         bool eventFilter( QObject *, QEvent * );
00158     };
00159 }
00160 
00161 
00162 static QXEmbedAppFilter* filter = 0;
00163 
00164 static QPtrDict<QGuardedPtr<QWidget> > *focusMap = 0;
00165 
00166 static XKeyEvent last_key_event;
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 class QPublicWidget : public QWidget
00177 {
00178 public:
00179     QTLWExtra* topData() { return QWidget::topData(); }
00180     QFocusData *focusData(){ return QWidget::focusData(); }
00181     bool focusNextPrev(bool b) { return focusNextPrevChild(b); }
00182 };
00183 
00184 
00185 
00186 typedef int (*QX11EventFilter) (XEvent*);
00187 extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter);
00188 static QX11EventFilter oldFilter = 0;
00189 
00190 
00191 
00192 static void sendXEmbedMessage( WId window, long message, long detail = 0,
00193                                long data1 = 0, long data2 = 0)
00194 {
00195     if (!window) return;
00196     XEvent ev;
00197     memset(&ev, 0, sizeof(ev));
00198     ev.xclient.type = ClientMessage;
00199     ev.xclient.window = window;
00200     ev.xclient.message_type = xembed;
00201     ev.xclient.format = 32;
00202     ev.xclient.data.l[0] = qt_x_time;
00203     ev.xclient.data.l[1] = message;
00204     ev.xclient.data.l[2] = detail;
00205     ev.xclient.data.l[3] = data1;
00206     ev.xclient.data.l[4] = data2;
00207     XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev);
00208 }
00209 
00210 
00211 
00212 static void sendClientMessage(Window window, Atom a, long x)
00213 {
00214   if (!window) return;
00215   XEvent ev;
00216   memset(&ev, 0, sizeof(ev));
00217   ev.xclient.type = ClientMessage;
00218   ev.xclient.window = window;
00219   ev.xclient.message_type = a;
00220   ev.xclient.format = 32;
00221   ev.xclient.data.l[0] = x;
00222   ev.xclient.data.l[1] = qt_x_time;
00223   XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev);
00224 }
00225 
00226 
00227 
00228 static void sendFocusMessage(Window window, int type, int mode, int detail)
00229 {
00230   if (!window) return;
00231   XEvent ev;
00232   memset(&ev, 0, sizeof(ev));
00233   ev.xfocus.type = type;
00234   ev.xfocus.window = window;
00235   ev.xfocus.mode = mode;
00236   ev.xfocus.detail = detail;
00237   XSendEvent(qt_xdisplay(), window, false, FocusChangeMask, &ev);
00238 }
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 bool QXEmbedAppFilter::eventFilter( QObject *o, QEvent * e)
00300 {
00301     static bool obeyFocus = false;
00302     switch ( e->type() ) {
00303     case QEvent::MouseButtonPress:
00304         
00305         if ( !((QWidget*)o)->isActiveWindow() )
00306             obeyFocus = true;
00307         break;
00308     case QEvent::FocusIn:
00309         
00310         
00311         
00312         
00313         if ( qApp->focusWidget() == o &&
00314              ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
00315             QFocusEvent* fe = (QFocusEvent*) e;
00316             if ( obeyFocus || fe->reason() == QFocusEvent::Mouse ||
00317                  fe->reason() == QFocusEvent::Shortcut ) {
00318                 
00319                 
00320                 
00321                 
00322                 WId window = ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->parentWinId;
00323                 focusMap->remove( qApp->focusWidget()->topLevelWidget() );
00324                 sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
00325             } else if ( fe->reason() == QFocusEvent::ActiveWindow ) {
00326                 
00327                 
00328                 
00329                 
00330                 
00331                 focusMap->remove( qApp->focusWidget()->topLevelWidget() );
00332                 focusMap->insert( qApp->focusWidget()->topLevelWidget(),
00333                                   new QGuardedPtr<QWidget>(qApp->focusWidget()->topLevelWidget()->focusWidget() ) );
00334                 
00335                 
00336                 qApp->focusWidget()->clearFocus();
00337                 
00338             }
00339             obeyFocus = false;
00340         }
00341         break;
00342     case QEvent::KeyPress: 
00343         if (qApp->focusWidget() == o &&
00344             ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
00345             
00346             
00347             
00348             
00349             
00350             
00351             
00352             
00353             
00354             
00355             
00356             
00357             QKeyEvent *k = (QKeyEvent *)e;
00358             QWidget *w = qApp->focusWidget();
00359             
00360             bool res = false;
00361             bool tabForward = true;
00362             if ( !(k->state() & ControlButton || k->state() & AltButton) ) {
00363                 if ( k->key() == Key_Backtab || (k->key() == Key_Tab && (k->state() & ShiftButton)) ) {
00364                     QFocusEvent::setReason( QFocusEvent::Backtab );
00365                     res = ((QPublicWidget*)w)->focusNextPrev( tabForward = false );
00366                     QFocusEvent::resetReason();
00367                 } else if ( k->key() == Key_Tab ) {
00368                     QFocusEvent::setReason( QFocusEvent::Tab );
00369                     res = ((QPublicWidget*)w)->focusNextPrev( tabForward = true );
00370                     QFocusEvent::resetReason();
00371                 }
00372             }
00373             if (res) {
00374                 
00375                 
00376                 QFocusData *fd = ((QPublicWidget*)w)->focusData();
00377                 WId window = ((QPublicWidget*)w->topLevelWidget())->topData()->parentWinId;
00378                 QWidget *cw = 0;
00379                 QWidget *fw = fd->home();
00380                 if (tabForward && window) {
00381                     while (cw != w && cw != fw && cw != w->topLevelWidget()) 
00382                         cw = fd->prev();
00383                     if (cw != w)
00384                         sendXEmbedMessage( window, XEMBED_FOCUS_NEXT );
00385                 } else if (window) {
00386                     while (cw != w && cw != fw && cw != w->topLevelWidget()) 
00387                         cw = fd->next();
00388                     if (cw != w)
00389                         sendXEmbedMessage( window, XEMBED_FOCUS_PREV );
00390                 }
00391                 
00392                 return true;
00393             }
00394         }
00395         break;
00396     default:
00397         break;
00398     }
00399     
00400     return false;
00401 }
00402 
00403 
00404 
00405 static int qxembed_x11_event_filter( XEvent* e)
00406 {
00407     switch ( e->type ) {
00408     case XKeyPress:
00409     case XKeyRelease: {
00410         
00411         last_key_event = e->xkey;
00412         break;
00413     }
00414     case ClientMessage:
00415         if ( e->xclient.message_type == xembed ) {
00416             
00417             
00418             Time msgtime = (Time) e->xclient.data.l[0];
00419             long message = e->xclient.data.l[1];
00420             long detail = e->xclient.data.l[2];
00421             
00422             if ( msgtime > qt_x_time )
00423                 qt_x_time = msgtime;
00424             QWidget* w = QWidget::find( e->xclient.window );
00425             if ( !w )
00426                 break;
00427             switch ( message) {
00428             case XEMBED_EMBEDDED_NOTIFY: {
00429                 
00430                 QTLWExtra *extra = ((QPublicWidget*)w->topLevelWidget())->topData();
00431                 extra->embedded = 1;
00432                 extra->parentWinId = e->xclient.data.l[3];
00433                 w->topLevelWidget()->show();
00434                 break;
00435             }
00436             case XEMBED_WINDOW_ACTIVATE: {
00437                 
00438                 
00439                 
00440                 
00441                 
00442                 XEvent ev;
00443                 memset(&ev, 0, sizeof(ev));
00444                 ev.xfocus.display = qt_xdisplay();
00445                 ev.xfocus.type = XFocusIn;
00446                 ev.xfocus.window = w->topLevelWidget()->winId();
00447                 ev.xfocus.mode = NotifyNormal;
00448                 ev.xfocus.detail = NotifyAncestor;
00449                 qApp->x11ProcessEvent( &ev );
00450             }
00451             break;
00452             case XEMBED_WINDOW_DEACTIVATE: {
00453                 
00454                 
00455                 
00456                 XEvent ev;
00457                 memset(&ev, 0, sizeof(ev));
00458                 ev.xfocus.display = qt_xdisplay();
00459                 ev.xfocus.type = XFocusOut;
00460                 ev.xfocus.window = w->topLevelWidget()->winId();
00461                 ev.xfocus.mode = NotifyNormal;
00462                 ev.xfocus.detail = NotifyAncestor;
00463                 qApp->x11ProcessEvent( &ev );
00464             }
00465             break;
00466             case XEMBED_FOCUS_IN:
00467                 
00468                 {
00469                     
00470                     QWidget* focusCurrent = 0;
00471                     QGuardedPtr<QWidget>* fw = focusMap->find( w->topLevelWidget() );
00472                     if ( fw ) {
00473                         focusCurrent = *fw;
00474                         
00475                         focusMap->remove( w->topLevelWidget() );
00476                     }
00477                     switch ( detail ) {
00478                     case XEMBED_FOCUS_CURRENT:
00479                         
00480                         if ( focusCurrent )
00481                             focusCurrent->setFocus();
00482                         else if ( !w->topLevelWidget()->focusWidget() )
00483                             w->topLevelWidget()->setFocus();
00484                         break;
00485                     case XEMBED_FOCUS_FIRST:
00486                         {
00487                             
00488                             QFocusEvent::setReason( QFocusEvent::Tab );
00489                             w->topLevelWidget()->setFocus();
00490                             ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(true);
00491                             QFocusEvent::resetReason();
00492                         }
00493                         break;
00494                     case XEMBED_FOCUS_LAST:
00495                         {
00496                             
00497                             QFocusEvent::setReason( QFocusEvent::Backtab );
00498                             w->topLevelWidget()->setFocus();
00499                             ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(false);
00500                             QFocusEvent::resetReason();
00501                         }
00502                         break;
00503                     default:
00504                         break;
00505                     }
00506                 }
00507                 break;
00508             case XEMBED_FOCUS_OUT:
00509                 
00510                 
00511                 
00512                 if ( w->topLevelWidget()->focusWidget() ) {
00513                     focusMap->insert( w->topLevelWidget(),
00514                         new QGuardedPtr<QWidget>(w->topLevelWidget()->focusWidget() ) );
00515                     w->topLevelWidget()->focusWidget()->clearFocus();
00516                 }
00517             break;
00518             default:
00519                 break;
00520             }
00521         } else if ( e->xclient.format == 32 && e->xclient.message_type ) {
00522             if ( e->xclient.message_type == qt_wm_protocols ) {
00523                 QWidget* w = QWidget::find( e->xclient.window );
00524                 if ( !w )
00525                     break;
00526                 
00527                 
00528                 
00529                 
00530                 
00531                 
00532                 
00533                 Atom a = e->xclient.data.l[0];
00534                 if ( a == qt_wm_take_focus ) {
00535                     
00536                     if ( (ulong) e->xclient.data.l[1] > qt_x_time )
00537                         qt_x_time = e->xclient.data.l[1];
00538                     
00539                     
00540                     
00541                     
00542                     if ( w->isActiveWindow() ) {
00543                         QEvent e( QEvent::WindowActivate );
00544                         QApplication::sendEvent( w, &e );
00545                     }
00546                 }
00547             }
00548         }
00549         break;
00550     default:
00551         break;
00552     }
00553     
00554     if ( oldFilter )
00555         return oldFilter( e );
00556     
00557     return false;
00558 }
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 void QXEmbed::initialize()
00568 {
00569     static bool is_initialized = false;
00570     if ( is_initialized )
00571         return;
00572 
00573     
00574     xembed = XInternAtom( qt_xdisplay(), "_XEMBED", false );
00575     
00576     oldFilter = qt_set_x11_event_filter( qxembed_x11_event_filter );
00577     
00578     focusMap = new QPtrDict<QGuardedPtr<QWidget> >;
00579     focusMap->setAutoDelete( true );
00580     
00581     filter = new QXEmbedAppFilter;
00582 
00583     is_initialized = true;
00584 }
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 QXEmbed::QXEmbed(QWidget *parent, const char *name, WFlags f)
00608   : QWidget(parent, name, f)
00609 {
00610     
00611     d = new QXEmbedData;
00612     
00613     
00614     
00615     
00616     
00617     
00618     d->focusProxy = new QWidget( this, "xembed_focus" );
00619     d->focusProxy->setGeometry( -1, -1, 1, 1 );
00620     
00621     
00622     
00623     initialize();
00624     window = 0;
00625     setFocusPolicy(StrongFocus);
00626     setKeyCompression( false );
00627 
00628     
00629     (void) topData();
00630 
00631     
00632     
00633     
00634     XSelectInput(qt_xdisplay(), winId(),
00635                  KeyPressMask | KeyReleaseMask |
00636                  ButtonPressMask | ButtonReleaseMask |
00637                  KeymapStateMask |
00638                  ButtonMotionMask |
00639                  PointerMotionMask | 
00640                  EnterWindowMask | LeaveWindowMask |
00641                  FocusChangeMask |
00642                  ExposureMask |
00643                  StructureNotifyMask |
00644                  SubstructureRedirectMask |
00645                  SubstructureNotifyMask
00646                  );
00647     
00648     
00649     
00650     topLevelWidget()->installEventFilter( this );
00651     qApp->installEventFilter( this );
00652 
00653     
00654     
00655     if ( qApp->activeWindow() == topLevelWidget() )
00656         if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
00657             XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
00658                             RevertToParent, qt_x_time );
00659     
00660     setAcceptDrops( true );
00661 }
00662 
00663 
00664 QXEmbed::~QXEmbed()
00665 {
00666     
00667     if ( d && d->xgrab)
00668         XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
00669     if ( window && ( autoDelete() || !d->xplain ))
00670         {
00671             
00672             
00673             
00674 #if 0
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 #else
00686             if( autoDelete())
00687                 XUnmapWindow( qt_xdisplay(), window );
00688 #endif
00689             XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0);
00690             if( !d->xplain )
00691                 XRemoveFromSaveSet( qt_xdisplay(), window );
00692             if( d->mapAfterRelease )
00693                 XMapWindow( qt_xdisplay(), window );
00694             XSync(qt_xdisplay(), false);
00695             
00696             if( autoDelete()  ) 
00697                 
00698                 
00699                 
00700                 
00701                 sendDelete();
00702       }
00703     window = 0;
00704     
00705     
00706     Window focus;
00707     int revert;
00708     XGetInputFocus( qt_xdisplay(), &focus, &revert );
00709     if( focus == d->focusProxy->winId())
00710         XSetInputFocus( qt_xdisplay(), topLevelWidget()->winId(), RevertToParent, qt_x_time );
00711     
00712     delete d;
00713 }
00714 
00715 
00716 
00717 
00718 
00719 void QXEmbed::sendDelete( void )
00720 {
00721   if (window)
00722     {
00723       sendClientMessage(window, qt_wm_protocols, qt_wm_delete_window);
00724       XFlush( qt_xdisplay() );
00725     }
00726 }
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 void QXEmbed::setProtocol( Protocol proto )
00736 {
00737     if (window == 0) {
00738         d->xplain = false;
00739         if (proto == XPLAIN)
00740             d->xplain = true;
00741     }
00742 }
00743 
00744 
00745 QXEmbed::Protocol QXEmbed::protocol()
00746 {
00747   if (d->xplain)
00748     return XPLAIN;
00749   return XEMBED;
00750 }
00751 
00752 
00753 
00754 void QXEmbed::resizeEvent(QResizeEvent*)
00755 {
00756     if (window != 0)
00757         XResizeWindow(qt_xdisplay(), window, width(), height());
00758 }
00759 
00760 
00761 void QXEmbed::showEvent(QShowEvent*)
00762 {
00763     if (window != 0)
00764         XMapRaised(qt_xdisplay(), window);
00765 }
00766 
00767 
00768 
00769 bool QXEmbed::eventFilter( QObject *o, QEvent * e)
00770 {
00771 
00772     switch ( e->type() ) {
00773     case QEvent::WindowActivate:
00774         if ( o == topLevelWidget() ) {
00775             
00776             
00777             if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
00778                 if (! hasFocus() )
00779                     XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
00780                                     RevertToParent, qt_x_time );
00781             if (d->xplain)
00782                 
00783                 checkGrab();
00784             else
00785                 
00786                 sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE );
00787         }
00788         break;
00789     case QEvent::WindowDeactivate:
00790         if ( o == topLevelWidget() ) {
00791             if (d->xplain)
00792                 
00793                 checkGrab();
00794             else
00795                 
00796                 sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE );
00797         }
00798         break;
00799     case QEvent::Move:
00800         {
00801             QWidget* pos = this;
00802             while( pos != o && pos != topLevelWidget())
00803                 pos = pos->parentWidget();
00804             if( pos == o ) {
00805                 
00806                 
00807                 QPoint globalPos = mapToGlobal(QPoint(0,0));
00808                 if (globalPos != d->lastPos) {
00809                     d->lastPos = globalPos;
00810                     sendSyntheticConfigureNotifyEvent();
00811                 }
00812             }
00813         }                    
00814         break;
00815     default:
00816         break;
00817    }
00818    return false;
00819 }
00820 
00821 
00822 bool  QXEmbed::event( QEvent * e)
00823 {
00824     return QWidget::event( e );
00825 }
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 void QXEmbed::keyPressEvent( QKeyEvent *)
00834 {
00835     if (!window)
00836         return;
00837     last_key_event.window = window;
00838     XSendEvent(qt_xdisplay(), window, false, KeyPressMask, (XEvent*)&last_key_event);
00839 
00840 }
00841 
00842 
00843 
00844 void QXEmbed::keyReleaseEvent( QKeyEvent *)
00845 {
00846     if (!window)
00847         return;
00848     last_key_event.window = window;
00849     XSendEvent(qt_xdisplay(), window, false, KeyReleaseMask, (XEvent*)&last_key_event);
00850 }
00851 
00852 
00853 void QXEmbed::focusInEvent( QFocusEvent * e ){
00854     if (!window)
00855         return;
00856     
00857     
00858     if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
00859       if ( qApp->activeWindow() == topLevelWidget() )
00860           
00861           
00862           
00863           XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
00864                           RevertToParent, qt_x_time );
00865     if (d->xplain) {
00866         
00867         checkGrab();
00868         
00869         
00870         
00871         sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
00872     } else {
00873         
00874         
00875         int detail = XEMBED_FOCUS_CURRENT;
00876         
00877         
00878         
00879         if ( e->reason() == QFocusEvent::Tab )
00880             detail = XEMBED_FOCUS_FIRST;
00881         else if ( e->reason() == QFocusEvent::Backtab )
00882             detail = XEMBED_FOCUS_LAST;
00883         sendXEmbedMessage( window, XEMBED_FOCUS_IN, detail);
00884     }
00885 }
00886 
00887 
00888 void QXEmbed::focusOutEvent( QFocusEvent * ){
00889     if (!window)
00890         return;
00891     if (d->xplain) {
00892         
00893         checkGrab();
00894         
00895         sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer );
00896     } else {
00897         
00898         sendXEmbedMessage( window, XEMBED_FOCUS_OUT );
00899     }
00900     
00901     
00902     
00903     
00904     
00905     
00906     
00907     if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
00908         if ( qApp->activeWindow() == topLevelWidget() )
00909             
00910             
00911             
00912             
00913             XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
00914                             RevertToParent, qt_x_time );
00915 }
00916 
00917 
00918 
00919 
00920 static bool wstate_withdrawn( WId winid )
00921 {
00922     Atom type;
00923     int format;
00924     unsigned long length, after;
00925     unsigned char *data;
00926     int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
00927                                 false, AnyPropertyType, &type, &format,
00928                                 &length, &after, &data );
00929     bool withdrawn = true;
00930     
00931     
00932     if ( r == Success && data && format == 32 ) {
00933         Q_UINT32 *wstate = (Q_UINT32*)data;
00934         withdrawn  = (*wstate == WithdrawnState );
00935         XFree( (char *)data );
00936     }
00937     return withdrawn;
00938 }
00939 
00940 
00941 
00942 static int get_parent(WId winid, Window *out_parent)
00943 {
00944     Window root, *children=0;
00945     unsigned int nchildren;
00946     int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
00947     if (st && children) 
00948         XFree(children);
00949     return st;
00950 }
00951 
00952 
00953 
00954 void QXEmbed::embed(WId w)
00955 {
00956     kdDebug() << "*** Embed " << w << " into " << winId() << ". window=" << window << endl;
00957     if (!w)
00958         return;
00959     
00960     
00961     bool has_window =  (w == window);
00962     window = w;
00963     if ( !has_window ) {
00964         
00965         
00966         
00967         if ( !wstate_withdrawn(window) ) {
00968             XWithdrawWindow(qt_xdisplay(), window, qt_xscreen());
00969             QApplication::flushX();
00970             
00971             while (!wstate_withdrawn(window))
00972                 USLEEP(1000);
00973         }
00974         
00975         
00976         
00977         
00978         Window parent;
00979         get_parent(w, &parent);
00980         kdDebug() << QString("> before reparent: parent=0x%1").arg(parent,0,16) << endl;
00981         for (int i = 0; i < 50; i++) {
00982             Window parent = 0;
00983             
00984             
00985             if( !d->xplain )
00986                 XAddToSaveSet( qt_xdisplay(), w );
00987             XReparentWindow(qt_xdisplay(), w, winId(), 0, 0);
00988             if (get_parent(w, &parent) && parent == winId()) {
00989                kdDebug() << QString("> Loop %1: ").arg(i)
00990                          << QString("> reparent of 0x%1").arg(w,0,16)
00991                          << QString(" into 0x%1").arg(winId(),0,16)
00992                          << QString(" successful") << endl;
00993                 break;
00994             }
00995             kdDebug() << QString("> Loop %1: ").arg(i)
00996                       << QString("> reparent of 0x%1").arg(w,0,16)
00997                       << QString(" into 0x%1").arg(winId(),0,16)
00998                       << QString(" failed") << endl;
00999             USLEEP(1000);
01000         }
01001     }
01002 }
01003 
01004 
01005 
01006 WId QXEmbed::embeddedWinId() const
01007 {
01008     return window;
01009 }
01010 
01011 
01012 
01013 
01014 bool QXEmbed::focusNextPrevChild( bool next )
01015 {
01016     if ( window )
01017         
01018         
01019         
01020         
01021         
01022         
01023         return false;
01024     else
01025         
01026         return QWidget::focusNextPrevChild( next );
01027 }
01028 
01029 
01030 
01031 bool QXEmbed::x11Event( XEvent* e)
01032 {
01033     switch ( e->type ) {
01034     case DestroyNotify:
01035         if ( e->xdestroywindow.window == window ) {
01036             
01037             window = 0;
01038             windowChanged( window );
01039             emit embeddedWindowDestroyed();
01040         }
01041         break;
01042     case ReparentNotify:
01043         if ( e->xreparent.window == d->focusProxy->winId() )
01044             break; 
01045         if ( window && e->xreparent.window == window &&
01046              e->xreparent.parent != winId() ) {
01047             
01048             window = 0;
01049             windowChanged( window );
01050             
01051             
01052             
01053             if( !d->xplain )
01054                 XRemoveFromSaveSet( qt_xdisplay(), window );
01055         } else if ( e->xreparent.parent == winId()){
01056             
01057             window = e->xreparent.window;
01058             
01059             
01060             if( !d->xplain )
01061                 XAddToSaveSet( qt_xdisplay(), window );
01062             XResizeWindow(qt_xdisplay(), window, width(), height());
01063             XMapRaised(qt_xdisplay(), window);
01064             
01065             sendSyntheticConfigureNotifyEvent();
01066             
01067             extraData()->xDndProxy = window;
01068             if ( parent() ) {
01069                 
01070                 
01071                 QEvent * layoutHint = new QEvent( QEvent::LayoutHint );
01072                 QApplication::postEvent( parent(), layoutHint );
01073             }
01074             windowChanged( window );
01075             if (d->xplain) {
01076                 
01077                 checkGrab();
01078                 if ( hasFocus() )
01079                     
01080                     sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
01081             } else {
01082                 
01083                 sendXEmbedMessage( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
01084                 if (isActiveWindow())
01085                     sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE);
01086                 else
01087                     sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE);
01088                 if ( hasFocus() )
01089                     sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT );
01090             }
01091         }
01092         break;
01093     case ButtonPress:
01094         if (d->xplain && d->xgrab) {
01095             
01096             
01097             QFocusEvent::setReason( QFocusEvent::Mouse );
01098             setFocus();
01099             QFocusEvent::resetReason();
01100             
01101             XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime);
01102             
01103             return true;
01104         }
01105         break;
01106     case ButtonRelease:
01107         if (d->xplain && d->xgrab) {
01108             
01109             XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime);
01110             return true;
01111         }
01112         break;
01113     case MapRequest:
01114         
01115         if ( window && e->xmaprequest.window == window )
01116             XMapRaised(qt_xdisplay(), window );
01117         break;
01118     case ClientMessage:
01119         
01120         
01121         if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
01122             long message = e->xclient.data.l[1];
01123             switch ( message ) {
01124                 
01125                 
01126                 
01127             case XEMBED_FOCUS_NEXT:
01128                 QWidget::focusNextPrevChild( true );
01129                 break;
01130             case XEMBED_FOCUS_PREV:
01131                 QWidget::focusNextPrevChild( false );
01132                 break;
01133                 
01134             case XEMBED_REQUEST_FOCUS:
01135                 QFocusEvent::setReason( QFocusEvent::Mouse );
01136                 setFocus();
01137                 QFocusEvent::resetReason();
01138                 break;
01139             default:
01140                 break;
01141             }
01142         }
01143     break;
01144 
01145     case ConfigureRequest:
01146         
01147         
01148         if (e->xconfigurerequest.window == window) 
01149         {
01150              sendSyntheticConfigureNotifyEvent();
01151         }
01152         break;
01153     case MotionNotify: 
01154     
01155     case EnterNotify:
01156         
01157         if ( QWhatsThis::inWhatsThisMode() )
01158             enterWhatsThisMode();
01159         break;
01160     default:
01161         break;
01162     }
01163     return false;
01164 }
01165 
01166 
01167 
01168 
01169 void QXEmbed::enterWhatsThisMode()
01170 {
01171     
01172     
01173     
01174     
01175     QWhatsThis::leaveWhatsThisMode();
01176     if ( !context_help )
01177         context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", false );
01178     sendClientMessage(window , qt_wm_protocols, context_help );
01179 }
01180 
01181 
01182 
01183 void QXEmbed::windowChanged( WId )
01184 {
01185 }
01186 
01187 
01188 
01189 
01190 bool QXEmbed::processClientCmdline( QWidget* client, int& argc, char ** argv )
01191 {
01192     int myargc = argc;
01193     WId window = 0;
01194     int i, j;
01195 
01196     j = 1;
01197     for ( i=1; i<myargc; i++ ) {
01198         if ( argv[i] && *argv[i] != '-' ) {
01199             argv[j++] = argv[i];
01200             continue;
01201         }
01202         QCString arg = argv[i];
01203         if ( strcmp(arg,"-embed") == 0 && i < myargc-1 ) {
01204             QCString s = argv[++i];
01205             window = s.toInt();
01206         } else
01207             argv[j++] = argv[i];
01208     }
01209     argc = j;
01210 
01211     if ( window != 0 ) {
01212         embedClientIntoWindow( client, window );
01213         return true;
01214     }
01215 
01216     return false;
01217 }
01218 
01219 
01220 
01221 
01222 void QXEmbed::embedClientIntoWindow(QWidget* client, WId window)
01223 {
01224     initialize();
01225     XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0);
01226     
01227     ((QXEmbed*)client)->topData()->embedded = true;
01228     ((QXEmbed*)client)->topData()->parentWinId = window;
01229     
01230     
01231     client->show();
01232 }
01233 
01234 
01235 
01236 
01237 
01238 QSizePolicy QXEmbed::sizePolicy() const
01239 {
01240     return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
01241 }
01242 
01243 
01244 
01245 QSize QXEmbed::sizeHint() const
01246 {
01247     return minimumSizeHint();
01248 }
01249 
01250 
01251 QSize QXEmbed::minimumSizeHint() const
01252 {
01253     int minw = 0;
01254     int minh = 0;
01255     if ( window ) {
01256         XSizeHints size;
01257         long msize;
01258         if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize)
01259             && ( size.flags & PMinSize) ) {
01260             minw = size.min_width;
01261             minh = size.min_height;
01262         }
01263     }
01264 
01265     return QSize( minw, minh );
01266 }
01267 
01268 
01269 
01270 void QXEmbed::setAutoDelete( bool b)
01271 {
01272     d->autoDelete = b;
01273 }
01274 
01275 
01276 bool QXEmbed::autoDelete() const
01277 {
01278     return d->autoDelete;
01279 }
01280 
01281 
01282 bool QXEmbed::customWhatsThis() const
01283 {
01284     return true;
01285 }
01286 
01287 
01288 
01289 
01290 
01291 
01292 void QXEmbed::checkGrab() 
01293 {
01294     if (d->xplain && isActiveWindow() && !hasFocus()) {
01295         if (! d->xgrab)
01296             XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(),
01297                         false, ButtonPressMask, GrabModeSync, GrabModeAsync,
01298                         None, None );
01299         d->xgrab = true;
01300     } else {
01301         if (d->xgrab)
01302             XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
01303         d->xgrab = false;
01304     }
01305 }
01306 
01307 
01308 
01309 void QXEmbed::sendSyntheticConfigureNotifyEvent() 
01310 {
01311     
01312     
01313     
01314     
01315     
01316     
01317     QPoint globalPos = mapToGlobal(QPoint(0,0));
01318     if (window) {
01319         XConfigureEvent c;
01320         memset(&c, 0, sizeof(c));
01321         c.type = ConfigureNotify;
01322         c.display = qt_xdisplay();
01323         c.send_event = True;
01324         c.event = window;
01325         c.window = winId();
01326         c.x = globalPos.x();
01327         c.y = globalPos.y();
01328         c.width = width();
01329         c.height = height();
01330         c.border_width = 0;
01331         c.above = None;
01332         c.override_redirect = 0;
01333         XSendEvent( qt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c );
01334     }
01335 }
01336 
01337 
01338 void QXEmbed::reparent( QWidget * parent, WFlags f, const QPoint & p, bool showIt )
01339 {
01340     
01341     
01342     
01343     
01344     Q_ASSERT( window == 0 );
01345     QWidget::reparent( parent, f, p, showIt );
01346 }
01347 
01348 
01349 #include "qxembed.moc"
01350 #endif // Q_WS_X11