0

我正在使用 Xlib 和 Qt 4.7 编写自己的窗口管理器。所以在我的应用程序中,我捕获了来自 XServer 的所有事件。

问题是下一个。当我在“MapRequest”事件上显示窗口时,有时它的内部内容会显示在单独的窗口中。大多数情况下,我在打开新网页后在浏览器(如 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 回答