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 emit embeddedWindowDestroyed();
01051
01052
01053
01054 if( !d->xplain )
01055 XRemoveFromSaveSet( qt_xdisplay(), window );
01056 } else if ( e->xreparent.parent == winId()){
01057
01058 window = e->xreparent.window;
01059
01060
01061 if( !d->xplain )
01062 XAddToSaveSet( qt_xdisplay(), window );
01063 XResizeWindow(qt_xdisplay(), window, width(), height());
01064 XMapRaised(qt_xdisplay(), window);
01065
01066 sendSyntheticConfigureNotifyEvent();
01067
01068 extraData()->xDndProxy = window;
01069 if ( parent() ) {
01070
01071
01072 QEvent * layoutHint = new QEvent( QEvent::LayoutHint );
01073 QApplication::postEvent( parent(), layoutHint );
01074 }
01075 windowChanged( window );
01076 if (d->xplain) {
01077
01078 checkGrab();
01079 if ( hasFocus() )
01080
01081 sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
01082 } else {
01083
01084 sendXEmbedMessage( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
01085 if (isActiveWindow())
01086 sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE);
01087 else
01088 sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE);
01089 if ( hasFocus() )
01090 sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT );
01091 }
01092 }
01093 break;
01094 case ButtonPress:
01095 if (d->xplain && d->xgrab) {
01096
01097
01098 QFocusEvent::setReason( QFocusEvent::Mouse );
01099 setFocus();
01100 QFocusEvent::resetReason();
01101
01102 XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime);
01103
01104 return true;
01105 }
01106 break;
01107 case ButtonRelease:
01108 if (d->xplain && d->xgrab) {
01109
01110 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime);
01111 return true;
01112 }
01113 break;
01114 case MapRequest:
01115
01116 if ( window && e->xmaprequest.window == window )
01117 XMapRaised(qt_xdisplay(), window );
01118 break;
01119 case ClientMessage:
01120
01121
01122 if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
01123 long message = e->xclient.data.l[1];
01124 switch ( message ) {
01125
01126
01127
01128 case XEMBED_FOCUS_NEXT:
01129 QWidget::focusNextPrevChild( true );
01130 break;
01131 case XEMBED_FOCUS_PREV:
01132 QWidget::focusNextPrevChild( false );
01133 break;
01134
01135 case XEMBED_REQUEST_FOCUS:
01136 QFocusEvent::setReason( QFocusEvent::Mouse );
01137 setFocus();
01138 QFocusEvent::resetReason();
01139 break;
01140 default:
01141 break;
01142 }
01143 }
01144 break;
01145
01146 case ConfigureRequest:
01147
01148
01149 if (e->xconfigurerequest.window == window)
01150 {
01151 sendSyntheticConfigureNotifyEvent();
01152 }
01153 break;
01154 case MotionNotify:
01155
01156 case EnterNotify:
01157
01158 if ( QWhatsThis::inWhatsThisMode() )
01159 enterWhatsThisMode();
01160 break;
01161 default:
01162 break;
01163 }
01164 return false;
01165 }
01166
01167
01168
01169
01170 void QXEmbed::enterWhatsThisMode()
01171 {
01172
01173
01174
01175
01176 QWhatsThis::leaveWhatsThisMode();
01177 if ( !context_help )
01178 context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", false );
01179 sendClientMessage(window , qt_wm_protocols, context_help );
01180 }
01181
01182
01183
01184 void QXEmbed::windowChanged( WId )
01185 {
01186 }
01187
01188
01189
01190
01191 bool QXEmbed::processClientCmdline( QWidget* client, int& argc, char ** argv )
01192 {
01193 int myargc = argc;
01194 WId window = 0;
01195 int i, j;
01196
01197 j = 1;
01198 for ( i=1; i<myargc; i++ ) {
01199 if ( argv[i] && *argv[i] != '-' ) {
01200 argv[j++] = argv[i];
01201 continue;
01202 }
01203 QCString arg = argv[i];
01204 if ( strcmp(arg,"-embed") == 0 && i < myargc-1 ) {
01205 QCString s = argv[++i];
01206 window = s.toInt();
01207 } else
01208 argv[j++] = argv[i];
01209 }
01210 argc = j;
01211
01212 if ( window != 0 ) {
01213 embedClientIntoWindow( client, window );
01214 return true;
01215 }
01216
01217 return false;
01218 }
01219
01220
01221
01222
01223 void QXEmbed::embedClientIntoWindow(QWidget* client, WId window)
01224 {
01225 initialize();
01226 XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0);
01227
01228 ((QXEmbed*)client)->topData()->embedded = true;
01229 ((QXEmbed*)client)->topData()->parentWinId = window;
01230
01231
01232 client->show();
01233 }
01234
01235
01236
01237
01238
01239 QSizePolicy QXEmbed::sizePolicy() const
01240 {
01241 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
01242 }
01243
01244
01245
01246 QSize QXEmbed::sizeHint() const
01247 {
01248 return minimumSizeHint();
01249 }
01250
01251
01252 QSize QXEmbed::minimumSizeHint() const
01253 {
01254 int minw = 0;
01255 int minh = 0;
01256 if ( window ) {
01257 XSizeHints size;
01258 long msize;
01259 if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize)
01260 && ( size.flags & PMinSize) ) {
01261 minw = size.min_width;
01262 minh = size.min_height;
01263 }
01264 }
01265
01266 return QSize( minw, minh );
01267 }
01268
01269
01270
01271 void QXEmbed::setAutoDelete( bool b)
01272 {
01273 d->autoDelete = b;
01274 }
01275
01276
01277 bool QXEmbed::autoDelete() const
01278 {
01279 return d->autoDelete;
01280 }
01281
01282
01283 bool QXEmbed::customWhatsThis() const
01284 {
01285 return true;
01286 }
01287
01288
01289
01290
01291
01292
01293 void QXEmbed::checkGrab()
01294 {
01295 if (d->xplain && isActiveWindow() && !hasFocus()) {
01296 if (! d->xgrab)
01297 XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(),
01298 false, ButtonPressMask, GrabModeSync, GrabModeAsync,
01299 None, None );
01300 d->xgrab = true;
01301 } else {
01302 if (d->xgrab)
01303 XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
01304 d->xgrab = false;
01305 }
01306 }
01307
01308
01309
01310 void QXEmbed::sendSyntheticConfigureNotifyEvent()
01311 {
01312
01313
01314
01315
01316
01317
01318 QPoint globalPos = mapToGlobal(QPoint(0,0));
01319 if (window) {
01320 XConfigureEvent c;
01321 memset(&c, 0, sizeof(c));
01322 c.type = ConfigureNotify;
01323 c.display = qt_xdisplay();
01324 c.send_event = True;
01325 c.event = window;
01326 c.window = winId();
01327 c.x = globalPos.x();
01328 c.y = globalPos.y();
01329 c.width = width();
01330 c.height = height();
01331 c.border_width = 0;
01332 c.above = None;
01333 c.override_redirect = 0;
01334 XSendEvent( qt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c );
01335 }
01336 }
01337
01338
01339 void QXEmbed::reparent( QWidget * parent, WFlags f, const QPoint & p, bool showIt )
01340 {
01341
01342
01343
01344
01345 Q_ASSERT( window == 0 );
01346 QWidget::reparent( parent, f, p, showIt );
01347 }
01348
01349
01350 #include "qxembed.moc"
01351 #endif // Q_WS_X11