src/gui/kernel/qx11embed_x11.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/kernel/qx11embed_x11.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1804 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qx11embed_x11.h"
+#include <qapplication.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qdatetime.h>
+#include <qpointer.h>
+#include <qdebug.h>
+#include <qx11info_x11.h>
+#include <private/qt_x11_p.h>
+#include <private/qwidget_p.h>
+
+#define XK_MISCELLANY
+#define XK_LATIN1
+#define None 0
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/keysymdef.h>
+#include <X11/X.h>
+
+#ifndef XK_ISO_Left_Tab
+#define XK_ISO_Left_Tab 0xFE20
+#endif
+
+//#define QX11EMBED_DEBUG
+#ifdef QX11EMBED_DEBUG
+#include <qdebug.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+    \class QX11EmbedWidget
+    \ingroup advanced
+
+    \brief The QX11EmbedWidget class provides an XEmbed client widget.
+
+    XEmbed is an X11 protocol that supports the embedding of a widget
+    from one application into another application.
+
+    An XEmbed \e{client widget} is a window that is embedded into a
+    \e container. A container is the graphical location that embeds
+    (or \e swallows) an external application.
+
+    QX11EmbedWidget is a widget used for writing XEmbed applets or
+    plugins. When it has been embedded and the container receives tab
+    focus, focus is passed on to the widget. When the widget reaches
+    the end of its focus chain, focus is passed back to the
+    container. Window activation, accelerator support, modality and
+    drag and drop (XDND) are also handled.
+
+    The widget and container can both initiate the embedding. If the
+    widget is the initiator, the X11 window ID of the container that
+    it wants to embed itself into must be passed to embedInto().
+
+    If the container initiates the embedding, the window ID of the
+    embedded widget must be known. The container calls embed(),
+    passing the window ID.
+
+    This example shows an application that embeds a QX11EmbedWidget
+    subclass into the window whose ID is passed as a command-line
+    argument:
+
+    \snippet doc/src/snippets/qx11embedwidget/main.cpp 0
+
+    The problem of obtaining the window IDs is often solved by the
+    container invoking the application that provides the widget as a
+    separate process (as a panel invokes a docked applet), passing
+    its window ID to the new process as a command-line argument. The
+    new process can then call embedInto() with the container's window
+    ID, as shown in the example code above. Similarly, the new
+    process can report its window ID to the container through IPC, in
+    which case the container can embed the widget.
+
+    When the widget has been embedded, it emits the signal
+    embedded(). If it is closed by the container, the widget emits
+    containerClosed(). If an error occurs when embedding, error() is
+    emitted.
+
+    There are XEmbed widgets available for KDE and GTK+. The GTK+
+    equivalent of QX11EmbedWidget is GtkPlug. The corresponding KDE 3
+    widget is called QXEmbed.
+
+    \sa QX11EmbedContainer, {XEmbed Specification}
+*/
+
+/*!
+    \class QX11EmbedContainer
+    \ingroup advanced
+
+    \brief The QX11EmbedContainer class provides an XEmbed container
+    widget.
+
+    XEmbed is an X11 protocol that supports the embedding of a widget
+    from one application into another application.
+
+    An XEmbed \e container is the graphical location that embeds an
+    external \e {client widget}. A client widget is a window that is
+    embedded into a container.
+
+    When a widget has been embedded and the container receives tab
+    focus, focus is passed on to the widget. When the widget reaches
+    the end of its focus chain, focus is passed back to the
+    container. Window activation, accelerator support, modality and
+    drag and drop (XDND) are also handled.
+
+    QX11EmbedContainer is commonly used for writing panels or
+    toolbars that hold applets, or for \e swallowing X11
+    applications. When writing a panel application, one container
+    widget is created on the toolbar, and it can then either swallow
+    another widget using embed(), or allow an XEmbed widget to be
+    embedded into itself. The container's X11 window ID, which is
+    retrieved with winId(), must then be known to the client widget.
+    After embedding, the client's window ID can be retrieved with
+    clientWinId().
+
+    In the following example, a container widget is created as the
+    main widget. It then invokes an application called "playmovie",
+    passing its window ID as a command line argument. The "playmovie"
+    program is an XEmbed client widget. The widget embeds itself into
+    the container using the container's window ID.
+
+    \snippet doc/src/snippets/qx11embedcontainer/main.cpp 0
+
+    When the client widget is embedded, the container emits the
+    signal clientIsEmbedded(). The signal clientClosed() is emitted
+    when a widget is closed.
+
+    It is possible for QX11EmbedContainer to embed XEmbed widgets
+    from toolkits other than Qt, such as GTK+. Arbitrary (non-XEmbed)
+    X11 widgets can also be embedded, but the XEmbed-specific
+    features such as window activation and focus handling are then
+    lost.
+
+    The GTK+ equivalent of QX11EmbedContainer is GtkSocket. The
+    corresponding KDE 3 widget is called QXEmbed.
+
+    \sa QX11EmbedWidget, {XEmbed Specification}
+*/
+
+/*! \fn void QX11EmbedWidget::embedded()
+
+    This signal is emitted by the widget that has been embedded by an
+    XEmbed container.
+*/
+
+/*! \fn void QX11EmbedWidget::containerClosed()
+
+    This signal is emitted by the client widget when the container
+    closes the widget. This can happen if the container itself
+    closes, or if the widget is rejected.
+
+    The container can reject a widget for any reason, but the most
+    common cause of a rejection is when an attempt is made to embed a
+    widget into a container that already has an embedded widget.
+*/
+
+/*! \fn void QX11EmbedContainer::clientIsEmbedded()
+
+    This signal is emitted by the container when a client widget has
+    been embedded.
+*/
+
+/*! \fn void QX11EmbedContainer::clientClosed()
+
+    This signal is emitted by the container when the client widget
+    closes.
+*/
+
+/*!
+    \fn void QX11EmbedWidget::error(QX11EmbedWidget::Error error)
+
+    This signal is emitted if an error occurred as a result of
+    embedding into or communicating with a container. The specified
+    \a error describes the problem that occurred.
+
+    \sa QX11EmbedWidget::Error
+*/
+
+/*!
+    \fn QX11EmbedContainer::Error QX11EmbedContainer::error() const
+
+    Returns the last error that occurred.
+*/
+
+/*! \fn void QX11EmbedContainer::error(QX11EmbedContainer::Error error)
+
+    This signal is emitted if an error occurred when embedding or
+    communicating with a client. The specified \a error describes the
+    problem that occurred.
+
+    \sa QX11EmbedContainer::Error
+*/
+
+/*!
+    \enum QX11EmbedWidget::Error
+
+    \value Unknown An unrecognized error occurred.
+
+    \value InvalidWindowID The X11 window ID of the container was
+        invalid. This error is usually triggered by passing an invalid
+        window ID to embedInto().
+
+    \omitvalue Internal
+*/
+
+/*!
+    \enum QX11EmbedContainer::Error
+
+    \value Unknown An unrecognized error occurred.
+
+    \value InvalidWindowID The X11 window ID of the container was
+        invalid. This error is usually triggered by passing an invalid
+        window ID to embed().
+
+    \omitvalue Internal
+*/
+
+const int XButtonPress = ButtonPress;
+const int XButtonRelease = ButtonRelease;
+#undef ButtonPress
+#undef ButtonRelease
+
+// This is a hack to move topData() out from QWidgetPrivate to public.  We
+// need to to inspect window()'s embedded state.
+class QHackWidget : public QWidget
+{
+    Q_DECLARE_PRIVATE(QWidget)
+public:
+    QTLWExtra* topData() { return d_func()->topData(); }
+};
+
+static unsigned int XEMBED_VERSION = 0;
+
+enum QX11EmbedMessageType {
+    XEMBED_EMBEDDED_NOTIFY = 0,
+    XEMBED_WINDOW_ACTIVATE = 1,
+    XEMBED_WINDOW_DEACTIVATE = 2,
+    XEMBED_REQUEST_FOCUS = 3,
+    XEMBED_FOCUS_IN = 4,
+    XEMBED_FOCUS_OUT = 5,
+    XEMBED_FOCUS_NEXT = 6,
+    XEMBED_FOCUS_PREV = 7,
+    XEMBED_MODALITY_ON = 10,
+    XEMBED_MODALITY_OFF = 11,
+    XEMBED_REGISTER_ACCELERATOR = 12,
+    XEMBED_UNREGISTER_ACCELERATOR = 13,
+    XEMBED_ACTIVATE_ACCELERATOR = 14
+};
+
+enum QX11EmbedFocusInDetail {
+    XEMBED_FOCUS_CURRENT = 0,
+    XEMBED_FOCUS_FIRST = 1,
+    XEMBED_FOCUS_LAST = 2
+};
+
+enum QX11EmbedFocusInFlags {
+    XEMBED_FOCUS_OTHER = (0 << 0),
+    XEMBED_FOCUS_WRAPAROUND = (1 << 0)
+};
+
+enum QX11EmbedInfoFlags {
+    XEMBED_MAPPED = (1 << 0)
+};
+
+enum QX11EmbedAccelModifiers {
+    XEMBED_MODIFIER_SHIFT = (1 << 0),
+    XEMBED_MODIFIER_CONTROL = (1 << 1),
+    XEMBED_MODIFIER_ALT = (1 << 2),
+    XEMBED_MODIFIER_SUPER = (1 << 3),
+    XEMBED_MODIFIER_HYPER = (1 << 4)
+};
+
+enum QX11EmbedAccelFlags {
+    XEMBED_ACCELERATOR_OVERLOADED = (1 << 0)
+};
+
+// Silence the default X11 error handler.
+static int x11ErrorHandler(Display *, XErrorEvent *)
+{
+    return 0;
+}
+
+// Returns the X11 timestamp. Maintained mainly by qapplication
+// internals, but also updated by the XEmbed widgets.
+static Time x11Time()
+{
+    return qt_x11Data->time;
+}
+
+// Gives the version and flags of the supported XEmbed protocol.
+static unsigned int XEmbedVersion()
+{
+    return 0;
+}
+
+// Sends an XEmbed message.
+static void sendXEmbedMessage(WId window, Display *display, long message,
+                  long detail = 0, long data1 = 0, long data2 = 0)
+{
+    XClientMessageEvent c;
+    memset(&c, 0, sizeof(c));
+    c.type = ClientMessage;
+    c.message_type = ATOM(_XEMBED);
+    c.format = 32;
+    c.display = display;
+    c.window = window;
+
+    c.data.l[0] = x11Time();
+    c.data.l[1] = message;
+    c.data.l[2] = detail;
+    c.data.l[3] = data1;
+    c.data.l[4] = data2;
+
+    XSendEvent(display, window, false, NoEventMask, (XEvent *) &c);
+}
+
+// From qapplication_x11.cpp
+static XKeyEvent lastKeyEvent;
+
+static QCoreApplication::EventFilter oldX11EventFilter;
+
+// The purpose of this global x11 filter is for one to capture the key
+// events in their original state, but most importantly this is the
+// only way to get the WM_TAKE_FOCUS message from WM_PROTOCOLS.
+static bool x11EventFilter(void *message, long *result)
+{
+    XEvent *event = reinterpret_cast<XEvent *>(message);
+    if (event->type == XKeyPress || event->type == XKeyRelease)
+	lastKeyEvent = event->xkey;
+
+    if (oldX11EventFilter && oldX11EventFilter != &x11EventFilter)
+	return oldX11EventFilter(message, result);
+    else
+	return false;
+}
+
+//
+struct functorData
+{
+    Window id, rootWindow;
+    bool clearedWmState;
+    bool reparentedToRoot;
+};
+
+static Bool functor(Display *display, XEvent *event, XPointer arg)
+{
+    functorData *data = (functorData *) arg;
+
+    if (!data->reparentedToRoot && event->type == ReparentNotify
+        && event->xreparent.window == data->id
+        && event->xreparent.parent == data->rootWindow) {
+        data->reparentedToRoot = true;
+        return true;
+    }
+
+    if (!data->clearedWmState
+        && event->type == PropertyNotify
+        && event->xproperty.window == data->id
+        && event->xproperty.atom == ATOM(WM_STATE)) {
+	if (event->xproperty.state == PropertyDelete) {
+            data->clearedWmState = true;
+            return true;
+        }
+
+	Atom ret;
+	int format, status;
+	unsigned char *retval;
+	unsigned long nitems, after;
+	status = XGetWindowProperty(display, data->id, ATOM(WM_STATE), 0, 2, False, ATOM(WM_STATE),
+				    &ret, &format, &nitems, &after, &retval );
+	if (status == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) {
+            long *state = (long *)retval;
+	    if (state[0] == WithdrawnState) {
+                data->clearedWmState = true;
+		return true;
+            }
+	}
+    }
+
+    return false;
+}
+
+class QX11EmbedWidgetPrivate : public QWidgetPrivate
+{
+    Q_DECLARE_PUBLIC(QX11EmbedWidget)
+public:
+    inline QX11EmbedWidgetPrivate()
+    {
+        lastError = QX11EmbedWidget::Unknown;
+        container = 0;
+    }
+
+    void setEmbedded();
+
+    void emitError(QX11EmbedWidget::Error error) {
+        Q_Q(QX11EmbedWidget);
+
+        lastError = error;
+        emit q->error(error);
+    }
+
+    enum FocusWidgets {
+        FirstFocusWidget,
+        LastFocusWidget
+    };
+
+    int focusOriginator;
+    QWidget *getFocusWidget(FocusWidgets fw);
+    void checkActivateWindow(QObject *o);
+    QX11EmbedWidget *xEmbedWidget(QObject *o) const;
+    void clearFocus();
+
+    WId container;
+    QPointer<QWidget> currentFocus;
+
+    QX11EmbedWidget::Error lastError;
+
+};
+
+/*!
+    Constructs a QX11EmbedWidget object with the given \a parent.
+*/
+QX11EmbedWidget::QX11EmbedWidget(QWidget *parent)
+    : QWidget(*new QX11EmbedWidgetPrivate, parent, 0)
+{
+    XSetErrorHandler(x11ErrorHandler);
+
+    setAttribute(Qt::WA_NativeWindow);
+    setAttribute(Qt::WA_DontCreateNativeAncestors);
+    createWinId();
+    XSelectInput(x11Info().display(), internalWinId(),
+                 KeyPressMask | KeyReleaseMask | ButtonPressMask
+                    | ButtonReleaseMask
+                    | KeymapStateMask | ButtonMotionMask | PointerMotionMask
+                    | FocusChangeMask
+                    | ExposureMask | StructureNotifyMask
+                    | SubstructureNotifyMask | PropertyChangeMask);
+
+    long data[] = {XEMBED_VERSION, XEMBED_MAPPED};
+    XChangeProperty(x11Info().display(), internalWinId(), ATOM(_XEMBED_INFO),
+                    ATOM(_XEMBED_INFO), 32, PropModeReplace,
+                    (unsigned char*) data, 2);
+
+    setFocusPolicy(Qt::StrongFocus);
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+    QApplication::instance()->installEventFilter(this);
+
+#ifdef QX11EMBED_DEBUG
+    qDebug() << "QX11EmbedWidget::QX11EmbedWidget: constructed client"
+             << (void *)this << "with winId" << winId();
+#endif
+}
+
+/*!
+    Destructs the QX11EmbedWidget object. If the widget is embedded
+    when deleted, it is hidden and then detached from its container,
+    so that the container is free to embed a new widget.
+*/
+QX11EmbedWidget::~QX11EmbedWidget()
+{
+    Q_D(QX11EmbedWidget);
+    if (d->container) {
+#ifdef QX11EMBED_DEBUG
+        qDebug() << "QX11EmbedWidget::~QX11EmbedWidget: unmapping"
+                 << (void *)this << "with winId" << winId()
+                 << "from container with winId" << d->container;
+#endif
+        XUnmapWindow(x11Info().display(), internalWinId());
+        XReparentWindow(x11Info().display(), internalWinId(), x11Info().appRootWindow(), 0, 0);
+    }
+
+#ifdef QX11EMBED_DEBUG
+    qDebug() << "QX11EmbedWidget::~QX11EmbedWidget: destructed client"
+             << (void *)this << "with winId" << winId();
+#endif
+}
+
+/*!
+    Returns the type of error that occurred last. This is the same error code
+    that is emitted by the error() signal.
+
+    \sa Error
+*/
+QX11EmbedWidget::Error QX11EmbedWidget::error() const
+{
+    return d_func()->lastError;
+}
+
+/*!
+    When this function is called, the widget embeds itself into the
+    container whose window ID is \a id.
+
+    If \a id is \e not the window ID of a container this function will
+    behave unpredictably.
+*/
+void QX11EmbedWidget::embedInto(WId id)
+{
+    Q_D(QX11EmbedWidget);
+#ifdef QX11EMBED_DEBUG
+    qDebug() << "QX11EmbedWidget::embedInto: embedding client"
+             << (void *)this << "with winId" << winId() << "into container"
+             << id;
+#endif
+
+    d->container = id;
+    switch (XReparentWindow(x11Info().display(), internalWinId(), d->container, 0, 0)) {
+    case BadWindow:
+        d->emitError(InvalidWindowID);
+        break;
+    case BadMatch:
+        d->emitError(Internal);
+        break;
+    case Success:
+    default:
+        break;
+    }
+    QTLWExtra* x = d->extra ? d->extra->topextra : 0;
+    if (x)
+        x->frameStrut.setCoords(0, 0, 0, 0);
+    d->data.fstrut_dirty = false;
+}
+
+/*! \internal
+
+    Gets the first or last child widget that can get focus.
+*/
+QWidget *QX11EmbedWidgetPrivate::getFocusWidget(FocusWidgets fw)
+{
+    Q_Q(QX11EmbedWidget);
+    QWidget *tlw = q;
+    QWidget *w = tlw->nextInFocusChain();
+
+    QWidget *last = tlw;
+
+    extern bool qt_tab_all_widgets;
+    uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
+
+    while (w != tlw)
+    {
+        if (((w->focusPolicy() & focus_flag) == focus_flag)
+            && w->isVisibleTo(q) && w->isEnabled())
+        {
+            last = w;
+            if (fw == FirstFocusWidget)
+                break;
+        }
+        w = w->nextInFocusChain();
+    }
+
+    return last;
+}
+
+/*! \internal
+
+    Returns the xembed widget that the widget is a child of
+*/
+QX11EmbedWidget *QX11EmbedWidgetPrivate::xEmbedWidget(QObject *o) const
+{
+    QX11EmbedWidget *xec = 0;
+
+    // Check the widget itself, then its parents, and find the first
+    // QX11EmbedWidget.
+    do {
+        if ((xec = qobject_cast<QX11EmbedWidget *>(o)))
+            return xec;
+    } while ((o = o->parent()));
+    return 0;
+}
+
+/*! \internal
+
+    Checks the active window.
+*/
+void QX11EmbedWidgetPrivate::checkActivateWindow(QObject *o)
+{
+    Q_Q(QX11EmbedWidget);
+    QX11EmbedWidget *xec = xEmbedWidget(o);
+
+    // check if we are in the right xembed client
+    if (q != xec)
+        return;
+
+    QWidget *w = qobject_cast<QWidget *>(o);
+
+    // if it is no active window, then don't do the change
+    if (!(w && qApp->activeWindow()))
+        return;
+
+    // if it already is the active window, don't do anything
+    if (w->window() != qApp->activeWindow())
+    {
+        qApp->setActiveWindow(w->window());
+        currentFocus = w;
+
+        sendXEmbedMessage(xec->containerWinId(), q->x11Info().display(), XEMBED_REQUEST_FOCUS);
+    }
+}
+
+/*! \internal
+
+    Clears the focus
+*/
+void QX11EmbedWidgetPrivate::clearFocus()
+{
+    Q_Q(QX11EmbedWidget);
+    // Setting focus on the client itself removes Qt's
+    // logical focus rectangle. We can't just do a
+    // clearFocus here, because when we send the synthetic
+    // FocusIn to ourselves on activation, Qt will set
+    // focus on focusWidget() again. This way, we "hide"
+    // focus rather than clearing it.
+
+    if (!q->window()->hasFocus())
+        q->window()->setFocus(Qt::OtherFocusReason);
+
+    currentFocus = 0;
+}
+
+/*! \internal
+
+    Sets the embedded flag on the client.
+*/
+void QX11EmbedWidgetPrivate::setEmbedded()
+{
+    Q_Q(QX11EmbedWidget);
+    ((QHackWidget *)q->window())->topData()->embedded = 1;
+}
+
+/*! \internal
+
+    Handles WindowActivate and FocusIn events for the client.
+*/
+bool QX11EmbedWidget::eventFilter(QObject *o, QEvent *event)
+{
+    Q_D(QX11EmbedWidget);
+    switch (event->type()) {
+    case QEvent::FocusIn:
+        switch (((QFocusEvent *)event)->reason()) {
+        case Qt::MouseFocusReason:
+            // If the user clicks into one of the client widget's
+            // children and we didn't have focus already, we request
+            // focus from our container.
+            if (d->xEmbedWidget(o) == this) {
+                if (d->currentFocus.isNull())
+                    sendXEmbedMessage(d->container, x11Info().display(), XEMBED_REQUEST_FOCUS);
+
+                d->currentFocus = qobject_cast<QWidget *>(o);
+            }
+            break;
+        case Qt::TabFocusReason:
+            // If the xembed client receives a focus event because of
+            // a Tab, then we are at the end of our focus chain and we
+            // ask the container to move to its next focus widget.
+            if (o == this) {
+                d->clearFocus();
+                sendXEmbedMessage(d->container, x11Info().display(), XEMBED_FOCUS_NEXT);
+                return true;
+            } else {
+                // We're listening on events from qApp, so in order
+                // for us to know who to set focus on if we receive an
+                // activation event, we note the widget that got the
+                // focusin last.
+                if (d->xEmbedWidget(o) == this)
+                    d->currentFocus = qobject_cast<QWidget *>(o);
+            }
+            break;
+        case Qt::BacktabFocusReason:
+            // If the window receives a focus event because of
+            // a Backtab, then we are at the start of our focus chain
+            // and we ask the container to move to its previous focus
+            // widget.
+            if (o == this) {
+                // See comment for Tab.
+                // If we receive a XEMBED_FOCUS_IN
+                // XEMBED_FOCUS_CURRENT, we will set focus in
+                // currentFocus. To avoid that in this case, we reset
+                // currentFocus.
+                d->clearFocus();
+                sendXEmbedMessage(d->container, x11Info().display(), XEMBED_FOCUS_PREV);
+                return true;
+            } else {
+                if (d->xEmbedWidget(o) == this)
+                    d->currentFocus = qobject_cast<QWidget *>(o);
+            }
+            break;
+        case Qt::ActiveWindowFocusReason:
+            if (isActiveWindow()) {
+                if (!d->currentFocus.isNull()) {
+                    if (!d->currentFocus->hasFocus())
+                        d->currentFocus->setFocus(Qt::OtherFocusReason);
+                } else {
+                    d->clearFocus();
+                    return true;
+                }
+            }
+
+            break;
+        case Qt::PopupFocusReason:
+        case Qt::ShortcutFocusReason:
+        case Qt::OtherFocusReason:
+            // If focus is received to any child widget because of any
+            // other reason, remember the widget so that we can give
+            // it focus again if we're activated.
+            if (d->xEmbedWidget(o) == this) {
+               d->currentFocus = qobject_cast<QWidget *>(o);
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    case QEvent::MouseButtonPress:
+        // If we get a mouse button press event inside a embedded widget
+        // make sure this is the active window in qapp.
+        d->checkActivateWindow(o);
+        break;
+    default:
+        break;
+    }
+
+    return QWidget::eventFilter(o, event);
+}
+
+/*! \internal
+
+    Handles some notification events and client messages. Client side
+    XEmbed message receiving is also handled here.
+*/
+bool QX11EmbedWidget::x11Event(XEvent *event)
+{
+    Q_D(QX11EmbedWidget);
+    switch (event->type) {
+    case DestroyNotify:
+#ifdef QX11EMBED_DEBUG
+        qDebug() << "QX11EmbedWidget::x11Event: client"
+                 << (void *)this << "with winId" << winId()
+                 << "received a DestroyNotify";
+#endif
+        // If the container window is destroyed, we signal this to the user.
+        d->container = 0;
+        emit containerClosed();
+        break;
+    case ReparentNotify:
+#ifdef QX11EMBED_DEBUG
+        qDebug() << "QX11EmbedWidget::x11Event: client"
+                 << (void *)this << "with winId" << winId()
+                 << "received a ReparentNotify to"
+                 << ((event->xreparent.parent == x11Info().appRootWindow())
+                     ? QString::fromLatin1("root") : QString::number(event->xreparent.parent));
+#endif
+        // If the container shuts down, we will be reparented to the
+        // root window. We must also consider the case that we may be
+        // reparented from one container to another.
+        if (event->xreparent.parent == x11Info().appRootWindow()) {
+            if (((QHackWidget *)this)->topData()->embedded) {
+                d->container = 0;
+                emit containerClosed();
+            }
+            return true;
+        } else {
+            d->container = event->xreparent.parent;
+        }
+        break;
+    case UnmapNotify:
+        // Mapping and unmapping are handled by changes to the
+        // _XEMBED_INFO property. Any default map/unmap requests are
+        // ignored.
+        return true;
+    case PropertyNotify:
+        // The container sends us map/unmap messages through the
+        // _XEMBED_INFO property. We adhere to the XEMBED_MAPPED bit in
+        // data2.
+        if (event->xproperty.atom == ATOM(_XEMBED_INFO)) {
+            Atom actual_type_return;
+            int actual_format_return;
+            unsigned long nitems_return;
+            unsigned long bytes_after_return;
+            unsigned char *prop_return = 0;
+            if (XGetWindowProperty(x11Info().display(), internalWinId(), ATOM(_XEMBED_INFO), 0, 2,
+                                   false, ATOM(_XEMBED_INFO), &actual_type_return,
+                                   &actual_format_return, &nitems_return,
+                                   &bytes_after_return, &prop_return) == Success) {
+                if (nitems_return > 1) {
+                    if (((long * )prop_return)[1] & XEMBED_MAPPED) {
+                        XMapWindow(x11Info().display(), internalWinId());
+                    } else {
+                        XUnmapWindow(x11Info().display(), internalWinId());
+                    }
+                }
+            }
+        }
+
+        break;
+    case ClientMessage:
+        // XEMBED messages have message_type _XEMBED
+        if (event->xclient.message_type == ATOM(_XEMBED)) {
+            // Discard XEMBED messages not to ourselves. (### dead code?)
+            if (event->xclient.window != internalWinId())
+                break;
+
+            // Update qt_x_time if necessary
+            Time msgtime = (Time) event->xclient.data.l[0];
+            if (msgtime > X11->time)
+                X11->time = msgtime;
+
+            switch (event->xclient.data.l[1]) {
+            case XEMBED_WINDOW_ACTIVATE: {
+                // When we receive an XEMBED_WINDOW_ACTIVATE, we simply send
+                // ourselves a WindowActivate event. Real activation happens
+                // when receive XEMBED_FOCUS_IN.
+                if (!isActiveWindow()) {
+                    QEvent ev(QEvent::WindowActivate);
+                    QApplication::sendEvent(this, &ev);
+                }
+            }
+                break;
+            case XEMBED_WINDOW_DEACTIVATE: {
+                // When we receive an XEMBED_WINDOW_DEACTIVATE, we simply send
+                // ourselves a WindowDeactivate event. Real activation happens
+                // when receive XEMBED_FOCUS_IN.
+                if (isActiveWindow()) {
+                    if (!qApp->activePopupWidget())
+                        QApplication::setActiveWindow(0);
+                } else {
+                    QEvent ev(QEvent::WindowDeactivate);
+                    QApplication::sendEvent(this, &ev);
+                }
+            }
+                break;
+            case XEMBED_EMBEDDED_NOTIFY: {
+#ifdef QX11EMBED_DEBUG
+                qDebug() << "QX11EmbedWidget::x11Event: client"
+                         << (void *)this << "with winId" << winId()
+                         << "received an XEMBED EMBEDDED NOTIFY message";
+#endif
+                // In this message's l[2] we have the max version
+                // supported by both the client and the
+                // container. QX11EmbedWidget does not use this field.
+
+                // We have been embedded, so we set our
+                // client's embedded flag.
+                d->setEmbedded();
+                emit embedded();
+            }
+                break;
+            case XEMBED_FOCUS_IN:
+                // don't set the focus if a modal dialog is open
+                if (qApp->activeModalWidget())
+                    break;
+
+                // in case we embed more than one topLevel window inside the same
+                // host window.
+                if (window() != qApp->activeWindow())
+                    qApp->setActiveWindow(this);
+
+                switch (event->xclient.data.l[2]) {
+                case XEMBED_FOCUS_CURRENT:
+                    // The container sends us this message if it wants
+                    // us to focus on the widget that last had focus.
+                    // This is the reply when XEMBED_REQUEST_FOCUS is
+                    // sent to the container.
+                    if (!d->currentFocus.isNull()) {
+                        if (!d->currentFocus->hasFocus())
+                            d->currentFocus->setFocus(Qt::OtherFocusReason);
+                    } else {
+                        // No widget currently has focus. We set focus
+                        // on the first widget next to the
+                        // client widget. Since the setFocus will not work
+                        // if the window is disabled, set the currentFocus
+                        // directly so that it's set on window activate.
+                        d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::FirstFocusWidget);
+                        d->currentFocus->setFocus(Qt::OtherFocusReason);
+                    }
+                    break;
+                case XEMBED_FOCUS_FIRST:
+                    // The container sends this message when it wants
+                    // us to focus on the first widget in our focus
+                    // chain (typically because of a tab).
+                    d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::FirstFocusWidget);
+                    d->currentFocus->setFocus(Qt::TabFocusReason);
+                    break;
+                case XEMBED_FOCUS_LAST:
+                    // The container sends this message when it wants
+                    // us to focus on the last widget in our focus
+                    // chain (typically because of a backtab).
+                    d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::LastFocusWidget);
+                    d->currentFocus->setFocus(Qt::BacktabFocusReason);
+                    break;
+                default:
+                    // Ignore any other XEMBED_FOCUS_IN details.
+                    break;
+                }
+                break;
+            case XEMBED_FOCUS_OUT:
+                // The container sends us this message when it wants us
+                // to lose focus and forget about the widget that last
+                // had focus. Typically sent by the container when it
+                // loses focus because of mouse or tab activity. We do
+                // then not want to set focus on anything if we're
+                // activated.
+                if (isActiveWindow())
+                    d->clearFocus();
+
+                break;
+            default:
+                // Ignore any other XEMBED messages.
+                break;
+            };
+        } else {
+            // Non-XEMBED client messages are not interesting.
+        }
+
+        break;
+    default:
+        // Ignore all other x11 events.
+        break;
+    }
+
+    // Allow default handling.
+    return QWidget::x11Event(event);
+}
+
+/*!
+    \reimp
+*/
+bool QX11EmbedWidget::event(QEvent *event)
+{
+    if (event->type() == QEvent::ParentChange) {
+        XSelectInput(x11Info().display(), internalWinId(),
+                     KeyPressMask | KeyReleaseMask | ButtonPressMask
+                     | ButtonReleaseMask
+                     | KeymapStateMask | ButtonMotionMask | PointerMotionMask
+                     | FocusChangeMask
+                     | ExposureMask | StructureNotifyMask
+                     | SubstructureNotifyMask | PropertyChangeMask);
+    }
+    return QWidget::event(event);
+}
+
+/*!
+    \reimp
+*/
+void QX11EmbedWidget::resizeEvent(QResizeEvent *event)
+{
+    if (layout())
+        layout()->update();
+    QWidget::resizeEvent(event);
+}
+
+/*!
+    If the widget is embedded, returns the window ID of the
+    container; otherwize returns 0.
+*/
+WId QX11EmbedWidget::containerWinId() const
+{
+    Q_D(const QX11EmbedWidget);
+    return d->container;
+}
+
+class QX11EmbedContainerPrivate : public QWidgetPrivate
+{
+    Q_DECLARE_PUBLIC(QX11EmbedContainer)
+public:
+    inline QX11EmbedContainerPrivate()
+    {
+        lastError = QX11EmbedContainer::Unknown;
+        client = 0;
+        focusProxy = 0;
+        clientIsXEmbed = false;
+        xgrab = false;
+    }
+
+    bool isEmbedded() const;
+    void moveInputToProxy();
+
+    void acceptClient(WId window);
+    void rejectClient(WId window);
+
+    void checkGrab();
+
+    WId topLevelParentWinId() const;
+
+    void emitError(QX11EmbedContainer::Error error) {
+        Q_Q(QX11EmbedContainer);
+        lastError = error;
+        emit q->error(error);
+    }
+
+    WId client;
+    QWidget *focusProxy;
+    bool clientIsXEmbed;
+    bool xgrab;
+    QRect clientOriginalRect;
+    QSize wmMinimumSizeHint;
+
+    QX11EmbedContainer::Error lastError;
+
+    static QX11EmbedContainer *activeContainer;
+};
+
+QX11EmbedContainer *QX11EmbedContainerPrivate::activeContainer = 0;
+
+/*!
+    Creates a QX11EmbedContainer object with the given \a parent.
+*/
+QX11EmbedContainer::QX11EmbedContainer(QWidget *parent)
+    : QWidget(*new QX11EmbedContainerPrivate, parent, 0)
+{
+    Q_D(QX11EmbedContainer);
+    XSetErrorHandler(x11ErrorHandler);
+
+    setAttribute(Qt::WA_NativeWindow);
+    setAttribute(Qt::WA_DontCreateNativeAncestors);
+    createWinId();
+
+    setFocusPolicy(Qt::StrongFocus);
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+    // ### PORT setKeyCompression(false);
+    setAcceptDrops(true);
+    setEnabled(false);
+
+    // Everybody gets a focus proxy, but only one toplevel container's
+    // focus proxy is actually in use.
+    d->focusProxy = new QWidget(this);
+    d->focusProxy->setAttribute(Qt::WA_NativeWindow);
+    d->focusProxy->setAttribute(Qt::WA_DontCreateNativeAncestors);
+    d->focusProxy->setGeometry(-1, -1, 1, 1);
+
+    // We need events from the window (activation status) and
+    // from qApp (keypress/release).
+    qApp->installEventFilter(this);
+
+    // Install X11 event filter.
+    if (!oldX11EventFilter)
+        oldX11EventFilter = QCoreApplication::instance()->setEventFilter(x11EventFilter);
+
+    XSelectInput(x11Info().display(), internalWinId(),
+                 KeyPressMask | KeyReleaseMask
+                 | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+                 | KeymapStateMask
+                 | PointerMotionMask
+                 | EnterWindowMask | LeaveWindowMask
+                 | FocusChangeMask
+                 | ExposureMask
+                 | StructureNotifyMask
+                 | SubstructureNotifyMask);
+
+    // Make sure our new event mask takes effect as soon as possible.
+    XFlush(x11Info().display());
+
+    // Move input to our focusProxy if this widget is active, and not
+    // shaded by a modal dialog (in which case isActiveWindow() would
+    // still return true, but where we must not move input focus).
+    if (qApp->activeWindow() == window() && !d->isEmbedded())
+        d->moveInputToProxy();
+
+#ifdef QX11EMBED_DEBUG
+    qDebug() << "QX11EmbedContainer::QX11EmbedContainer: constructed container"
+             << (void *)this << "with winId" << winId();
+#endif
+}
+
+/*!
+    Destructs a QX11EmbedContainer.
+*/
+QX11EmbedContainer::~QX11EmbedContainer()
+{
+    Q_D(QX11EmbedContainer);
+    if (d->client) {
+	XUnmapWindow(x11Info().display(), d->client);
+	XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(), 0, 0);
+    }
+
+    if (d->xgrab)
+	XUngrabButton(x11Info().display(), AnyButton, AnyModifier, internalWinId());
+}
+
+
+QX11EmbedContainer::Error QX11EmbedContainer::error() const {
+    return d_func()->lastError;
+}
+
+
+/*! \reimp
+*/
+void QX11EmbedContainer::paintEvent(QPaintEvent *)
+{
+}
+
+/*! \internal
+
+    Returns wether or not the windows' embedded flag is set.
+*/
+bool QX11EmbedContainerPrivate::isEmbedded() const
+{
+    Q_Q(const QX11EmbedContainer);
+    return ((QHackWidget *)q->window())->topData()->embedded == 1;
+}
+
+/*! \internal
+
+    Returns the parentWinId of the window.
+*/
+WId QX11EmbedContainerPrivate::topLevelParentWinId() const
+{
+    Q_Q(const QX11EmbedContainer);
+    return ((QHackWidget *)q->window())->topData()->parentWinId;
+}
+
+/*!
+    If the container has an embedded widget, this function returns
+    the X11 window ID of the client; otherwise it returns 0.
+*/
+WId QX11EmbedContainer::clientWinId() const
+{
+    Q_D(const QX11EmbedContainer);
+    return d->client;
+}
+
+/*!
+    Instructs the container to embed the X11 window with window ID \a
+    id. The client widget will then move on top of the container
+    window and be resized to fit into the container.
+
+    The \a id should be the ID of a window controlled by an XEmbed
+    enabled application, but this is not mandatory. If \a id does not
+    belong to an XEmbed client widget, then focus handling,
+    activation, accelerators and other features will not work
+    properly.
+*/
+void QX11EmbedContainer::embedClient(WId id)
+{
+    Q_D(QX11EmbedContainer);
+
+    if (id == 0) {
+	d->emitError(InvalidWindowID);
+	return;
+    }
+
+    // Walk up the tree of parent windows to prevent embedding of ancestors.
+    WId thisId = internalWinId();
+    Window rootReturn;
+    Window parentReturn;
+    Window *childrenReturn = 0;
+    unsigned int nchildrenReturn;
+    do {
+        if (XQueryTree(x11Info().display(), thisId, &rootReturn,
+                       &parentReturn, &childrenReturn, &nchildrenReturn) == 0) {
+	    d->emitError(InvalidWindowID);
+	    return;
+        }
+        if (childrenReturn) {
+            XFree(childrenReturn);
+            childrenReturn = 0;
+        }
+
+        thisId = parentReturn;
+        if (id == thisId) {
+	    d->emitError(InvalidWindowID);
+	    return;
+        }
+    } while (thisId != rootReturn);
+
+    // watch for property notify events (see below)
+    XGrabServer(x11Info().display());
+    XWindowAttributes attrib;
+    if (!XGetWindowAttributes(x11Info().display(), id, &attrib)) {
+        XUngrabServer(x11Info().display());
+	d->emitError(InvalidWindowID);
+	return;
+    }
+    XSelectInput(x11Info().display(), id, attrib.your_event_mask | PropertyChangeMask | StructureNotifyMask);
+    XUngrabServer(x11Info().display());
+
+    // Put the window into WithdrawnState
+    XUnmapWindow(x11Info().display(), id);
+    XSync(x11Info().display(), False); // make sure the window is hidden
+
+    /*
+      Wait for notification from the window manager that the window is
+      in withdrawn state.  According to the ICCCM section 4.1.3.1,
+      we should wait for the WM_STATE property to either be deleted or
+      set to WithdrawnState.
+
+      For safety, we will not wait more than 500 ms, so that we can
+      preemptively workaround buggy window managers.
+    */
+    QTime t;
+    t.start();
+
+    functorData data;
+    data.id = id;
+    data.rootWindow = attrib.root;
+    data.clearedWmState = false;
+    data.reparentedToRoot = false;
+
+    do {
+	if (t.elapsed() > 500) // time-out after 500 ms
+	    break;
+
+	XEvent event;
+	if (!XCheckIfEvent(x11Info().display(), &event, functor, (XPointer) &data)) {
+	    XSync(x11Info().display(), False);
+            usleep(50000);
+	    continue;
+	}
+
+        qApp->x11ProcessEvent(&event);
+    } while (!data.clearedWmState || !data.reparentedToRoot);
+
+    // restore the event mask
+    XSelectInput(x11Info().display(), id, attrib.your_event_mask);
+
+    switch (XReparentWindow(x11Info().display(), id, internalWinId(), 0, 0)) {
+    case BadWindow:
+    case BadMatch:
+	d->emitError(InvalidWindowID);
+	break;
+    default:
+	break;
+    }
+}
+
+/*! \internal
+
+    Handles key, activation and focus events for the container.
+*/
+bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
+{
+    Q_D(QX11EmbedContainer);
+    switch (event->type()) {
+    case QEvent::KeyPress:
+        // Forward any keypresses to our client.
+	if (o == this && d->client) {
+	    lastKeyEvent.window = d->client;
+	    XSendEvent(x11Info().display(), d->client, false, KeyPressMask, (XEvent *) &lastKeyEvent);
+	    return true;
+	}
+	break;
+    case QEvent::KeyRelease:
+	// Forward any keyreleases to our client.
+	if (o == this && d->client) {
+	    lastKeyEvent.window = d->client;
+	    XSendEvent(x11Info().display(), d->client, false, KeyReleaseMask, (XEvent *) &lastKeyEvent);
+	    return true;
+	}
+	break;
+
+    case QEvent::WindowActivate:
+	// When our container window is activated, we pass the
+	// activation message on to our client. Note that X input
+	// focus is set to our focus proxy. We want to intercept all
+	// keypresses.
+	if (o == window() && d->client) {
+            if (d->clientIsXEmbed) {
+                sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_ACTIVATE);
+            } else {
+                d->checkGrab();
+                if (hasFocus())
+                    XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time());
+            }
+            if (!d->isEmbedded())
+                d->moveInputToProxy();
+	}
+	break;
+    case QEvent::WindowDeactivate:
+	// When our container window is deactivated, we pass the
+	// deactivation message to our client.
+	if (o == window() && d->client) {
+	    if (d->clientIsXEmbed)
+		sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_DEACTIVATE);
+	    else
+		d->checkGrab();
+	}
+	break;
+    case QEvent::FocusIn:
+        // When receiving FocusIn events generated by Tab or Backtab,
+	// we pass focus on to our client. Any mouse activity is sent
+	// directly to the client, and it will ask us for focus with
+	// XEMBED_REQUEST_FOCUS.
+	if (o == this && d->client) {
+            if (!d->isEmbedded())
+                d->activeContainer = this;
+
+            if (d->clientIsXEmbed) {
+                if (!d->isEmbedded())
+                    d->moveInputToProxy();
+
+		QFocusEvent *fe = (QFocusEvent *)event;
+		switch (fe->reason()) {
+		case Qt::TabFocusReason:
+		    sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_FIRST);
+		    break;
+		case Qt::BacktabFocusReason:
+		    sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_LAST);
+		    break;
+		default:
+		    sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
+		    break;
+		}
+	    } else {
+		d->checkGrab();
+                XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time());
+	    }
+	}
+
+	break;
+    case QEvent::FocusOut: {
+	// When receiving a FocusOut, we ask our client to remove its
+	// focus.
+	if (o == this && d->client) {
+            if (!d->isEmbedded()) {
+                d->activeContainer = 0;
+                if (isActiveWindow())
+                    d->moveInputToProxy();
+            }
+
+	    if (d->clientIsXEmbed) {
+		QFocusEvent *fe = (QFocusEvent *)event;
+		if (o == this && d->client && fe->reason() != Qt::ActiveWindowFocusReason)
+		    sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_OUT);
+	    } else {
+		d->checkGrab();
+	    }
+	}
+    }
+	break;
+
+    case QEvent::Close: {
+	if (o == this && d->client) {
+	    // Unmap the client and reparent it to the root window.
+	    // Wait until the messages have been processed. Then ask
+	    // the window manager to delete the window.
+	    XUnmapWindow(x11Info().display(), d->client);
+	    XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(), 0, 0);
+	    XSync(x11Info().display(), false);
+
+	    XEvent ev;
+	    memset(&ev, 0, sizeof(ev));
+	    ev.xclient.type = ClientMessage;
+	    ev.xclient.window = d->client;
+	    ev.xclient.message_type = ATOM(WM_PROTOCOLS);
+	    ev.xclient.format = 32;
+	    ev.xclient.data.s[0] = ATOM(WM_DELETE_WINDOW);
+	    XSendEvent(x11Info().display(), d->client, false, NoEventMask, &ev);
+
+	    XFlush(x11Info().display());
+	    d->client = 0;
+	    d->clientIsXEmbed = false;
+            d->wmMinimumSizeHint = QSize();
+            updateGeometry();
+            setEnabled(false);
+	    update();
+
+	    emit clientClosed();
+	}
+    }
+    default:
+	break;
+    }
+
+    return QWidget::eventFilter(o, event);
+}
+
+/*! \internal
+
+    Handles X11 events for the container.
+*/
+bool QX11EmbedContainer::x11Event(XEvent *event)
+{
+    Q_D(QX11EmbedContainer);
+
+    switch (event->type) {
+    case CreateNotify:
+	// The client created an embedded window.
+	if (d->client)
+	    d->rejectClient(event->xcreatewindow.window);
+	else
+	    d->acceptClient(event->xcreatewindow.window);
+      break;
+    case DestroyNotify:
+	if (event->xdestroywindow.window == d->client) {
+	    // The client died.
+	    d->client = 0;
+	    d->clientIsXEmbed = false;
+            d->wmMinimumSizeHint = QSize();
+            updateGeometry();
+	    update();
+            setEnabled(false);
+	    emit clientClosed();
+	}
+        break;
+    case ReparentNotify:
+	// The client sends us this if it reparents itself out of our
+	// widget.
+	if (event->xreparent.window == d->client && event->xreparent.parent != internalWinId()) {
+	    d->client = 0;
+	    d->clientIsXEmbed = false;
+            d->wmMinimumSizeHint = QSize();
+            updateGeometry();
+	    update();
+            setEnabled(false);
+	    emit clientClosed();
+	} else if (event->xreparent.parent == internalWinId()) {
+	    // The client reparented itself into this window.
+	    if (d->client)
+		d->rejectClient(event->xreparent.window);
+	    else
+		d->acceptClient(event->xreparent.window);
+	}
+	break;
+    case ClientMessage: {
+	if (event->xclient.message_type == ATOM(_XEMBED)) {
+	    // Ignore XEMBED messages not to ourselves
+	    if (event->xclient.window != internalWinId())
+		break;
+
+	    // Receiving an XEmbed message means the client
+	    // is an XEmbed client.
+	    d->clientIsXEmbed = true;
+
+	    Time msgtime = (Time) event->xclient.data.l[0];
+	    if (msgtime > X11->time)
+		X11->time = msgtime;
+
+	    switch (event->xclient.data.l[1]) {
+	    case XEMBED_REQUEST_FOCUS: {
+		// This typically happens when the client gets focus
+		// because of a mouse click.
+		if (!hasFocus())
+		    setFocus(Qt::OtherFocusReason);
+
+		// The message is passed along to the topmost container
+		// that eventually responds with a XEMBED_FOCUS_IN
+		// message. The focus in message is passed all the way
+		// back until it reaches the original focus
+		// requestor. In the end, not only the original client
+		// has focus, but also all its ancestor containers.
+		if (d->isEmbedded()) {
+                    // If our window's embedded flag is set, then
+		    // that suggests that we are part of a client. The
+		    // parentWinId will then point to an container to whom
+		    // we must pass this message.
+		    sendXEmbedMessage(d->topLevelParentWinId(), x11Info().display(), XEMBED_REQUEST_FOCUS);
+		} else {
+                    // Our window's embedded flag is not set,
+		    // so we are the topmost container. We respond to
+		    // the focus request message with a focus in
+		    // message. This message will pass on from client
+		    // to container to client until it reaches the
+		    // originator of the XEMBED_REQUEST_FOCUS message.
+		    sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
+		}
+
+		break;
+	    }
+	    case XEMBED_FOCUS_NEXT:
+		// Client sends this event when it received a tab
+		// forward and was at the end of its focus chain. If
+		// we are the only widget in the focus chain, we send
+		// ourselves a FocusIn event.
+                if (d->focus_next != this) {
+		    focusNextPrevChild(true);
+                } else {
+                    QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
+                    qApp->sendEvent(this, &event);
+                }
+
+		break;
+	    case XEMBED_FOCUS_PREV:
+		// Client sends this event when it received a backtab
+		// and was at the start of its focus chain. If we are
+		// the only widget in the focus chain, we send
+		// ourselves a FocusIn event.
+                if (d->focus_next != this) {
+		    focusNextPrevChild(false);
+                } else {
+                    QFocusEvent event(QEvent::FocusIn, Qt::BacktabFocusReason);
+                    qApp->sendEvent(this, &event);
+                }
+
+		break;
+	    default:
+		break;
+	    }
+	}
+    }
+	break;
+    case XButtonPress:
+	if (!d->clientIsXEmbed) {
+            setFocus(Qt::MouseFocusReason);
+            XAllowEvents(x11Info().display(), ReplayPointer, CurrentTime);
+            return true;
+	}
+	break;
+    case XButtonRelease:
+	if (!d->clientIsXEmbed)
+            XAllowEvents(x11Info().display(), SyncPointer, CurrentTime);
+	break;
+    default:
+	break;
+    }
+
+    return QWidget::x11Event(event);
+}
+
+/*! \internal
+
+    Whenever the container is resized, we need to resize our client.
+*/
+void QX11EmbedContainer::resizeEvent(QResizeEvent *)
+{
+    Q_D(QX11EmbedContainer);
+    if (d->client)
+	XResizeWindow(x11Info().display(), d->client, width(), height());
+}
+
+/*! \internal
+
+    We use the QShowEvent to signal to our client that we want it to
+    map itself. We do this by changing its window property
+    XEMBED_INFO. The client will get an X11 PropertyNotify.
+*/
+void QX11EmbedContainer::showEvent(QShowEvent *)
+{
+    Q_D(QX11EmbedContainer);
+    if (d->client) {
+        long data[] = {XEMBED_VERSION, XEMBED_MAPPED};
+	XChangeProperty(x11Info().display(), d->client, ATOM(_XEMBED_INFO), ATOM(_XEMBED_INFO), 32,
+			PropModeReplace, (unsigned char *) data, 2);
+    }
+}
+
+/*! \internal
+
+    We use the QHideEvent to signal to our client that we want it to
+    unmap itself. We do this by changing its window property
+    XEMBED_INFO. The client will get an X11 PropertyNotify.
+*/
+void QX11EmbedContainer::hideEvent(QHideEvent *)
+{
+    Q_D(QX11EmbedContainer);
+    if (d->client) {
+        long data[] = {XEMBED_VERSION, XEMBED_MAPPED};
+	XChangeProperty(x11Info().display(), d->client, ATOM(_XEMBED_INFO), ATOM(_XEMBED_INFO), 32,
+			PropModeReplace, (unsigned char *) data, 2);
+    }
+}
+
+/*!
+    \reimp
+*/
+bool QX11EmbedContainer::event(QEvent *event)
+{
+    if (event->type() == QEvent::ParentChange) {
+        XSelectInput(x11Info().display(), internalWinId(),
+                     KeyPressMask | KeyReleaseMask
+                     | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+                     | KeymapStateMask
+                     | PointerMotionMask
+                     | EnterWindowMask | LeaveWindowMask
+                     | FocusChangeMask
+                     | ExposureMask
+                     | StructureNotifyMask
+                     | SubstructureNotifyMask);
+    }
+    return QWidget::event(event);
+}
+
+/*! \internal
+
+    Rejects a client window by reparenting it to the root window.  The
+    client will receive a reparentnotify, and will most likely assume
+    that the container has shut down. The XEmbed protocol does not
+    define any way to reject a client window, but this is a clean way
+    to do it.
+*/
+void QX11EmbedContainerPrivate::rejectClient(WId window)
+{
+    Q_Q(QX11EmbedContainer);
+    q->setEnabled(false);
+    XRemoveFromSaveSet(q->x11Info().display(), client);
+    XReparentWindow(q->x11Info().display(), window, q->x11Info().appRootWindow(), 0, 0);
+}
+
+/*! \internal
+
+    Accepts a client by mapping it, resizing it and optionally
+    activating and giving it logical focusing through XEMBED messages.
+*/
+void QX11EmbedContainerPrivate::acceptClient(WId window)
+{
+    Q_Q(QX11EmbedContainer);
+    client = window;
+    q->setEnabled(true);
+
+    // This tells Qt that we wish to forward DnD messages to
+    // our client.
+    if (!extra)
+        createExtra();
+    extraData()->xDndProxy = client;
+
+    unsigned int version = XEmbedVersion();
+
+    Atom actual_type_return;
+    int actual_format_return;
+    unsigned long nitems_return = 0;
+    unsigned long bytes_after_return;
+    unsigned char *prop_return = 0;
+    unsigned int clientversion = 0;
+
+    // Add this client to our saveset, so if we crash, the client window
+    // doesn't get destroyed. This is useful for containers that restart
+    // automatically after a crash, because it can simply reembed its clients
+    // without having to restart them (KDE panel).
+    XAddToSaveSet(q->x11Info().display(), client);
+
+    // XEmbed clients have an _XEMBED_INFO property in which we can
+    // fetch the version
+    if (XGetWindowProperty(q->x11Info().display(), client, ATOM(_XEMBED_INFO), 0, 2, false,
+                           ATOM(_XEMBED_INFO), &actual_type_return, &actual_format_return,
+                           &nitems_return, &bytes_after_return, &prop_return) == Success) {
+
+	if (actual_type_return != None && actual_format_return != 0) {
+	    // Clients with the _XEMBED_INFO property are XEMBED clients.
+	    clientIsXEmbed = true;
+
+	    long *p = (long *)prop_return;
+	    if (nitems_return >= 2)
+		clientversion = (unsigned int)p[0];
+	}
+
+	XFree(prop_return);
+    }
+
+    // Store client window's original size and placement.
+    Window root;
+    int x_return, y_return;
+    unsigned int width_return, height_return, border_width_return, depth_return;
+    XGetGeometry(q->x11Info().display(), client, &root, &x_return, &y_return,
+		 &width_return, &height_return, &border_width_return, &depth_return);
+    clientOriginalRect.setCoords(x_return, y_return,
+				 x_return + width_return - 1,
+				 y_return + height_return - 1);
+
+    // Ask the client for its minimum size.
+    XSizeHints size;
+    long msize;
+    if (XGetWMNormalHints(q->x11Info().display(), client, &size, &msize) && (size.flags & PMinSize)) {
+	wmMinimumSizeHint = QSize(size.min_width, size.min_height);
+        q->updateGeometry();
+    }
+
+    // The container should set the data2 field to the lowest of its
+    // supported version number and that of the client (from
+    // _XEMBED_INFO property).
+    unsigned int minversion = version > clientversion ? clientversion : version;
+    sendXEmbedMessage(client, q->x11Info().display(), XEMBED_EMBEDDED_NOTIFY, q->internalWinId(), minversion);
+    XMapWindow(q->x11Info().display(), client);
+
+    // Resize it, but no smaller than its minimum size hint.
+    XResizeWindow(q->x11Info().display(),
+                  client,
+                  qMax(q->width(), wmMinimumSizeHint.width()),
+                  qMax(q->height(), wmMinimumSizeHint.height()));
+    q->update();
+
+    // Not mentioned in the protocol is that if the container
+    // is already active, the client must be activated to work
+    // properly.
+    if (q->window()->isActiveWindow())
+	sendXEmbedMessage(client, q->x11Info().display(), XEMBED_WINDOW_ACTIVATE);
+
+    // Also, if the container already has focus, then it must
+    // send a focus in message to its new client; otherwise we ask
+    // it to remove focus.
+    if (q->focusWidget() == q && q->hasFocus())
+	sendXEmbedMessage(client, q->x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_FIRST);
+    else
+	sendXEmbedMessage(client, q->x11Info().display(), XEMBED_FOCUS_OUT);
+
+    if (!clientIsXEmbed) {
+        checkGrab();
+        if (q->hasFocus()) {
+            XSetInputFocus(q->x11Info().display(), client, XRevertToParent, x11Time());
+        }
+    } else {
+        if (!isEmbedded())
+            moveInputToProxy();
+    }
+
+    emit q->clientIsEmbedded();
+}
+
+/*! \internal
+
+    Moves X11 keyboard input focus to the focusProxy, unless the focus
+    is there already. When X11 keyboard input focus is on the
+    focusProxy, which is a child of the container and a sibling of the
+    client, X11 keypresses and keyreleases will always go to the proxy
+    and not to the client.
+*/
+void QX11EmbedContainerPrivate::moveInputToProxy()
+{
+    Q_Q(QX11EmbedContainer);
+    // Following Owen Taylor's advice from the XEmbed specification to
+    // always use CurrentTime when no explicit user action is involved.
+    XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, CurrentTime);
+}
+
+/*! \internal
+
+    Ask the window manager to give us a default minimum size.
+*/
+QSize QX11EmbedContainer::minimumSizeHint() const
+{
+    Q_D(const QX11EmbedContainer);
+    if (!d->client || !d->wmMinimumSizeHint.isValid())
+	return QWidget::minimumSizeHint();
+    return d->wmMinimumSizeHint;
+}
+
+/*! \internal
+
+*/
+void QX11EmbedContainerPrivate::checkGrab()
+{
+    Q_Q(QX11EmbedContainer);
+    if (!clientIsXEmbed && q->isActiveWindow() && !q->hasFocus()) {
+        if (!xgrab) {
+            XGrabButton(q->x11Info().display(), AnyButton, AnyModifier, q->internalWinId(),
+                        true, ButtonPressMask, GrabModeSync, GrabModeAsync,
+                        None, None);
+        }
+        xgrab = true;
+    } else {
+	if (xgrab)
+	    XUngrabButton(q->x11Info().display(), AnyButton, AnyModifier, q->internalWinId());
+        xgrab = false;
+    }
+}
+
+/*!
+    Detaches the client from the embedder. The client will appear as a
+    standalone window on the desktop.
+*/
+void QX11EmbedContainer::discardClient()
+{
+    Q_D(QX11EmbedContainer);
+    if (d->client) {
+	XResizeWindow(x11Info().display(), d->client, d->clientOriginalRect.width(),
+		      d->clientOriginalRect.height());
+
+	d->rejectClient(d->client);
+    }
+}
+
+QT_END_NAMESPACE