⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qx11embed_x11.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
class QX11EmbedWidgetPrivate : public QWidgetPrivate{    Q_DECLARE_PUBLIC(QX11EmbedWidget)public:    inline QX11EmbedWidgetPrivate()    {        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);    initXEmbedAtoms(x11Info().display());    createWinId();    XSelectInput(x11Info().display(), internalWinId(),                 KeyPressMask | KeyReleaseMask | ButtonPressMask                    | ButtonReleaseMask                    | KeymapStateMask | ButtonMotionMask | PointerMotionMask                    | FocusChangeMask                    | ExposureMask | StructureNotifyMask                    | SubstructureNotifyMask | PropertyChangeMask);    unsigned int data[] = {XEMBED_VERSION, XEMBED_MAPPED};    XChangeProperty(x11Info().display(), internalWinId(), _XEMBED_INFO,                    _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 (!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 == _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(), _XEMBED_INFO, 0, 2,                                   false, _XEMBED_INFO, &actual_type_return,                                   &actual_format_return, &nitems_return,                                   &bytes_after_return, &prop_return) == Success) {                if (nitems_return > 1) {                    if (((int * )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 == _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 need                // to send ourselves a synthetic FocusIn X11 event for                // Qt to activate us.                XEvent ev;                memset(&ev, 0, sizeof(ev));                ev.xfocus.display = x11Info().display();                ev.xfocus.type = XFocusIn;                ev.xfocus.window = internalWinId();                ev.xfocus.mode = NotifyNormal;                ev.xfocus.detail = NotifyNonlinear;                ((QApplication *)QApplication::instance())->x11ProcessEvent(&ev);            }                break;            case XEMBED_WINDOW_DEACTIVATE: {                // When we receive an XEMBED_WINDOW_DEACTIVATE, we                // need to send ourselves a synthetic FocusOut event                // for Qt to deativate us.                XEvent ev;                memset(&ev, 0, sizeof(ev));                ev.xfocus.display = x11Info().display();                ev.xfocus.type = XFocusOut;                ev.xfocus.window = internalWinId();                ev.xfocus.mode = NotifyNormal;                ev.xfocus.detail = NotifyNonlinear;                ((QApplication *)QApplication::instance())->x11ProcessEvent(&ev);            }                break;            case XEMBED_EMBEDDED_NOTIFY: {#ifdef QX11EMBED_DEBUG                qDebug() << "QX11EmbedWidget::x11Event: client"                         << (void *)this << "with winId" << winId()                         << "received an XEMBED EMBEDDED NOTIFY message";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -