Qt在Linux下Wayland桌面上抓取桌面的一个坑

前言

最近WPS在适配了下Wayland的桌面环境,不得不说Gnome下的wayland比KDE的wayland的要稳定的多,然而,还是遇到了一些小坑,这里记录下。

Wayland只是一个协议(Protocol),就像X Window当前的协议——X11一样,它只定义了如何与内核通讯、如何与Client通讯,具体的策略,依然是交给开发者自己。所以Wayland依然 是贯彻“提供机制,而非策略”的Unix程序。

问题

先说问题,我这边发现调用Qt的抓屏函数screen->grabWindow,发现截图出来是黑的。具体表现就是WPS的截图功能无效;

结论

由于安全原因,Wayland下不支持非系统的软件截桌面的图

解决方案

但是我这边看过一个开源的截图工具,在wayland下的解决方案是调用系统的
https://github.com/lupoDharkael/flameshot/blob/b0326bcb6cb5ed5048e5574c682fce75cbfa7bbe/src/utils/screengrabber.cpp#L47

#ifdef Q_OS_LINUX
    if(m_info.waylandDectected()) {
        QPixmap res;
        // handle screenshot based on DE
        switch (m_info.windowManager()) {
        case DesktopInfo::GNOME: {
            // https://github.com/GNOME/gnome-shell/blob/695bfb96160033be55cfb5ac41c121998f98c328/data/org.gnome.Shell.Screenshot.xml
            QString path = FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png";
            QDBusInterface gnomeInterface(QStringLiteral("org.gnome.Shell"),
                                          QStringLiteral("/org/gnome/Shell/Screenshot"),
                                          QStringLiteral("org.gnome.Shell.Screenshot"));
            QDBusReply<bool> reply = gnomeInterface.call("Screenshot", false, false, path);
            if (reply.value()) {
                res = QPixmap(path);
            } else {
                ok = false;
            }
            break;
        } case DesktopInfo::KDE: {
            // https://github.com/KDE/spectacle/blob/517a7baf46a4ca0a45f32fd3f2b1b7210b180134/src/PlatformBackends/KWinWaylandImageGrabber.cpp#L145
            QDBusInterface kwinInterface(QStringLiteral("org.kde.KWin"),
                                         QStringLiteral("/Screenshot"),
                                         QStringLiteral("org.kde.kwin.Screenshot"));
            QDBusReply<QString> reply = kwinInterface.call("screenshotFullscreen");
            res = QPixmap(reply.value());
            break;
        } default:
            ok = false;
            break;
        }
        if (!ok) {
            SystemNotification().sendMessage(tr("Unable to capture screen"));
        }
        return res;
    }
#endif

文章作者: 张小飞
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 张小飞 !
  目录