qxembed.cpp Source File (kdeui Library)

| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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         xplain = FALSE;
    00101         xgrab = FALSE;
    00102         lastPos = QPoint(0,0);
    00103     }
    00104     ~QXEmbedData(){};
    00105
    00106
    00107     bool autoDelete;
    00108     bool xplain;
    00109     bool xgrab;
    00110     QWidget* focusProxy;
    00111     QPoint lastPos;
    00112 };
    00113
    00114 class QXEmbedAppFilter : public QObject
    00115 {
    00116 public:
    00117     QXEmbedAppFilter(){ qApp->installEventFilter( this ); }
    00118     ~QXEmbedAppFilter(){};
    00119     bool eventFilter( QObject *, QEvent * );
    00120 };
    00121
    00122
    00123 static QXEmbedAppFilter* filter = 0;
    00124 static QPtrDict<QGuardedPtr<QWidget> > *focusMap = 0;
    00125
    00126 static XKeyEvent last_key_event;
    00127 static bool tabForward = TRUE;
    00128
    00129
    00130 class QPublicWidget : public QWidget
    00131 {
    00132 public:
    00133     QTLWExtra* topData() { return QWidget::topData(); };
    00134     QFocusData *focusData(){ return QWidget::focusData(); };
    00135 };
    00136
    00137 typedef int (*QX11EventFilter) (XEvent*);
    00138 extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter);
    00139 static QX11EventFilter oldFilter = 0;
    00140
    00141
    00142 static void send_xembed_message( WId window, long message, long detail = 0,
    00143                                  long data1 = 0, long data2 = 0)
    00144 {
    00145     if (!window) return;
    00146     XEvent ev;
    00147     memset(&ev, 0, sizeof(ev));
    00148     ev.xclient.type = ClientMessage;
    00149     ev.xclient.window = window;
    00150     ev.xclient.message_type = xembed;
    00151     ev.xclient.format = 32;
    00152     ev.xclient.data.l[0] = qt_x_time;
    00153     ev.xclient.data.l[1] = message;
    00154     ev.xclient.data.l[2] = detail;
    00155     ev.xclient.data.l[3] = data1;
    00156     ev.xclient.data.l[4] = data2;
    00157     XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev);
    00158 }
    00159
    00160 static void sendClientMessage(Window window, Atom a, long x)
    00161 {
    00162   if (!window) return;
    00163   XEvent ev;
    00164   memset(&ev, 0, sizeof(ev));
    00165   ev.xclient.type = ClientMessage;
    00166   ev.xclient.window = window;
    00167   ev.xclient.message_type = a;
    00168   ev.xclient.format = 32;
    00169   ev.xclient.data.l[0] = x;
    00170   ev.xclient.data.l[1] = qt_x_time;
    00171   XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev);
    00172 }
    00173
    00174 static void sendFocusMessage(Window window, int type, int mode, int detail)
    00175 {
    00176   if (!window) return;
    00177   XEvent ev;
    00178   memset(&ev, 0, sizeof(ev));
    00179   ev.xfocus.type = type;
    00180   ev.xfocus.window = window;
    00181   ev.xfocus.mode = mode;
    00182   ev.xfocus.detail = detail;
    00183   XSendEvent(qt_xdisplay(), window, FALSE, FocusChangeMask, &ev);
    00184 }
    00185
    00186
    00187 bool QXEmbedAppFilter::eventFilter( QObject *o, QEvent * e)
    00188 {
    00189     static bool obeyFocus = FALSE;
    00190     switch ( e->type() ) {
    00191     case QEvent::MouseButtonPress:
    00192         if ( !((QWidget*)o)->isActiveWindow() )
    00193             obeyFocus = TRUE;
    00194         break;
    00195     case QEvent::FocusIn:
    00196         if ( qApp->focusWidget() == o &&
    00197              ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
    00198             QFocusEvent* fe = (QFocusEvent*) e;
    00199
    00200             if ( obeyFocus || fe->reason() == QFocusEvent::Mouse ||
    00201                  fe->reason() == QFocusEvent::Shortcut ) {
    00202                 WId window = ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->parentWinId;
    00203                 focusMap->remove( qApp->focusWidget()->topLevelWidget() );
    00204                 send_xembed_message( window, XEMBED_REQUEST_FOCUS );
    00205             } else if ( fe->reason() == QFocusEvent::ActiveWindow ) {
    00206                 focusMap->remove( qApp->focusWidget()->topLevelWidget() );
    00207                 focusMap->insert( qApp->focusWidget()->topLevelWidget(),
    00208                                   new QGuardedPtr<QWidget>(qApp->focusWidget()->topLevelWidget()->focusWidget() ) );
    00209                 qApp->focusWidget()->clearFocus();
    00210             }
    00211             obeyFocus = FALSE;
    00212         }
    00213         break;
    00214     default:
    00215         break;
    00216     }
    00217     return FALSE;
    00218 }
    00219
    00220
    00221 static int qxembed_x11_event_filter( XEvent* e)
    00222 {
    00223     //kdDebug() << "qxembed_x11_event_filter " << KXEventUtil::getX11EventInfo(e) << endl;
    00224
    00225     switch ( e->type ) {
    00226     case XKeyPress: {
    00227         int kc = XKeycodeToKeysym(qt_xdisplay(), e->xkey.keycode, 0);
    00228         if ( kc == XK_Tab || kc == XK_ISO_Left_Tab ) {
    00229             tabForward = (e->xkey.state & ShiftMask) == 0;
    00230             QWidget* w = QWidget::find( e->xkey.window );
    00231             if ( w && w->isActiveWindow() && qApp->focusWidget() &&
    00232                  qApp->focusWidget()->topLevelWidget() == w->topLevelWidget() &&
    00233                  ((QPublicWidget*)w->topLevelWidget())->topData()->embedded ) {
    00234                 WId window = ((QPublicWidget*)w->topLevelWidget())->topData()->parentWinId;
    00235                 QFocusData *fd = ((QPublicWidget*)w)->focusData();
    00236                 while ( fd->next() != w->topLevelWidget() )
    00237                     ;
    00238                 QWidget* first = fd->next();
    00239                 QWidget* last = fd->prev(); last = fd->prev();
    00240                 if ( !tabForward && fd->focusWidget() == first ) {
    00241                     send_xembed_message( window, XEMBED_FOCUS_PREV );
    00242                     return TRUE;
    00243                 } else if ( tabForward && fd->focusWidget() == last ) {
    00244                     send_xembed_message( window, XEMBED_FOCUS_NEXT );
    00245                     return TRUE;
    00246                 }
    00247             }
    00248         } else
    00249             last_key_event = e->xkey;
    00250     }
    00251     // FALL THROUGH
    00252     case XKeyRelease: {
    00253         last_key_event = e->xkey;
    00254         break;
    00255     }
    00256     case ClientMessage:
    00257         if ( e->xclient.message_type == xembed ) {
    00258             Time msgtime = (Time) e->xclient.data.l[0];
    00259             long message = e->xclient.data.l[1];
    00260             long detail = e->xclient.data.l[2];
    00261             if ( msgtime > qt_x_time )
    00262                 qt_x_time = msgtime;
    00263             QWidget* w = QWidget::find( e->xclient.window );
    00264             if ( !w )
    00265                 break;
    00266             switch ( message) {
    00267             case XEMBED_EMBEDDED_NOTIFY:
    00268                 ((QPublicWidget*)w->topLevelWidget())->topData()->embedded = 1;
    00269                 w->topLevelWidget()->show();
    00270                 break;
    00271             case XEMBED_WINDOW_ACTIVATE: {
    00272                 // fake focus in
    00273                 XEvent ev;
    00274                 memset(&ev, 0, sizeof(ev));
    00275                 ev.xfocus.display = qt_xdisplay();
    00276                 ev.xfocus.type = XFocusIn;
    00277                 ev.xfocus.window = w->topLevelWidget()->winId();
    00278                 ev.xfocus.mode = NotifyNormal;
    00279                 ev.xfocus.detail = NotifyAncestor;
    00280                 qApp->x11ProcessEvent( &ev );
    00281             }
    00282             break;
    00283             case XEMBED_WINDOW_DEACTIVATE: {
    00284                 // fake focus out
    00285                 XEvent ev;
    00286                 memset(&ev, 0, sizeof(ev));
    00287                 ev.xfocus.display = qt_xdisplay();
    00288                 ev.xfocus.type = XFocusOut;
    00289                 ev.xfocus.window = w->topLevelWidget()->winId();
    00290                 ev.xfocus.mode = NotifyNormal;
    00291                 ev.xfocus.detail = NotifyAncestor;
    00292                 qApp->x11ProcessEvent( &ev );
    00293             }
    00294             break;
    00295             case XEMBED_FOCUS_IN:
    00296                 {
    00297                     QWidget* focusCurrent = 0;
    00298                     QGuardedPtr<QWidget>* fw = focusMap->find( w->topLevelWidget() );
    00299                     if ( fw ) {
    00300                         focusCurrent = *fw;
    00301                         focusMap->remove( w->topLevelWidget() );
    00302                     }
    00303                     switch ( detail ) {
    00304                     case XEMBED_FOCUS_CURRENT:
    00305                         if ( focusCurrent )
    00306                             focusCurrent->setFocus();
    00307                         else if ( !w->topLevelWidget()->focusWidget() )
    00308                             w->topLevelWidget()->setFocus();
    00309                         break;
    00310                     case XEMBED_FOCUS_FIRST:
    00311                         {
    00312                             QFocusData *fd = ((QPublicWidget*)w)->focusData();
    00313                             while ( fd->next() != w->topLevelWidget() )
    00314                                 ;
    00315                             QWidget* fw = fd->next();
    00316                             QFocusEvent::setReason( QFocusEvent::Tab );
    00317                             if ( w )
    00318                                 fw->setFocus();
    00319                             else
    00320                                 w->topLevelWidget()->setFocus();
    00321                             QFocusEvent::resetReason();
    00322                         }
    00323                         break;
    00324                     case XEMBED_FOCUS_LAST:
    00325                         {
    00326                             QFocusData *fd = ((QPublicWidget*)w)->focusData();
    00327                             while ( fd->next() != w->topLevelWidget() )
    00328                                 ;
    00329                             QWidget* fw = fd->prev();
    00330                             QFocusEvent::setReason( QFocusEvent::Tab );
    00331                             if ( w )
    00332                                 fw->setFocus();
    00333                             else
    00334                                 w->topLevelWidget()->setFocus();
    00335                             QFocusEvent::resetReason();
    00336                         }
    00337                         break;
    00338                     default:
    00339                         break;
    00340                     }
    00341                 }
    00342                 break;
    00343             case XEMBED_FOCUS_OUT:
    00344                 if ( w->topLevelWidget()->focusWidget() ) {
    00345                     focusMap->insert( w->topLevelWidget(),
    00346                                       new QGuardedPtr<QWidget>(w->topLevelWidget()->focusWidget() ) );
    00347                     w->topLevelWidget()->focusWidget()->clearFocus();
    00348                 }
    00349             break;
    00350             default:
    00351                 break;
    00352             }
    00353         } else if ( e->xclient.format == 32 && e->xclient.message_type ) {
    00354             if ( e->xclient.message_type == qt_wm_protocols ) {
    00355                 QWidget* w = QWidget::find( e->xclient.window );
    00356                 if ( !w )
    00357                     break;
    00358                 Atom a = e->xclient.data.l[0];
    00359                 if ( a == qt_wm_take_focus ) {
    00360                     if ( (ulong) e->xclient.data.l[1] > qt_x_time )
    00361                         qt_x_time = e->xclient.data.l[1];
    00362                     if ( w->isActiveWindow() ) {
    00363                         // send another WindowActivate. The QXEmbed
    00364                         // widget will filter it and pass the focus to
    00365                         // the proxy
    00366                         QEvent e( QEvent::WindowActivate );
    00367                         QApplication::sendEvent( w, &e );
    00368                     }
    00369                 }
    00370             }
    00371         }
    00372         break;
    00373     default:
    00374         break;
    00375     }
    00376
    00377     if ( oldFilter )
    00378         return oldFilter( e );
    00379     return FALSE;
    00380 }
    00381
    00390 void QXEmbed::initialize()
    00391 {
    00392     static bool is_initialized = FALSE;
    00393     if ( is_initialized )
    00394         return;
    00395     xembed = XInternAtom( qt_xdisplay(), "_XEMBED", FALSE );
    00396     oldFilter = qt_set_x11_event_filter( qxembed_x11_event_filter );
    00397
    00398     focusMap = new QPtrDict<QGuardedPtr<QWidget> >;
    00399     focusMap->setAutoDelete( TRUE );
    00400
    00401     filter = new QXEmbedAppFilter;
    00402
    00403     is_initialized = TRUE;
    00404 }
    00405
    00406
    00445 QXEmbed::QXEmbed(QWidget *parent, const char *name, WFlags f)
    00446   : QWidget(parent, name, f)
    00447 {
    00448     d = new QXEmbedData;
    00449     d->focusProxy = new QWidget( this, "xembed_focus" );
    00450     d->focusProxy->setGeometry( -1, -1, 1, 1 );
    00451     initialize();
    00452     window = 0;
    00453     setFocusPolicy(StrongFocus);
    00454     setKeyCompression( FALSE );
    00455
    00456     //trick to create extraData();
    00457     (void) topData();
    00458
    00459     // we are interested in SubstructureNotify
    00460     XSelectInput(qt_xdisplay(), winId(),
    00461                  KeyPressMask | KeyReleaseMask |
    00462                  ButtonPressMask | ButtonReleaseMask |
    00463                  KeymapStateMask |
    00464                  ButtonMotionMask |
    00465                  PointerMotionMask | // may need this, too
    00466                  EnterWindowMask | LeaveWindowMask |
    00467                  FocusChangeMask |
    00468                  ExposureMask |
    00469                  StructureNotifyMask |
    00470                  SubstructureRedirectMask |
    00471                  SubstructureNotifyMask
    00472                  );
    00473
    00474     topLevelWidget()->installEventFilter( this );
    00475     qApp->installEventFilter( this );
    00476
    00477     if (isActiveWindow())
    00478         if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
    00479             XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
    00480                             RevertToParent, qt_x_time );
    00481
    00482     setAcceptDrops( TRUE );
    00483 }
    00484
    00488 QXEmbed::~QXEmbed()
    00489 {
    00490   if ( d && d->xgrab)
    00491     XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
    00492
    00493   if ( window != 0 ) {
    00494         if ( autoDelete() )
    00495             XUnmapWindow( qt_xdisplay(), window );
    00496
    00497         XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0);
    00498         XSync(qt_xdisplay(), FALSE);
    00499
    00500         if ( autoDelete() ) {
    00501             XEvent ev;
    00502             memset(&ev, 0, sizeof(ev));
    00503             ev.xclient.type = ClientMessage;
    00504             ev.xclient.window = window;
    00505             ev.xclient.message_type = qt_wm_protocols;
    00506             ev.xclient.format = 32;
    00507             ev.xclient.data.s[0] = qt_wm_delete_window;
    00508             XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev);
    00509         }
    00510         XFlush( qt_xdisplay() );
    00511      }
    00512   window = 0;
    00513
    00514   delete d;
    00515 }
    00516
    00517
    00531 void QXEmbed::setProtocol( Protocol proto )
    00532 {
    00533     if (window == 0) {
    00534         d->xplain = FALSE;
    00535         if (proto == XPLAIN)
    00536             d->xplain = TRUE;
    00537     }
    00538 }
    00539
    00544 QXEmbed::Protocol QXEmbed::protocol()
    00545 {
    00546   if (d->xplain)
    00547     return XPLAIN;
    00548   return XEMBED;
    00549 }
    00550
    00551
    00554 void QXEmbed::resizeEvent(QResizeEvent*)
    00555 {
    00556     if (window != 0)
    00557         XResizeWindow(qt_xdisplay(), window, width(), height());
    00558 }
    00559
    00562 void QXEmbed::showEvent(QShowEvent*)
    00563 {
    00564     if (window != 0)
    00565         XMapRaised(qt_xdisplay(), window);
    00566 }
    00567
    00568
    00571 bool QXEmbed::eventFilter( QObject *o, QEvent * e)
    00572 {
    00573
    00574     switch ( e->type() ) {
    00575     case QEvent::WindowActivate:
    00576         if ( o == topLevelWidget() ) {
    00577             if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
    00578                 if (! hasFocus() )
    00579                     XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
    00580                                     RevertToParent, qt_x_time );
    00581             if (d->xplain)
    00582                 checkGrab();
    00583             else
    00584                 send_xembed_message( window, XEMBED_WINDOW_ACTIVATE );
    00585         }
    00586         break;
    00587     case QEvent::WindowDeactivate:
    00588         if ( o == topLevelWidget() ) {
    00589             if (d->xplain)
    00590                 checkGrab();
    00591             else
    00592                 send_xembed_message( window, XEMBED_WINDOW_DEACTIVATE );
    00593         }
    00594         break;
    00595     case QEvent::Move:
    00596         {
    00597             QPoint globalPos = mapToGlobal(QPoint(0,0));
    00598             if (globalPos != d->lastPos) {
    00599                 d->lastPos = globalPos;
    00600                 sendSyntheticConfigureNotifyEvent();
    00601             }
    00602         }
    00603         break;
    00604     default:
    00605         break;
    00606    }
    00607    return FALSE;
    00608 }
    00609
    00610
    00611 bool  QXEmbed::event( QEvent * e)
    00612 {
    00613     return QWidget::event( e );
    00614 }
    00615
    00618 void QXEmbed::keyPressEvent( QKeyEvent *)
    00619 {
    00620     if (!window)
    00621         return;
    00622     last_key_event.window = window;
    00623     XSendEvent(qt_xdisplay(), window, FALSE, KeyPressMask, (XEvent*)&last_key_event);
    00624
    00625 }
    00626
    00629 void QXEmbed::keyReleaseEvent( QKeyEvent *)
    00630 {
    00631     if (!window)
    00632         return;
    00633     last_key_event.window = window;
    00634     XSendEvent(qt_xdisplay(), window, FALSE, KeyReleaseMask, (XEvent*)&last_key_event);
    00635 }
    00636
    00639 void QXEmbed::focusInEvent( QFocusEvent * e ){
    00640     if (!window)
    00641         return;
    00642     if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
    00643         XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
    00644                         RevertToParent, qt_x_time );
    00645     if (d->xplain) {
    00646         checkGrab();
    00647         sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
    00648     } else {
    00649         int detail = XEMBED_FOCUS_CURRENT;
    00650         if ( e->reason() == QFocusEvent::Tab )
    00651             detail = tabForward?XEMBED_FOCUS_FIRST:XEMBED_FOCUS_LAST;
    00652         send_xembed_message( window, XEMBED_FOCUS_IN, detail);
    00653     }
    00654 }
    00655
    00658 void QXEmbed::focusOutEvent( QFocusEvent * ){
    00659     if (!window)
    00660         return;
    00661     if (d->xplain) {
    00662         checkGrab();
    00663         sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer );
    00664     } else {
    00665         send_xembed_message( window, XEMBED_FOCUS_OUT );
    00666     }
    00667     if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
    00668         XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
    00669                         RevertToParent, qt_x_time );
    00670 }
    00671
    00672
    00673
    00674 static bool wstate_withdrawn( WId winid )
    00675 {
    00676     Atom type;
    00677     int format;
    00678     unsigned long length, after;
    00679     unsigned char *data;
    00680     int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
    00681                                 FALSE, AnyPropertyType, &type, &format,
    00682                                 &length, &after, &data );
    00683     bool withdrawn = TRUE;
    00684     if ( r == Success && data && format == 32 ) {
    00685         Q_UINT32 *wstate = (Q_UINT32*)data;
    00686         withdrawn  = (*wstate == WithdrawnState );
    00687         XFree( (char *)data );
    00688     }
    00689     return withdrawn;
    00690 }
    00691
    00692 static int get_parent(WId winid, Window *out_parent)
    00693 {
    00694     Window root, *children=0;
    00695     unsigned int nchildren;
    00696     int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
    00697     if (st) {
    00698         if (children) {
    00699             XFree(children);
    00700         }
    00701         return st;
    00702     } else {
    00703         // kdDebug() << QString("**** FAILED **** XQueryTree returns status %1").arg(st) << endl;
    00704     }
    00705     return st;
    00706 }
    00707 #include <unistd.h>
    00720 void QXEmbed::embed(WId w)
    00721 {
    00722     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;
    00723     if (!w)
    00724         return;
    00725     XAddToSaveSet( qt_xdisplay(), w );
    00726     bool has_window =  w == window;
    00727     window = w;
    00728     if ( !has_window ) {
    00729         if ( !wstate_withdrawn(window) ) {
    00730             XWithdrawWindow(qt_xdisplay(), window, qt_xscreen());
    00731             QApplication::flushX();
    00732             while (!wstate_withdrawn(window))
    00733                 ;
    00734         }
    00735         Window parent;
    00736         get_parent(w, &parent);
    00737         kdDebug() << QString(">>> before reparent: parent=0x%1").arg(parent, 0, 16) << endl;
    00738         for (int i = 0; i < 50; i++) {
    00739             Window parent = 0;
    00740             XReparentWindow(qt_xdisplay(), w, winId(), 0, 0);
    00741             if (get_parent(w, &parent) && parent == winId()) {
    00742                kdDebug() << QString(">>> Loop %1: reparent of 0x%2 into 0x%3 successful").arg(i).arg(w, 0, 16).arg(winId(), 0, 16) << endl;
    00743                break;
    00744             }
    00745             kdDebug() << QString(">>> Loop %1: reparent of 0x%2 into 0x%3 failed").arg(i).arg(w, 0, 16).arg(winId(), 0, 16) << endl;
    00746             USLEEP(1000);
    00747         }
    00748         QApplication::syncX();
    00749     }
    00750
    00751     XResizeWindow(qt_xdisplay(), w, width(), height());
    00752     XMapRaised(qt_xdisplay(), window);
    00753     sendSyntheticConfigureNotifyEvent();
    00754     extraData()->xDndProxy = w;
    00755
    00756     if ( parent() ) {
    00757         QEvent * layoutHint = new QEvent( QEvent::LayoutHint );
    00758         QApplication::postEvent( parent(), layoutHint );
    00759     }
    00760     windowChanged( window );
    00761     if (d->xplain) {
    00762         checkGrab();
    00763         if ( hasFocus() )
    00764             sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
    00765     } else {
    00766         send_xembed_message( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
    00767         send_xembed_message( window, isActiveWindow() ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE );
    00768         if ( hasFocus() )
    00769             send_xembed_message( window, XEMBED_FOCUS_IN );
    00770     }
    00771 }
    00772
    00773
    00778 WId QXEmbed::embeddedWinId() const
    00779 {
    00780     return window;
    00781 }
    00782
    00783
    00786 bool QXEmbed::focusNextPrevChild( bool next )
    00787 {
    00788     if ( window )
    00789         return FALSE;
    00790     else
    00791         return QWidget::focusNextPrevChild( next );
    00792 }
    00793
    00794
    00797 bool QXEmbed::x11Event( XEvent* e)
    00798 {
    00799     //kdDebug() << "x11Event " << KXEventUtil::getX11EventInfo(e) << endl;
    00800     switch ( e->type ) {
    00801     case DestroyNotify:
    00802         if ( e->xdestroywindow.window == window ) {
    00803             window = 0;
    00804             windowChanged( window );
    00805             emit embeddedWindowDestroyed();
    00806         }
    00807         break;
    00808     case ReparentNotify:
    00809         if ( e->xreparent.window == d->focusProxy->winId() )
    00810             break; // ignore proxy
    00811         if ( window && e->xreparent.window == window &&
    00812              e->xreparent.parent != winId() ) {
    00813             // we lost the window
    00814             window = 0;
    00815             windowChanged( window );
    00816         } else if ( e->xreparent.parent == winId() ){
    00817             // we got a window
    00818             window = e->xreparent.window;
    00819             embed( window );
    00820         }
    00821         break;
    00822     case ButtonPress:
    00823         if (d->xplain) {
    00824             QFocusEvent::setReason( QFocusEvent::Mouse );
    00825             setFocus();
    00826             QFocusEvent::resetReason();
    00827             XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime);
    00828             return TRUE;
    00829         }
    00830         break;
    00831     case ButtonRelease:
    00832         if (d->xplain)
    00833             XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime);
    00834         break;
    00835     case MapRequest:
    00836         if ( window && e->xmaprequest.window == window )
    00837             XMapRaised(qt_xdisplay(), window );
    00838         break;
    00839     case ClientMessage:
    00840         if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
    00841             long message = e->xclient.data.l[1];
    00842 //          long detail = e->xclient.data.l[2];
    00843             switch ( message ) {
    00844             case XEMBED_FOCUS_NEXT:
    00845                 QWidget::focusNextPrevChild( TRUE );
    00846                 break;
    00847             case XEMBED_FOCUS_PREV:
    00848                 QWidget::focusNextPrevChild( FALSE );
    00849                 break;
    00850             case XEMBED_REQUEST_FOCUS:
    00851                 QFocusEvent::setReason( QFocusEvent::Mouse );
    00852                 setFocus();
    00853                 QFocusEvent::resetReason();
    00854                 break;
    00855             default:
    00856                 break;
    00857             }
    00858         }
    00859         break;
    00860
    00861     case ConfigureRequest:
    00862         if (e->xconfigurerequest.window == window)
    00863         {
    00864              sendSyntheticConfigureNotifyEvent();
    00865         }
    00866         break;
    00867     case MotionNotify:
    00868         // fall through, workaround for Qt 3.0 < 3.0.3
    00869     case EnterNotify:
    00870         if ( QWhatsThis::inWhatsThisMode() )
    00871             enterWhatsThisMode();
    00872         break;
    00873     default:
    00874         break;
    00875     }
    00876     return FALSE;
    00877 }
    00878
    00879  // temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000  )
    00880 void QXEmbed::enterWhatsThisMode()
    00881 {
    00882     QWhatsThis::leaveWhatsThisMode();
    00883     if ( !context_help )
    00884         context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", FALSE );
    00885     sendClientMessage(window , qt_wm_protocols, context_help );
    00886 }
    00887
    00888
    00894 void QXEmbed::windowChanged( WId )
    00895 {
    00896 }
    00897
    00898
    00909 bool QXEmbed::processClientCmdline( QWidget* client, int& argc, char ** argv )
    00910 {
    00911     int myargc = argc;
    00912     WId window = 0;
    00913     int i, j;
    00914
    00915     j = 1;
    00916     for ( i=1; i<myargc; i++ ) {
    00917         if ( argv[i] && *argv[i] != '-' ) {
    00918             argv[j++] = argv[i];
    00919             continue;
    00920         }
    00921         QCString arg = argv[i];
    00922         if ( strcmp(arg,"-embed") == 0 && i < myargc-1 ) {
    00923             QCString s = argv[++i];
    00924             window = s.toInt();
    00925         } else
    00926             argv[j++] = argv[i];
    00927     }
    00928     argc = j;
    00929
    00930     if ( window != 0 ) {
    00931         embedClientIntoWindow( client, window );
    00932         return TRUE;
    00933     }
    00934
    00935     return FALSE;
    00936 }
    00937
    00938
    00947 void QXEmbed::embedClientIntoWindow(QWidget* client, WId window)
    00948 {
    00949     initialize();
    00950     XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0);
    00951     ((QXEmbed*)client)->topData()->embedded = TRUE;
    00952     ((QXEmbed*)client)->topData()->parentWinId = window;
    00953     client->show();
    00954 }
    00955
    00956
    00957
    00963 QSizePolicy QXEmbed::sizePolicy() const
    00964 {
    00965     return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
    00966 }
    00967
    00968
    00972 QSize QXEmbed::sizeHint() const
    00973 {
    00974     return minimumSizeHint();
    00975 }
    00976
    00989 QSize QXEmbed::minimumSizeHint() const
    00990 {
    00991     int minw = 0;
    00992     int minh = 0;
    00993     if ( window ) {
    00994         XSizeHints size;
    00995         long msize;
    00996         if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize)
    00997             && ( size.flags & PMinSize) ) {
    00998             minw = size.min_width;
    00999             minh = size.min_height;
    01000         }
    01001     }
    01002
    01003     return QSize( minw, minh );
    01004 }
    01005
    01006 void QXEmbed::setAutoDelete( bool b)
    01007 {
    01008     d->autoDelete = b;
    01009 }
    01010
    01011 bool QXEmbed::autoDelete() const
    01012 {
    01013     return d->autoDelete;
    01014 }
    01015
    01018 bool QXEmbed::customWhatsThis() const
    01019 {
    01020     return TRUE;
    01021 }
    01022
    01023
    01024 void QXEmbed::checkGrab()
    01025 {
    01026     if (d->xplain && isActiveWindow() && !hasFocus()) {
    01027         if (! d->xgrab)
    01028             XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(),
    01029                         FALSE, ButtonPressMask, GrabModeSync, GrabModeAsync,
    01030                         None, None );
    01031         d->xgrab = TRUE;
    01032     } else {
    01033         if (d->xgrab)
    01034             XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
    01035         d->xgrab = FALSE;
    01036     }
    01037 }
    01038
    01039
    01040 void QXEmbed::sendSyntheticConfigureNotifyEvent()
    01041 {
    01042     QPoint globalPos = mapToGlobal(QPoint(0,0));
    01043     if (window) {
    01044         // kdDebug(6100) << "*************** sendSyntheticConfigureNotify ******************" << endl;
    01045         XConfigureEvent c;
    01046         memset(&c, 0, sizeof(c));
    01047         c.type = ConfigureNotify;
    01048         c.display = qt_xdisplay();
    01049         c.send_event = True;
    01050         c.event = window;
    01051         c.window = winId();
    01052         c.x = globalPos.x();
    01053         c.y = globalPos.y();
    01054         c.width = width();
    01055         c.height = height();
    01056         c.border_width = 0;
    01057         c.above = None;
    01058         c.override_redirect = 0;
    01059         XSendEvent( qt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
    01060         //kdDebug(6100) << "SENT " << KXEventUtil::getX11EventInfo((XEvent*)&c) << endl;
    01061     }
    01062 }
    01063
    01064 // for KDE
    01065 #include "qxembed.moc"
    01066 #endif

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:58:07 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001