diff options
Diffstat (limited to 'kdeui/qxembed.cpp')
-rw-r--r-- | kdeui/qxembed.cpp | 1450 |
1 files changed, 0 insertions, 1450 deletions
diff --git a/kdeui/qxembed.cpp b/kdeui/qxembed.cpp deleted file mode 100644 index 03d9ca1d2..000000000 --- a/kdeui/qxembed.cpp +++ /dev/null @@ -1,1450 +0,0 @@ -/**************************************************************************** - Implementation of QXEmbed class - - Copyright (C) 1999-2002 Trolltech AS - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*****************************************************************************/ - - -// L-000: About comments marked with Lxxxx. -// -// These comments represent an attempt to provide a more adequate -// documentation to KDE developpers willing to modify QXEmbed. Keep in -// mind that these comments were written long after most of the code. -// Please improve them if you spot something wrong or missing -// (Leon Bottou, 26-10-2003). -// -// Relevant documents: -// - QXEmbed developper documentation -// (see comments in qxembed.h) -// - Xlib Reference Manual -// (sections about focus, reparenting, window management) -// - ICCCM Manual -// (window management) -// - XEMBED specification -// (http://www.freedesktop.org/Standards/xembed-spec) -// - XPLAIN and XEMBED. -// <http://lists.kde.org/?w=2&r=1&s=qxembed+variants&q=t> -// - Accumulated community knowledge. -// <http://lists.kde.org/?w=2&r=1&s=qxembed&q=t> -// <http://lists.kde.org/?l=kde-devel&w=2&r=1&s=qxembed&q=b> -// <http://lists.kde.org/?l=kfm-devel&w=2&r=1&s=qxembed&q=b> -// - - -#include <tqapplication.h> -#include <tqptrlist.h> -#include <tqptrdict.h> -#include <tqguardedptr.h> -#include <tqwhatsthis.h> -#include <tqfocusdata.h> - -// L0001: QXEmbed works only under X windows. -#ifdef Q_WS_X11 - -# include <X11/X.h> -# include <X11/Xlib.h> -# include <X11/Xutil.h> -# include <X11/Xatom.h> -# define XK_MISCELLANY -# define XK_LATIN1 -# include <X11/keysymdef.h> -# include <kdebug.h> -# include <kxerrorhandler.h> - -// L0002: Is file config.h KDE specific? -# include <config.h> -# ifdef HAVE_UNISTD_H -# include <unistd.h> -# ifdef HAVE_USLEEP -# define USLEEP(x) usleep(x) -# else -# define USLEEP(x) sleep(0) -# endif -# else -# define USLEEP(x) sleep(0) -# endif - -# include "qxembed.h" - -// L0003: This keysym is used for focus navigation. -# ifndef XK_ISO_Left_Tab -# define XK_ISO_Left_Tab 0xFE20 -# endif - -// L0004: Conflicts between X11 and Qt definitions. -const int XFocusOut = FocusOut; -const int XFocusIn = FocusIn; -const int XKeyPress = KeyPress; -const int XKeyRelease = KeyRelease; -# undef KeyRelease -# undef KeyPress -# undef FocusOut -# undef FocusIn - -// L0005: Variables defined in qapplication_x11.cpp -extern Atom qt_wm_protocols; -extern Atom qt_wm_delete_window; -extern Atom qt_wm_take_focus; -extern Atom qt_wm_state; - -// L0006: X11 atoms private to QXEmbed -static Atom xembed = 0; -static Atom context_help = 0; - -// L0007: Xembed message codes (see XEmbed spec) -#define XEMBED_EMBEDDED_NOTIFY 0 -#define XEMBED_WINDOW_ACTIVATE 1 -#define XEMBED_WINDOW_DEACTIVATE 2 -#define XEMBED_REQUEST_FOCUS 3 -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 -#define XEMBED_FOCUS_NEXT 6 -#define XEMBED_FOCUS_PREV 7 - -// L0008: Xembed message details (see XEmbed spec) -// -- XEMBED_FOCUS_IN: -#define XEMBED_FOCUS_CURRENT 0 -#define XEMBED_FOCUS_FIRST 1 -#define XEMBED_FOCUS_LAST 2 - - -// L0100: Private data held by the QXEmbed object. -// This belongs to the embedder side. -class QXEmbedData -{ -public: - QXEmbedData(){ - autoDelete = true; - xplain = false; - xgrab = false; - mapAfterRelease = false; - lastPos = TQPoint(0,0); - } - ~QXEmbedData(){} - - bool autoDelete; // L0101: See L2600 - bool xplain; // L0102: See L1100 - bool xgrab; // L0103: See L2800 - bool mapAfterRelease; - TQWidget* focusProxy; // L0104: See XEmbed spec - TQPoint lastPos; // L0105: See L1390 -}; - -namespace -{ - // L0200: This application wide event filter handles focus - // issues in the embedded client. - class QXEmbedAppFilter : public TQObject - { - public: - QXEmbedAppFilter() { tqApp->installEventFilter( this ); } - ~QXEmbedAppFilter() { } - bool eventFilter( TQObject *, TQEvent * ); - }; -} - -// L0201: See L0200, L0740 -static QXEmbedAppFilter* filter = 0; -// L0202: See L0610, L0730 -static TQPtrDict<TQGuardedPtr<TQWidget> > *focusMap = 0; -// L0203: See L0660, L1400, L1450 -static XKeyEvent last_key_event; - -// L0300: This class gives access protected members of class TQWidget. -// Function focusData() is useful to reimplement tab focus management -// (L0620) Function topData() returns a structure QTLWExtra containing -// information unique to toplevel windows. This structure contains two -// members for the sole use of QXEmbed. Flag `embedded' indicates whether -// the toplevel window is embedded using the XEMBED protocol (L0680). -// Handle `parentWinId' then records the id of the embedding window. - -class QPublicWidget : public TQWidget -{ -public: - QTLWExtra* topData() { return TQWidget::topData(); } - TQFocusData *focusData(){ return TQWidget::focusData(); } - bool focusNextPrev(bool b) { return focusNextPrevChild(b); } -}; - -// L0400: This sets a very low level filter for X11 messages. -// See qapplication_x11.cpp -typedef int (*QX11EventFilter) (XEvent*); -extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter); -static QX11EventFilter oldFilter = 0; - - -// L0500: Helper to send XEmbed messages. -static void sendXEmbedMessage( WId window, long message, long detail = 0, - long data1 = 0, long data2 = 0) -{ - if (!window) return; - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = window; - ev.xclient.message_type = xembed; - ev.xclient.format = 32; - ev.xclient.data.l[0] = GET_QT_X_TIME(); - ev.xclient.data.l[1] = message; - ev.xclient.data.l[2] = detail; - ev.xclient.data.l[3] = data1; - ev.xclient.data.l[4] = data2; - XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev); -} - -// L0501: Helper to send ICCCM Client messages. -// See X11 ICCCM Specification. -static void sendClientMessage(Window window, Atom a, long x) -{ - if (!window) return; - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = window; - ev.xclient.message_type = a; - ev.xclient.format = 32; - ev.xclient.data.l[0] = x; - ev.xclient.data.l[1] = GET_QT_X_TIME(); - XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev); -} - -// L0502: Helper to send fake X11 focus messages. -// See X11 Reference Manual and Window Management stuff. -static void sendFocusMessage(Window window, int type, int mode, int detail) -{ - if (!window) return; - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xfocus.type = type; - ev.xfocus.window = window; - ev.xfocus.mode = mode; - ev.xfocus.detail = detail; - XSendEvent(qt_xdisplay(), window, false, FocusChangeMask, &ev); -} - - -// ------------------------------------------------------------ -// L0600: MOST OF WHAT FOLLOWS CONCERNS THE CLIENT SIDE. -// The following code mostly executes inside a Qt application swallowed -// by QXEmbed widget. It mostly consists of event filters that fight -// the normal Qt mechanisms in order to implement the XEMBED protocol. -// All this would be a lot simpler if it was implemented by Qt itself. - - - -// L0610: This event filter receives all Qt events. Its main purpose is to -// capture the Qt focus events in the embedded client in order to -// implement the XEMBED protocol. -// -// Let's start with a few reminders: -// -// - X11 only has the concept of the "X11 focus window". This window -// basically receives all key events. The ICCCM conventions define -// how the window manager and the applications must cooperate to -// choose the X11 focus window. -// -// - Most toolkits, including Qt, maintain the concepts of 'active -// widget' and 'Qt focus widget'. A toplevel widget is active when -// the X11 focus is set to one of its children. By extension a -// widget is active when its toplevel widget is active. There is one -// Qt focus widget for each toplevel widget. When the toplevel -// widget is active, all key events are sent to the Qt focus widget, -// regardless of which descendant of the toplevel window has the X11 -// focus. Widgets can adjust their appearance according to both -// their activation and focus states. The Qt FocusIn and FocusOut -// events indicate when a widget simultaneously is active and has -// the Qt focus. -// -// The XEMBED protocol defines ways to communicate abouth both -// activation and focus. The embedded client is active as soon as the -// embedding window is active (L0676, L0677). A widget in the embedded -// client receives key events when (1) it has the Qt focus in the -// embedded application, and (2) the QXEmbed widget in the embedding -// application is active and has the Qt focus. The Qt library in the -// embedded application is unaware of the focus status of the QXEmbed -// widget. We must make sure it does the right thing regarding the -// sending of focus events and the visual appearance of the focussed -// widgets. When the QXEmbed widget looses the Qt focus, we clear the -// focus in the embedded client (L1570, L0688). Conversely, when -// the QXEmbed widget gains the Qt focus, we restore the Qt focus -// window in the embedded client (L1530, L0680, L0683). -// Variable focusMap is used to remember which was the Qt focus -// widget in the embedded application. All this would be a lot -// simpler if it was implemented inside Qt... -// -// The XPLAIN protocol is much less refined in this respect. -// The activation status of the embedded client simply reflect -// the focus status of the QXEmbed widget. This is achieved -// by sending fake X11 focus message to the client (L1521, L1561). -// A passive button grab (L2800) intercepts mouse activity in the -// embedded client and sets the Qt focus to the QXEmbed widget -// when this happens (L2060). This can be achieved without -// cooperation from the client. - -bool QXEmbedAppFilter::eventFilter( TQObject *o, TQEvent * e) -{ - static bool obeyFocus = false; - switch ( e->type() ) { - case TQEvent::MouseButtonPress: - // L0612: This will become clear with L0614 - if ( !((TQWidget*)o)->isActiveWindow() ) - obeyFocus = true; - break; - case TQEvent::FocusIn: - // L0613: FocusIn events either occur because the widget already was - // active and has just been given the Qt focus (L0614) or - // because the widget already had the Qt focus and just became - // active (L0615). - if ( TQT_BASE_OBJECT(tqApp->tqfocusWidget()) == TQT_BASE_OBJECT(o) && - ((QPublicWidget*)tqApp->tqfocusWidget()->tqtopLevelWidget())->topData()->embedded ) { - TQFocusEvent* fe = (TQFocusEvent*) e; - if ( obeyFocus || fe->reason() != TQFocusEvent::ActiveWindow /*|| fe->reason() == TQFocusEvent::Mouse || - fe->reason() == TQFocusEvent::Shortcut*/ ) { - // L0614: A widget in the embedded client was just given the Qt focus. - // Variable `obeyFocus' suggests that this is the result of mouse - // activity in the client. The XEMBED_REQUEST_FOCUS message causes - // the embedding widget to take the Qt focus (L2085). -#ifdef USE_QT4 - WId window = ((QPublicWidget*)tqApp->tqfocusWidget()->tqtopLevelWidget())->effectiveWinId(); -#else // USE_QT4 - WId window = ((QPublicWidget*)tqApp->tqfocusWidget()->tqtopLevelWidget())->topData()->parentWinId; -#endif // USE_QT4 - focusMap->remove( tqApp->tqfocusWidget()->tqtopLevelWidget() ); - sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS ); - } else if ( fe->reason() == TQFocusEvent::ActiveWindow ) { - // L0615: Both the embedder and the embedded client became active. - // But we do not know whether the QXEmbed widget has the Qt focus. - // So we clear the Qt focus for now. If indeed the QXEmbed widget - // has the focus, it will receive a FocusIn message (L1530) and - // tell us to restore the focus (L0680, L0683). - focusMap->remove( tqApp->tqfocusWidget()->tqtopLevelWidget() ); - focusMap->insert( tqApp->tqfocusWidget()->tqtopLevelWidget(), - new TQGuardedPtr<TQWidget>(tqApp->tqfocusWidget()->tqtopLevelWidget()->tqfocusWidget() ) ); - // L0616: tqApp->tqfocusWidget() might belong to a modal dialog and not be - // equal to tqApp->tqfocusWidget()->tqtopLevelWidget()->tqfocusWidget() ! - tqApp->tqfocusWidget()->clearFocus(); - // L0617: ??? [why not {obeyFocus=false; return true;} here?] - } - obeyFocus = false; - } - break; - case TQEvent::KeyPress: - if (TQT_BASE_OBJECT(tqApp->tqfocusWidget()) == TQT_BASE_OBJECT(o) && - ((QPublicWidget*)tqApp->tqfocusWidget()->tqtopLevelWidget())->topData()->embedded ) { - // L0620: The following code replaces the Qt code that - // handles focus focus changes with the tab key. See the - // XEMBED specification for details. The keypress event - // arrives here after an interesting itinerary. It is first - // saved in the embedding application (L0660). After being - // rejected for tab navigation in the embedding application - // (L1901), it gets forwarded to the embedded client - // (L1400) and arrives here. Depending on the status of - // the tab chain in the embedded client, focus navigation - // messages are sent back to the embedding application - // (L0653, L0654) which then performs tab navigation - // (L2081). - TQKeyEvent *k = (TQKeyEvent *)e; - TQWidget *w = tqApp->tqfocusWidget(); - // L0621: The following tests are copied from TQWidget::event(). - bool res = false; - bool tabForward = true; - if ( !(k->state() & ControlButton || k->state() & AltButton) ) { - if ( k->key() == Key_Backtab || (k->key() == Key_Tab && (k->state() & ShiftButton)) ) { -#ifdef USE_QT4 - res = ((QPublicWidget*)w)->focusNextPrev( tabForward = false ); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Backtab ); - res = ((QPublicWidget*)w)->focusNextPrev( tabForward = false ); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - } else if ( k->key() == Key_Tab ) { -#ifdef USE_QT4 - res = ((QPublicWidget*)w)->focusNextPrev( tabForward = true ); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Tab ); - res = ((QPublicWidget*)w)->focusNextPrev( tabForward = true ); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - } - } - if (res) { - // L0625: We changed the focus because of tab/backtab key - // Now check whether we have been looping around. - TQFocusData *fd = ((QPublicWidget*)w)->focusData(); -#ifdef USE_QT4 - WId window = ((QPublicWidget*)w->tqtopLevelWidget())->effectiveWinId(); -#else // USE_QT4 - WId window = ((QPublicWidget*)w->tqtopLevelWidget())->topData()->parentWinId; -#endif // USE_QT4 - TQWidget *cw = 0; - TQWidget *fw = fd->home(); - if (tabForward && window) { - while (cw != w && cw != fw && cw != w->tqtopLevelWidget()) - cw = fd->prev(); - if (cw != w) - sendXEmbedMessage( window, XEMBED_FOCUS_NEXT ); - } else if (window) { - while (cw != w && cw != fw && cw != w->tqtopLevelWidget()) - cw = fd->next(); - if (cw != w) - sendXEmbedMessage( window, XEMBED_FOCUS_PREV ); - } - // L0628: Qt should no longer process this event. - return true; - } - } - break; - default: - break; - } - // L0640: Application gets to see the events anyway. - return false; -} - -// L0650: This filter receives all XEvents in both the client and the embedder. -// Most of it involves the embedded client (except L0660, L0671). -static int qxembed_x11_event_filter( XEvent* e) -{ - switch ( e->type ) { - case XKeyPress: - case XKeyRelease: { - // L0660: This is for the embedding side (L1450). - last_key_event = e->xkey; - break; - } - case ClientMessage: - if ( e->xclient.message_type == xembed ) { - // L0670: This is where the XEmbed messages are - // processed on the client side. - Time msgtime = (Time) e->xclient.data.l[0]; - long message = e->xclient.data.l[1]; - long detail = e->xclient.data.l[2]; - // L0671: Keep Qt message time up to date - if ( msgtime > GET_QT_X_TIME() ) - SET_QT_X_TIME(msgtime); - TQWidget* w = TQT_TQWIDGET(TQWidget::find( e->xclient.window )); - if ( !w ) - break; - switch ( message) { - case XEMBED_EMBEDDED_NOTIFY: { - // L0675: We just have been embedded into a XEMBED aware widget. - QTLWExtra *extra = ((QPublicWidget*)w->tqtopLevelWidget())->topData(); - extra->embedded = 1; -#ifdef USE_QT4 - // [FIXME] - printf("[FIXME] WId not set in kdelibs/tdeui/qxembed.cpp\n\r"); -#else // USE_QT4 - extra->parentWinId = e->xclient.data.l[3]; -#endif // USE_QT4 - w->tqtopLevelWidget()->show(); - break; - } - case XEMBED_WINDOW_ACTIVATE: { - // L0676: Embedding window becomes active. Send a fake XFocusIn - // to convince Qt that we are active as well. Qt will send - // us a focus notification (L0615) that we will intercept to - // ensure that we have no Qt focus widget yet. The Qt focus - // widget might later be set in L0680. - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xfocus.display = qt_xdisplay(); - ev.xfocus.type = XFocusIn; - ev.xfocus.window = w->tqtopLevelWidget()->winId(); - ev.xfocus.mode = NotifyNormal; - ev.xfocus.detail = NotifyAncestor; - tqApp->x11ProcessEvent( &ev ); - } - break; - case XEMBED_WINDOW_DEACTIVATE: { - // L0677: Embedding window becomes inactive. Send a fake XFocusOut - // event to convince Qt that we no longer are active. We will - // receive extra Qt FocusOut events but we do not care. - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xfocus.display = qt_xdisplay(); - ev.xfocus.type = XFocusOut; - ev.xfocus.window = w->tqtopLevelWidget()->winId(); - ev.xfocus.mode = NotifyNormal; - ev.xfocus.detail = NotifyAncestor; - tqApp->x11ProcessEvent( &ev ); - } - break; - case XEMBED_FOCUS_IN: - // L0680: Embedding application gives us the focus. - { - // L0681: Search saved focus widget. - TQWidget* focusCurrent = 0; - TQGuardedPtr<TQWidget>* fw = focusMap->find( w->tqtopLevelWidget() ); - if ( fw ) { - focusCurrent = *fw; - // L0682: Remove it from the map - focusMap->remove( w->tqtopLevelWidget() ); - } - switch ( detail ) { - case XEMBED_FOCUS_CURRENT: - // L0683: Set focus on saved focus widget - if ( focusCurrent ) { - focusCurrent->setFocus(); - if( QXEmbed* emb = tqt_dynamic_cast< QXEmbed* >( focusCurrent )) - emb->updateEmbeddedFocus( true ); - } - else if ( !w->tqtopLevelWidget()->tqfocusWidget() ) - w->tqtopLevelWidget()->setFocus(); - break; - case XEMBED_FOCUS_FIRST: - { - // L0684: Search first widget in tab chain -#ifdef USE_QT4 - w->tqtopLevelWidget()->setFocus(); - ((QPublicWidget*)w->tqtopLevelWidget())->focusNextPrev(true); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Tab ); - w->tqtopLevelWidget()->setFocus(); - ((QPublicWidget*)w->tqtopLevelWidget())->focusNextPrev(true); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - } - break; - case XEMBED_FOCUS_LAST: - { - // L0686: Search last widget in tab chain -#ifdef USE_QT4 - w->tqtopLevelWidget()->setFocus(); - ((QPublicWidget*)w->tqtopLevelWidget())->focusNextPrev(false); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Backtab ); - w->tqtopLevelWidget()->setFocus(); - ((QPublicWidget*)w->tqtopLevelWidget())->focusNextPrev(false); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - } - break; - default: - break; - } - } - break; - case XEMBED_FOCUS_OUT: - // L0688: Embedding application takes the focus away - // We first record what the focus widget was - // and clear the Qt focus. - if ( w->tqtopLevelWidget()->tqfocusWidget() ) { - if( QXEmbed* emb = tqt_dynamic_cast< QXEmbed* >( w->tqtopLevelWidget()->tqfocusWidget())) - emb->updateEmbeddedFocus( false ); - focusMap->insert( w->tqtopLevelWidget(), - new TQGuardedPtr<TQWidget>(w->tqtopLevelWidget()->tqfocusWidget() ) ); - w->tqtopLevelWidget()->tqfocusWidget()->clearFocus(); - } - break; - default: - break; - } - } else if ( e->xclient.format == 32 && e->xclient.message_type ) { - if ( e->xclient.message_type == qt_wm_protocols ) { - TQWidget* w = TQT_TQWIDGET(TQWidget::find( e->xclient.window )); - if ( !w ) - break; - // L0690: This is for the embedding side! - // See L0902 for more information about the focus proxy. - // Window manager may send WM_TAKE_FOCUS messages to the - // embedding application to indicate that it becomes active. - // But this also suggests that the window manager has - // changed the X11 focus. We want to make sure it goes - // to the focus proxy window eventually. - Atom a = e->xclient.data.l[0]; - if ( a == qt_wm_take_focus ) { - // L0695: update Qt message time variable - if ( (ulong) e->xclient.data.l[1] > GET_QT_X_TIME() ) - SET_QT_X_TIME(e->xclient.data.l[1]); - // L0696: There is no problem when the window is not active. - // Qt will generate a WindowActivate event that will - // do the job (L1310). This does not happen if the - // window is already active. So we simulate it. - if ( w->isActiveWindow() ) { - TQEvent e( TQEvent::WindowActivate ); - TQApplication::sendEvent( w, &e ); - } - } - } - } - break; - default: - break; - } - // L0698: The next x11 filter - if ( oldFilter ) - return oldFilter( e ); - // L0699: Otherwise process the event as usual. - return false; -} - - - -// L0700: Install the xembed filters in both client and embedder sides. -// This function is called automatically when using -// embedClientIntoWindow() or creating an instance of QXEmbed You may -// have to call it manually for a client when using embedder-side -// embedding, though. -void QXEmbed::initialize() -{ - static bool is_initialized = false; - if ( is_initialized ) - return; - - // L0710: Atom used by the XEMBED protocol. - xembed = XInternAtom( qt_xdisplay(), "_XEMBED", false ); - // L0720: Install low level filter for X11 events (L0650) - oldFilter = qt_set_x11_event_filter( qxembed_x11_event_filter ); - // L0730: See L0610 for an explanation about focusMap. - focusMap = new TQPtrDict<TQGuardedPtr<TQWidget> >; - focusMap->setAutoDelete( true ); - // L0740: Create client side application wide event filter (L0610) - filter = new QXEmbedAppFilter; - - is_initialized = true; -} - - - - - -// ------------------------------------------------------------ -// L0800: MOST OF WHAT FOLLOWS CONCERNS THE EMBEDDER SIDE. -// Things that happen inside a Qt application that contain -// a QXEmbed widget for embedding other applications. -// This applies to both the XEMBED and XPLAIN protocols. -// Deviations are commented below. - - - -// L0810: Class QXEmbed. -// A QXEmbed widget serves as an embedder that can manage one single -// embedded X-window. These so-called client windows can be arbitrary -// Qt or non Qt applications. There are two different ways of using -// QXEmbed, from the client side or from the embedder's side. - - -// L0900: Constructs a xembed widget. -QXEmbed::QXEmbed(TQWidget *parent, const char *name, WFlags f) - : TQWidget(parent, name, f) -{ - // L0901: Create private data. See L0100. - d = new QXEmbedData; - // L0902: Create focus proxy widget. See XEmbed specification. - // Each QXEmbed widget has a focus proxy window. Every single - // QXEmbed widget tries to force its focus proxy window onto the - // whole embedding application. They compete between themselves and - // against Qt (L0690, L0914, L1040, L1310, L1510, L1580). - // This would be much simpler if implemented within Qt. - d->focusProxy = new TQWidget( tqtopLevelWidget(), "xembed_focus" ); - d->focusProxy->setGeometry( -1, -1, 1, 1 ); - d->focusProxy->show(); - // make sure it's shown - for XSetInputFocus - TQApplication::sendPostedEvents( d->focusProxy, 0 ); - // L0903: Install the client side event filters - // because they also provide services for the embedder side - // See L0660, L0671, L0685. - initialize(); - window = 0; - setFocusPolicy(TQ_StrongFocus); - setKeyCompression( false ); - - // L0910: Trick Qt to create extraData(); - (void) topData(); - - // L0912: We are mostly interested in SubstructureNotify - // This is sent when something happens to the children of - // the X11 window associated with the QXEmbed widget. - XSelectInput(qt_xdisplay(), winId(), - KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask | - KeymapStateMask | - ButtonMotionMask | - PointerMotionMask | // may need this, too - EnterWindowMask | LeaveWindowMask | - FocusChangeMask | - ExposureMask | - StructureNotifyMask | - SubstructureRedirectMask | - SubstructureNotifyMask - ); - // L0913: all application events pass through eventFilter(). - // This is mostly used to force the X11 focus on the - // proxy focus window. See L1300. - tqtopLevelWidget()->installEventFilter( this ); - tqApp->installEventFilter( this ); - - // L0914: Start moving the X11 focus on the focus proxy window. - // See L1581 to know why we do not use isActiveWindow(). - if ( tqApp->activeWindow() == tqtopLevelWidget() ) - if ( !((QPublicWidget*) tqtopLevelWidget())->topData()->embedded ) - XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), - RevertToParent, GET_QT_X_TIME() ); - // L0915: ??? [drag&drop?] - setAcceptDrops( true ); -} - -// L1000: Destructor must dispose of the embedded client window. -QXEmbed::~QXEmbed() -{ - // L1010: Make sure no pointer grab is left. - if ( d && d->xgrab) - XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() ); - if ( window && ( autoDelete() || !d->xplain )) - { - // L1021: Hide the window and safely reparent it into the root, - // otherwise it would be destroyed by X11 together - // with this QXEmbed's window. -#if 0 -// TODO: The proper XEmbed way would be to unmap the window, and the embedded -// app would detect the embedding has ended, and do whatever it finds appropriate. -// However, QXEmbed currently doesn't provide support for this detection, -// so for the time being, it's better to leave the window mapped as toplevel window. -// This will be ever more complicated with the systray windows, as the simple API -// for them (KWin::setSystemTrayWindowFor()) doesn't make it possible to detect -// themselves they have been released from systray, but KWin requires them -// to be visible to allow next Kicker instance to swallow them. -// See also below the L1022 comment. -// XUnmapWindow( qt_xdisplay(), window ); -#else - if( autoDelete()) - XUnmapWindow( qt_xdisplay(), window ); -#endif - XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0); - if( !d->xplain ) - XRemoveFromSaveSet( qt_xdisplay(), window ); - if( d->mapAfterRelease ) - XMapWindow( qt_xdisplay(), window ); - XSync(qt_xdisplay(), false); - // L1022: Send the WM_DELETE_WINDOW message - if( autoDelete() /*&& d->xplain*/ ) - // This sendDelete should only apply to XPLAIN. - // XEMBED apps are supposed to detect when the embedding ends. - // ??? [We do not do this detection yet! - // So we sendDelete() instead.] - sendDelete(); - } - window = 0; - // L01040: Our focus proxy window will be destroyed as well. - // Make sure that the X11 focus is not lost in the process. - Window focus; - int revert; - XGetInputFocus( qt_xdisplay(), &focus, &revert ); - if( focus == d->focusProxy->winId()) - XSetInputFocus( qt_xdisplay(), tqtopLevelWidget()->winId(), RevertToParent, GET_QT_X_TIME() ); - // L01045: Delete our private data. - delete d; -} - - -// L1050: Sends a WM_DELETE_WINDOW message to the embedded window. This is -// what typically happens when you click on the close button of a -// window manager decoration. -void QXEmbed::sendDelete( void ) -{ - if (window) - { - sendClientMessage(window, qt_wm_protocols, qt_wm_delete_window); - XFlush( qt_xdisplay() ); - } -} - -// L1100: Sets the protocol used for embedding windows. -// This function must be called before embedding a window. -// Protocol XEMBED provides maximal functionality (focus, tabs, etc) -// but requires explicit cooperation from the embedded window. -// Protocol XPLAIN provides maximal compatibility with -// embedded applications that do not support the XEMBED protocol. -// The default is XEMBED. -void QXEmbed::setProtocol( Protocol proto ) -{ - if (!window) { - d->xplain = false; - if (proto == XPLAIN) - d->xplain = true; - } -} - -// L1150: Returns the protocol used for embedding the current window. -QXEmbed::Protocol QXEmbed::protocol() -{ - if (d->xplain) - return XPLAIN; - return XEMBED; -} - - -// L1200: QXEmbed widget size changes: resize embedded window. -void QXEmbed::resizeEvent(TQResizeEvent*) -{ - if (window) - XResizeWindow(qt_xdisplay(), window, width(), height()); -} - -// L1250: QXEmbed widget is shown: make sure embedded window is visible. -void QXEmbed::showEvent(TQShowEvent*) -{ - if (window) - XMapRaised(qt_xdisplay(), window); -} - - -// L1300: This event filter sees all application events (L0913). -bool QXEmbed::eventFilter( TQObject *o, TQEvent * e) -{ - - switch ( e->type() ) { - case TQEvent::WindowActivate: - if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(tqtopLevelWidget()) ) { - // L1310: Qt thinks the application window has just been activated. - // Make sure the X11 focus is on the focus proxy window. See L0686. - if ( !((QPublicWidget*) tqtopLevelWidget())->topData()->embedded ) - if (! hasFocus() ) - XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), - RevertToParent, GET_QT_X_TIME() ); - if (d->xplain) - // L1311: Activation has changed. Grab state might change. See L2800. - checkGrab(); - else - // L1312: Let the client know that we just became active - sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE ); - } - break; - case TQEvent::WindowDeactivate: - if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(tqtopLevelWidget()) ) { - if (d->xplain) - // L1321: Activation has changed. Grab state might change. See L2800. - checkGrab(); - else - // L1322: Let the client know that we are no longer active - sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE ); - } - break; - case TQEvent::Move: - { - TQWidget* pos = this; - while( TQT_BASE_OBJECT(pos) != TQT_BASE_OBJECT(o) && TQT_BASE_OBJECT(pos) != TQT_BASE_OBJECT(tqtopLevelWidget())) - pos = pos->parentWidget(); - if( TQT_BASE_OBJECT(pos) == TQT_BASE_OBJECT(o) ) { - // L1390: Send fake configure notify events whenever the - // global position of the client changes. See L2900. - TQPoint globalPos = mapToGlobal(TQPoint(0,0)); - if (globalPos != d->lastPos) { - d->lastPos = globalPos; - sendSyntheticConfigureNotifyEvent(); - } - } - } - break; - default: - break; - } - return false; -} - -// L1350: ??? [why this?] -bool QXEmbed::event( TQEvent * e) -{ - return TQWidget::event( e ); -} - -// L1400: Forward keypress event to the client -// Receiving a Qt key event indicates that -// the QXEmbed object has the Qt focus. -// The X11 event that caused the Qt key event -// must be forwarded to the client. -// See L0660. -void QXEmbed::keyPressEvent( TQKeyEvent *) -{ - if (!window) - return; - last_key_event.window = window; - XSendEvent(qt_xdisplay(), window, false, KeyPressMask, (XEvent*)&last_key_event); - -} - -// L1450: Forward keyrelease event to the client. -// See comment L1400. -void QXEmbed::keyReleaseEvent( TQKeyEvent *) -{ - if (!window) - return; - last_key_event.window = window; - XSendEvent(qt_xdisplay(), window, false, KeyReleaseMask, (XEvent*)&last_key_event); -} - -// L1500: Handle Qt focus in event. -void QXEmbed::focusInEvent( TQFocusEvent * e ){ - if (!window) - return; - // L1510: This is a good time to set the X11 focus on the focus proxy window. - // Except if the the embedding application itself is embedded into another. - if ( !((QPublicWidget*) tqtopLevelWidget())->topData()->embedded ) - if ( tqApp->activeWindow() == tqtopLevelWidget() ) - // L1511: Alter X focus only when window is active. - // This is dual safety here because FocusIn implies this. - // But see L1581 for an example where this really matters. - XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), - RevertToParent, GET_QT_X_TIME() ); - if (d->xplain) { - // L1520: Qt focus has changed. Grab state might change. See L2800. - checkGrab(); - // L1521: Window managers activate applications by setting the X11 focus. - // We cannot do this (see L1510) but we can send a fake focus event - // and forward the X11 key events ourselves (see L1400, L1450). - sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer ); - } else { - // L1530: No need for fake events with XEMBED. - // Just inform the client. It knows what to do. - int detail = XEMBED_FOCUS_CURRENT; - // L1531: When the focus change is caused by the tab key, - // the client must select the first (or last) widget of - // its own tab chain. - if ( e->reason() == TQFocusEvent::Tab ) - detail = XEMBED_FOCUS_FIRST; - else if ( e->reason() == TQFocusEvent::Backtab ) - detail = XEMBED_FOCUS_LAST; - sendXEmbedMessage( window, XEMBED_FOCUS_IN, detail); - } -} - -// L1550: Handle Qt focus out event. -void QXEmbed::focusOutEvent( TQFocusEvent * ){ - if (!window) - return; - if (d->xplain) { - // L1560: Qt focus has changed. Grab state might change. See L2800. - checkGrab(); - // L1561: Send fake focus out message. See L1521. - sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer ); - } else { - // L1570: Send XEMBED focus out message. See L1531. - sendXEmbedMessage( window, XEMBED_FOCUS_OUT ); - } - // L1580: The QXEmbed object might loose the focus because its - // toplevel window looses the X11 focus and is no longer active, - // or simply because the Qt focus has been moved to another widget. - // In the latter case only, we want to make sure that the X11 focus - // is properly set to the X11 focus widget. We do this because - // the client application might have moved the X11 focus after - // receiving the fake focus messages. - if ( !((QPublicWidget*) tqtopLevelWidget())->topData()->embedded ) - if ( tqApp->activeWindow() == tqtopLevelWidget() ) - // L1581: Alter X focus only when window is active. - // The test above is not the same as isActiveWindow(). - // Function isActiveWindow() also returns true when a modal - // dialog child of this window is active. - XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), - RevertToParent, GET_QT_X_TIME() ); -} - - -// When QXEmbed has TQt focus and gets/loses X focus, make sure the client knows -// about the state of the focus. -void QXEmbed::updateEmbeddedFocus( bool hasfocus ){ - if (!window || d->xplain) - return; - if( hasfocus ) - sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT); - else - sendXEmbedMessage( window, XEMBED_FOCUS_OUT); -} - -// L1600: Helper for QXEmbed::embed() -// Check whether a window is in withdrawn state. -static bool wstate_withdrawn( WId winid ) -{ - Atom type; - int format; - unsigned long length, after; - unsigned char *data; - int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2, - false, AnyPropertyType, &type, &format, - &length, &after, &data ); - bool withdrawn = true; - // L1610: Non managed windows have no WM_STATE property. - // Returning true ensures that the loop L1711 stops. - if ( r == Success && data && format == 32 ) { - TQ_UINT32 *wstate = (TQ_UINT32*)data; - withdrawn = (*wstate == WithdrawnState ); - XFree( (char *)data ); - } - return withdrawn; -} - -// L1650: Helper for QXEmbed::embed() -// Get the X11 id of the parent window. -static int get_parent(WId winid, Window *out_parent) -{ - Window root, *children=0; - unsigned int nchildren; - int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren); - if (st && children) - XFree(children); - return st; -} - -// L1700: Embeds the window w into this QXEmbed widget. -// See doc in qxembed.h. -void QXEmbed::embed(WId w) -{ - kdDebug() << "*** Embed " << w << " into " << winId() << ". window=" << window << endl; - if (!w) - return; - // L1701: The has_window variable prevents embedding a same window twice. - // ??? [what happens if one embed two windows into the same QXEmbed?] - bool has_window = (w == window); - window = w; - if ( !has_window ) { - KXErrorHandler errhandler; // make X BadWindow errors silent - // L1710: Try hard to withdraw the window. - // This makes sure that the window manager will - // no longer try to manage this window. - if ( !wstate_withdrawn(window) ) { - XWithdrawWindow(qt_xdisplay(), window, qt_xscreen()); - TQApplication::flushX(); - // L1711: See L1610 - for (int i=0; i < 10000; ++i) { - if (wstate_withdrawn(window)) { - Window parent = 0; - get_parent(w, &parent); - if (parent == qt_xrootwin()) break; - } - USLEEP(1000); - } - } - // L1710: It would be sufficient in principle to reparent - // window w into winId(). Everything else happens in L2020. - // The following code might be useful when the X11 server takes - // time to create the embedded application main window. - Window parent = 0; - get_parent(w, &parent); - kdDebug() << TQString(TQString("> before reparent: parent=0x%1").arg(parent,0,16)) << endl; - for (int i = 0; i < 50; i++) { - // this is done once more when finishing embedding, but it's done also here - // just in case we crash before reaching that place - if( !d->xplain ) - XAddToSaveSet( qt_xdisplay(), w ); - XReparentWindow(qt_xdisplay(), w, winId(), 0, 0); - if (get_parent(w, &parent) && parent == winId()) { - kdDebug() << TQString(TQString("> Loop %1: ").arg(i)) - << TQString(TQString("> reparent of 0x%1").arg(w,0,16)) - << TQString(TQString(" into 0x%1").arg(winId(),0,16)) - << TQString(" successful") << endl; - break; - } - kdDebug() << TQString(TQString("> Loop %1: ").arg(i)) - << TQString(TQString("> reparent of 0x%1").arg(w,0,16)) - << TQString(TQString(" into 0x%1").arg(winId(),0,16)) - << TQString(" failed") << endl; - USLEEP(1000); - } - if( parent != winId()) // failed - window = 0; - } -} - -// When a window is reparented into QXEmbed (or created inside of it), this function -// sets up the actual embedding. -void QXEmbed::handleEmbed() -{ - // only XEMBED apps can survive crash, - // see http://lists.kde.org/?l=kfm-devel&m=106752026501968&w=2 - if( !d->xplain ) - XAddToSaveSet( qt_xdisplay(), window ); - XResizeWindow(qt_xdisplay(), window, width(), height()); - XMapRaised(qt_xdisplay(), window); - // L2024: see L2900. - sendSyntheticConfigureNotifyEvent(); - // L2025: ??? [any idea about drag&drop?] - extraData()->xDndProxy = window; - if ( parent() ) { - // L2030: embedded window might have new size requirements. - // see L2500, L2520, L2550. - TQEvent * layoutHint = new TQEvent( TQEvent::LayoutHint ); - TQApplication::postEvent( parent(), layoutHint ); - } - windowChanged( window ); - if (d->xplain) { - // L2040: Activation has changed. Grab state might change. See L2800. - checkGrab(); - if ( hasFocus() ) - // L2041: Send fake focus message to inform the client. See L1521. - sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer ); - } else { - // L2050: Send XEMBED messages (see L0670, L1312, L1322, L1530) - sendXEmbedMessage( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() ); - if (isActiveWindow()) - sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE); - else - sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE); - if ( hasFocus() ) - sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT ); - } -} - -// L1800: Returns the window identifier of the embedded window -WId QXEmbed::embeddedWinId() const -{ - return window; -} - - -// L1900: Control Qt tab focus management. -// See Qt documentation. -bool QXEmbed::focusNextPrevChild( bool next ) -{ - if ( window ) - // L1901: Return false when there is an embedded window - // When the user presses TAB, Qt will not change - // the focus and pass the TAB key events to the QXEmbed widget. - // These key events will be forwarded to the client (L1400, L1450) - // who eventually will manage the tab focus (L0620) and possible - // instruct us to call TQWidget::focusNextPrevChild (L2081). - return false; - else - // L1920: Default behavior otherwise. - return TQWidget::focusNextPrevChild( next ); -} - - -// L2000: Filter for X11 events sent to the QXEmbed window. -bool QXEmbed::x11Event( XEvent* e) -{ - switch ( e->type ) { - case DestroyNotify: - if ( e->xdestroywindow.window == window ) { - // L2005: Client window is being destroyed. - window = 0; - windowChanged( window ); - emit embeddedWindowDestroyed(); - } - break; - case CreateNotify: - // A window was created inside of QXEmbed, handle it as embedded - if( window == 0 ) { // only one window - window = e->xcreatewindow.window; - handleEmbed(); - } - break; - case ReparentNotify: - if ( e->xreparent.window == d->focusProxy->winId() ) - break; // ignore proxy - if ( window && e->xreparent.window == window && - e->xreparent.parent != winId() ) { - // L2010: We lost the window - window = 0; - windowChanged( window ); - emit embeddedWindowDestroyed(); - // L2011: Remove window from save set - // ??? [not sure it is good to touch this window since - // someone else has taken control of it already.] - if( !d->xplain ) - XRemoveFromSaveSet( qt_xdisplay(), window ); - } else if ( e->xreparent.parent == winId()){ - if( window == 0 ) // something started embedding from the outside - window = e->xreparent.window; - // L2020: We got a window. Complete the embedding process. - if( e->xreparent.window == window ) - handleEmbed(); - } - break; - case ButtonPress: - if (d->xplain && d->xgrab) { - // L2060: The passive grab has intercepted a mouse click - // in the embedded client window. Take the focus. -#ifdef USE_QT4 - setFocus(); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Mouse ); - setFocus(); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - // L2064: Resume X11 event processing. - XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime); - // L2065: Qt should not know about this. - return true; - } - break; - case ButtonRelease: - if (d->xplain && d->xgrab) { - // L2064: Resume X11 event processing after passive grab (see L2060) - XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime); - return true; - } - break; - case MapRequest: - // L2070: Behave like a window manager. - if ( window && e->xmaprequest.window == window ) - XMapRaised(qt_xdisplay(), window ); - break; - case ClientMessage: - // L2080: This is where the QXEmbed object receives XEMBED - // messaged from the client application. - if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) { - long message = e->xclient.data.l[1]; - switch ( message ) { - // L2081: Tab focus management. It is very important to call the - // focusNextPrevChild() defined by TQWidget (not QXEmbed). - // See L1901. - case XEMBED_FOCUS_NEXT: - TQWidget::focusNextPrevChild( true ); - break; - case XEMBED_FOCUS_PREV: - TQWidget::focusNextPrevChild( false ); - break; - // L2085: The client asks for the focus. - case XEMBED_REQUEST_FOCUS: - if( ((QPublicWidget*)tqtopLevelWidget())->topData()->embedded ) { - focusMap->remove( tqtopLevelWidget() ); - focusMap->insert( tqtopLevelWidget(), new TQGuardedPtr<TQWidget>( this )); -#ifdef USE_QT4 - WId window = ((QPublicWidget*)tqtopLevelWidget())->effectiveWinId(); -#else // USE_QT4 - WId window = ((QPublicWidget*)tqtopLevelWidget())->topData()->parentWinId; -#endif // USE_QT4 - sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS ); - } else { -#ifdef USE_QT4 - setFocus(); -#else // USE_QT4 - TQFocusEvent::setReason( TQFocusEvent::Mouse ); - setFocus(); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - } - break; - default: - break; - } - } - break; - - case ConfigureRequest: - // L2090: Client wants to change its geometry. - // Just inform it that nothing has changed. - if (e->xconfigurerequest.window == window) - { - sendSyntheticConfigureNotifyEvent(); - } - break; - case MotionNotify: - // fall through, workaround for Qt 3.0 < 3.0.3 - case EnterNotify: - // L2095: See L2200. - if ( TQWhatsThis::inWhatsThisMode() ) - enterWhatsThisMode(); - break; - default: - break; - } - return false; -} - - -// L2200: Try to handle Qt's "what's this" mode. Broken. -// "temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000" -void QXEmbed::enterWhatsThisMode() -{ - // L2210: When the what-s-this pointer enters the embedded window (L2095) - // cancel what-s-this mode, and use a non stantard _NET_WM_ message - // to instruct the embedded client to enter the "what's this" mode. - // This works only one way... - TQWhatsThis::leaveWhatsThisMode(); - if ( !context_help ) - context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", false ); - sendClientMessage(window , qt_wm_protocols, context_help ); -} - - -// L2300: indicates that the embedded window has been changed. -void QXEmbed::windowChanged( WId ) -{ -} - - -// L2400: Utility function for clients that embed themselves. -// This is client side code. -bool QXEmbed::processClientCmdline( TQWidget* client, int& argc, char ** argv ) -{ - int myargc = argc; - WId window = 0; - int i, j; - - j = 1; - for ( i=1; i<myargc; i++ ) { - if ( argv[i] && *argv[i] != '-' ) { - argv[j++] = argv[i]; - continue; - } - TQCString arg = argv[i]; - if ( !strcmp(arg,"-embed") && i < myargc-1 ) { - TQCString s = argv[++i]; - window = s.toInt(); - } else - argv[j++] = argv[i]; - } - argc = j; - - if ( window ) { - embedClientIntoWindow( client, window ); - return true; - } - - return false; -} - - -// L2450: Utility function for clients that embed themselves. -// This is client side code. -void QXEmbed::embedClientIntoWindow(TQWidget* client, WId window) -{ - initialize(); - XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0); - // L2451: These two lines are redundant. See L0680. - ((QXEmbed*)client)->topData()->embedded = true; -#ifdef USE_QT4 - // [FIXME] - printf("[FIXME] WId not set in kdelibs/tdeui/qxembed.cpp\n\r"); -#else // USE_QT4 - ((QXEmbed*)client)->topData()->parentWinId = window; -#endif // USE_QT4 - // L2452: This seems redundant because L2020 maps the window. - // But calling show() might also set Qt internal flags. - client->show(); -} - - - -// L2500: Specifies that this widget can use additional space, -// and that it can survive on less than tqsizeHint(). -TQSizePolicy QXEmbed::sizePolicy() const -{ - return TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding ); -} - - -// L2520: Returns a size sufficient for the embedded window -TQSize QXEmbed::tqsizeHint() const -{ - return tqminimumSizeHint(); -} - -// L2550: Returns the minimum size specified by the embedded window. -TQSize QXEmbed::tqminimumSizeHint() const -{ - int minw = 0; - int minh = 0; - if ( window ) { - XSizeHints size; - long msize; - if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize) - && ( size.flags & PMinSize) ) { - minw = size.min_width; - minh = size.min_height; - } - } - - return TQSize( minw, minh ); -} - -// L2600: Tells what shoud be done with the embedded window when -// the embedding window is destroyed. -void QXEmbed::setAutoDelete( bool b) -{ - d->autoDelete = b; -} - -// L2650: See L2600. -bool QXEmbed::autoDelete() const -{ - return d->autoDelete; -} - -// L2700: See L2200. -bool QXEmbed::customWhatsThis() const -{ - return true; -} - -// L2800: When using the XPLAIN protocol, this function maintains -// a passive button grab when (1) the application is active -// and (2) the Qt focus is not on the QXEmbed. This passive -// grab intercepts button clicks in the client window and -// give us chance to request the Qt focus (L2060). -void QXEmbed::checkGrab() -{ - if (d->xplain && isActiveWindow() && !hasFocus()) { - if (! d->xgrab) - XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(), - false, ButtonPressMask, GrabModeSync, GrabModeAsync, - None, None ); - d->xgrab = true; - } else { - if (d->xgrab) - XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() ); - d->xgrab = false; - } -} - -// L2900: This sends fake configure notify events to inform -// the client about its window geometry. See L1390, L2024 and L2090. -void QXEmbed::sendSyntheticConfigureNotifyEvent() -{ - // L2910: It seems that the x and y coordinates are global. - // But this is what ICCCM section 4.1.5 wants. - // See http://lists.kde.org/?l=kfm-devel&m=107090222032378 - TQPoint globalPos = mapToGlobal(TQPoint(0,0)); - if (window) { -#if 0 - XConfigureEvent c; - memset(&c, 0, sizeof(c)); - c.type = ConfigureNotify; - c.display = qt_xdisplay(); - c.send_event = True; - c.event = window; - c.window = window; - c.x = globalPos.x(); - c.y = globalPos.y(); - c.width = width(); - c.height = height(); - c.border_width = 0; - c.above = None; - c.override_redirect = 0; - XSendEvent( qt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c ); -#endif - // Yes, this doesn't make sense at all. See the commit message. - XSetWindowBorderWidth( qt_xdisplay(), window, 1 ); - XSetWindowBorderWidth( qt_xdisplay(), window, 0 ); - } -} - -// L3000: One should not call TQWidget::reparent after embedding a window. -void QXEmbed::reparent( TQWidget * parent, WFlags f, const TQPoint & p, bool showIt ) -{ - // TQWidget::reparent() destroys the old X Window for the widget, and - // creates a new one, thus QXEmbed after reparenting is no longer the - // parent of the embedded window. I think reparenting of QXEmbed can be - // done only by a mistake, so just complain. - Q_ASSERT( !window ); - TQWidget::reparent( parent, f, p, showIt ); -} - -// for KDE -#include "qxembed.moc" -#endif // Q_WS_X11 |