ウィンドウマネージャ。 Xウィンドウの内部コンテンツは別のウィンドウにありますか?

私は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()<<(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);
0

1 答え

問題は、トップレベルのウィンドウのみを表示する必要があることと、表示されることが想定されている場合のみです。私も同じ問題があり、MapRequestイベントハンドラより多くの場所でクライアントウィンドウを表示していたことがわかりました。だから、あなたのコードをチェックしてください。明示的な要求なしにウィンドウを表示する別のイベントを処理しているかもしれません!

それ以上の助けが必要な場合は、すべてのイベントハンドラを投稿してから、私の答えをコメントしてください。私はそれを編集して、あなたに助けてもらいます。

0
追加された
コードを別の回答として追加しないでください。代わりに質問を編集してください。
追加された 著者 AlQafir,
次に、Webページ上にフラッシュオブジェクトが表示されると、それはX Windowです。全画面ボタンをクリックすると、ウィンドウはトップレベルウィンドウとして親子化され、サイズ変更されます。 ReparentNotifyハンドラでoverride_redirectフラグを使用するのを忘れていますか?
追加された 著者 AlQafir,
私はすでに問題の原因を見つけました。クライアント用のイベントマスクに1つの奇妙なフラグがありました(SubstructureRedirectMask)。このフラグは、ルートウィンドウと自分が作成したウィンドウに対してのみ必要です。しかし、1つのケースではまだ動作しません。ウェブページ(たとえばYouTube)に動画をアップロードしてフルスクリーンに拡大しようとすると、別のウィンドウに動画が表示されます。私はMapRequest以外の場所に罫線を作成していないと確信しています。 「トップレベルウィンドウ」のチェックが正しくない可能性がありますか?
追加された 著者 Nemo,
ReparentNotifyハンドラはまったくありません。しかし、私はこのイベントのデバッグ出力を持っており、ビデオ付きウィンドウからReparentNotifyを受け取ることはできません.MapRequestのみです。また、MapRequestのデバッグ出力には、「override_redirect」ウィンドウではなく「トップレベル」であることが示されています。それはNORMALタイプです。私はこの窓が国境を持ってはならないことを知る方法を知っている。他のどのプロパティがそれに影響を与えることができますか?
追加された 著者 Nemo,