桌面任务栏预览图问题分析

发布时间:2023年12月18日

?现象描述:

用户某软件在使用过程中发现部分应用子窗口显示在了任务栏窗口缩略图中。

期望:

窗口缩略图仅显示主窗口,不显示子窗口或弹出窗口等。

问题分析定位:

缩略图显示子窗口说明任务栏获取到的需要显示的窗口类型中有需要任务栏屏蔽的窗口类型,应获取到此窗口类型并进行屏蔽

利用xprop命令获取窗口类型,它是一个用于在X服务器中显示窗口属性的实用命令

xprop | grep TYPE

获取到需要屏蔽的窗口为Dialog,ComboBox,Utility类型的窗口.

任务栏需要在预览图中进行窗口屏蔽的操作

备注-xprop使用说明:

终端输入xprop并回车后,光标将变为十字光标,此时点击想要了解的窗口,就能获取该窗口的状态,类型等信息?

输出结果中的 _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG, _KDE_NET_WM_WINDOW_TYPE_OVERRIDE, _NET_WM_WINDOW_TYPE_NORMAL 为我们想要了解的窗口的类型

也可直接通过xprop | grep TYPE命令直接获取窗口类型

解决方案:

任务栏处理预览图规则:

任务栏代码中的处理:

监听到桌面有窗口添加,执行onWindowAdded函数

??? connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &UKUITaskBar::onWindowAdded);

在onWindowAdded函数中进行判断,仅在acceptWindow(window)返回值为真的情况下进行预览图添加

void UKUITaskBar::onWindowAdded(WId window)
{
    auto const pos = mKnownWindows.find(window);
    if (mKnownWindows.end() == pos && acceptWindow(window))
        addWindow(window);
}

在acceptWindow函数中对ignoreList中的窗口类型进行屏蔽
QFlags<NET::WindowTypeMask> ignoreList;
ignoreList新增:
    ignoreList |= NET::DialogMask;
    ignoreList |= NET::UtilityMask;
    ignoreList |= NET::ComboBoxMask;
    if (NET::typeMatchesMask(info.windowType(NET::AllTypesMask), ignoreList))        return false;

/**
 * @brief acceptWindow 对接收的窗口类型进行过滤
 * @param window 窗口id
 * @return 返回值为false代表不接受次窗口在任务栏预览图中显示
 */
bool UKUITaskBar::acceptWindow(WId window) const
{
    QFlags<NET::WindowTypeMask> ignoreList;
    ignoreList |= NET::DesktopMask;
    ignoreList |= NET::DockMask;
    ignoreList |= NET::SplashMask;
    ignoreList |= NET::ToolbarMask;
    ignoreList |= NET::MenuMask;
    ignoreList |= NET::PopupMenuMask;
ignoreList |= NET::NotificationMask;
    ignoreList |= NET::DialogMask;
    ignoreList |= NET::UtilityMask;
    ignoreList |= NET::ComboBoxMask;

    KWindowInfo info(window, NET::WMWindowType | NET::WMState, NET::WM2TransientFor);
    if (!info.valid())
        return false;
    if (NET::typeMatchesMask(info.windowType(NET::AllTypesMask), ignoreList))
        return false;
    if (info.state() & NET::SkipTaskbar)
        return false;
    // WM_TRANSIENT_FOR hint not set - normal window
    WId transFor = info.transientFor();
    if (transFor == 0 || transFor == window || transFor == (WId) QX11Info::appRootWindow())
        return true;
    info = KWindowInfo(transFor, NET::WMWindowType);
    QFlags<NET::WindowTypeMask> normalFlag;
    normalFlag |= NET::NormalMask;
    normalFlag |= NET::DialogMask;
    normalFlag |= NET::UtilityMask;
    return !NET::typeMatchesMask(info.windowType(NET::AllTypesMask), normalFlag);
}

备注-任务栏预览图核心代码:
QPixmap qimageFromXImage(XImage* ximage)
{
    QImage::Format format = QImage::Format_ARGB32_Premultiplied;
    if (ximage->depth == 24)
        format = QImage::Format_RGB32;
    else if (ximage->depth == 16)
        format = QImage::Format_RGB16;

    QImage image = QImage(reinterpret_cast<uchar*>(ximage->data),
                          ximage->width, ximage->height,
                          ximage->bytes_per_line, format).copy();

    // 大端还是小端
    if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && ximage->byte_order == MSBFirst)
            || (QSysInfo::ByteOrder == QSysInfo::BigEndian && ximage->byte_order == LSBFirst)) {

        for (int i = 0; i < image.height(); i++) {
            if (ximage->depth == 16) {
                ushort* p = reinterpret_cast<ushort*>(image.scanLine(i));
                ushort* end = p + image.width();
                while (p < end) {
                    *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
                    p++;
                }
            } else {
                uint* p = reinterpret_cast<uint*>(image.scanLine(i));
                uint* end = p + image.width();
                while (p < end) {
                    *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
                         | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
                    p++;
                }
            }
        }
    }

    // 修复alpha通道
    if (format == QImage::Format_RGB32) {
        QRgb* p = reinterpret_cast<QRgb*>(image.bits());
        for (int y = 0; y < ximage->height; ++y) {
            for (int x = 0; x < ximage->width; ++x)
                p[x] |= 0xff000000;
            p += ximage->bytes_per_line / 4;
        }
    }
    return QPixmap::fromImage(image);
}

文章来源:https://blog.csdn.net/weixin_38887743/article/details/135056222
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。