00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00038
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
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
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
00087
00088
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
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
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
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
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
00364
00365
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
00457 (void) topData();
00458
00459
00460 XSelectInput(qt_xdisplay(), winId(),
00461 KeyPressMask | KeyReleaseMask |
00462 ButtonPressMask | ButtonReleaseMask |
00463 KeymapStateMask |
00464 ButtonMotionMask |
00465 PointerMotionMask |
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
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
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;
00811 if ( window && e->xreparent.window == window &&
00812 e->xreparent.parent != winId() ) {
00813
00814 window = 0;
00815 windowChanged( window );
00816 } else if ( e->xreparent.parent == winId() ){
00817
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
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
00869 case EnterNotify:
00870 if ( QWhatsThis::inWhatsThisMode() )
00871 enterWhatsThisMode();
00872 break;
00873 default:
00874 break;
00875 }
00876 return FALSE;
00877 }
00878
00879
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
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
01061 }
01062 }
01063
01064
01065 #include "qxembed.moc"
01066 #endif