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