0

Xlib と Qt 4.7 を使用して独自のウィンドウ マネージャーを作成しています。したがって、私のアプリケーションでは、XServer からのすべてのイベントをキャッチします。

問題は次です。「MapRequest」イベントでウィンドウを表示すると、その内部コンテンツが別のウィンドウに表示されることがあります。ほとんどの場合、新しい Web ページを開いた後、ブラウザー (Firefox や Google Chrome など) でこの問題に直面します。Qt Creator や Dolphin でダイアログ ウィンドウを開いた後、メディア プレーヤーでも同様です。その理由は何でしょうか?私が逃したものは何ですか?

どんなアドバイスも大歓迎です。

これが MapRequest ハンドラです。

bool Manager::mapRequestHandler(XEvent* pEvent)
{
    Window lWindow = pEvent->xmaprequest.window;

    QMWindowWidget* lWidget = findWidget(lWindow);
    if (!lWidget)
    {
        lWidget = (QMWindowWidget*)QWidget::find(lWindow);
    }

    if (lWidget)
    {
        XMapWindow(QX11Info::display(), lWindow);
        lWidget->show();
        XRaiseWindow(QX11Info::display(), lWidget->winId());
        return true;
    }
    else
    {
        qDebug()<<"CREATING WINDOW IN MAP_REQUEST...";
        createClientWindow(lWindow); //this function calls only here.
        qDebug()<<"WINDOW CREATED";
        return true;
    }
    return false;
}

これが createClientWindow() 関数です。

void Manager::createClientWindow(Qt::HANDLE pWinID)
{
    XWindowAttributes lWinAttr;
    if(!XGetWindowAttributes(QX11Info::display(), pWinID, &lWinAttr))
    {
        return;
    }
    if(lWinAttr.override_redirect)
    {
        return;
    }

    QStringList lWindowType = getWindowType(pWinID);
    if(lWindowType[0] == "Desktop")
    {
        return;
    }
    else if(lWindowType[0] == "Splash"       || lWindowType[0] == "Dock" ||
            lWindowType[0] == "KDE_override" || lWindowType[0] == "Popup_menu")
    {
        XMapWindow(QX11Info::display(), pWinID);
        XRaiseWindow(QX11Info::display(), pWinID);
        return;
    }
    else
    {
        QMWindowWidget *lWindowWidget = new QMWindowWidget(pWinID, lWinAttr);
        connect(lWindowWidget, SIGNAL(destroyed(QObject*)), this, SLOT(slotWidgetDestroyed(QObject*)));
        mListWindows.append(lWindowWidget);
    }
}

QMWindowWidget のコンストラクター。

mClientAttr = pWinAttr;
mWmHints = XGetWMHints(QX11Info::display(), pWindow);

XGrabServer(QX11Info::display());

XTextProperty lTitle;
XGetWMName(QX11Info::display(), pWindow, &lTitle);
this->setWindowTitle(QString::fromUtf8((const char*)lTitle.value));
qDebug()<<pWindow<<(const char*)lTitle.value;

int widgetX = pWinAttr.x - 3;
int widgetY = pWinAttr.y - 33;
if (widgetX < 0)
{
    widgetX = 0;
}
if (widgetY < 0)
{
    widgetY = 0;
}
XAddToSaveSet(QX11Info::display(), pWindow);
XSetWindowBorderWidth(QX11Info::display(), pWindow, 0);
XResizeWindow(QX11Info::display(), pWindow, pWinAttr.width, pWinAttr.height);
this->setGeometry(widgetX, widgetY, pWinAttr.width + 6, pWinAttr.height + 33);

XSelectInput(QX11Info::display(),this->winId(),
             KeyReleaseMask | KeyPressMask |
             ButtonMotionMask|
             ButtonPressMask | ButtonReleaseMask |
             FocusChangeMask |
             ExposureMask |
             StructureNotifyMask |
             SubstructureNotifyMask |
             SubstructureRedirectMask);

XReparentWindow(QX11Info::display(), pWindow, this->winId(), 3, 30);

XSelectInput(QX11Info::display(), pWindow,
             ColormapChangeMask |
             PropertyChangeMask |
             StructureNotifyMask);

this->show();
XMapWindow(QX11Info::display(), pWindow);
XRaiseWindow(QX11Info::display(), this->winId());
XSetInputFocus(QX11Info::display(), pWindow, RevertToParent, CurrentTime);

XUngrabServer(QX11Info::display());
XSync(QX11Info::display(), false);
4

1 に答える 1

0

問題は、最上位のウィンドウのみを表示する必要があり、表示する必要がある場合にのみ表示する必要があることです。私は同じ問題を抱えていて、MapRequest イベント ハンドラよりも多くの場所でクライアント ウィンドウを表示していることを発見しました。したがって、コードを確認してください。明示的な要求なしでウィンドウを表示する別のイベントを処理している可能性があります!

さらにサポートが必要な場合は、すべてのイベント ハンドラーを投稿してから、私の回答にコメントしてください。編集してサポートを提供します。

于 2011-10-28T09:07:03.320 に答える