From fc8294c46c2f113690bf41fe9139f193cc9695cf Mon Sep 17 00:00:00 2001 From: donghualin Date: Thu, 18 Aug 2022 10:42:52 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dwayland=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E4=B8=8B=E5=BA=94=E7=94=A8=E6=89=93=E5=BC=80=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E6=97=A0=E6=B3=95=E6=98=BE=E7=A4=BA=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wayland环境下,窗管无法提供windowId,原来通过windowID的方式获取截图的方式失效,因此窗管增加了通过窗体的UUID的方式来获取截图的接口,前端通过传入UUID的方式来获取截图 Log: 修复wayland环境下无法显示预览图的问题 Influence: wayland-任务栏打开一个应用窗口,鼠标放入到窗口上,查看预览图 Bug: https://pms.uniontech.com/bug-view-140919.html Change-Id: I3506e8edb8f875ba7c5d7b3d3471ad51a3170f58 --- frame/controller/dockitemmanager.cpp | 3 +- frame/item/appmultiitem.cpp | 129 ++------------------------ frame/item/appmultiitem.h | 7 -- frame/item/components/appsnapshot.cpp | 27 ++---- frame/util/imageutil.cpp | 53 +++++++++++ frame/util/imageutil.h | 3 + 6 files changed, 71 insertions(+), 151 deletions(-) diff --git a/frame/controller/dockitemmanager.cpp b/frame/controller/dockitemmanager.cpp index c773fb16e..3742aec42 100644 --- a/frame/controller/dockitemmanager.cpp +++ b/frame/controller/dockitemmanager.cpp @@ -450,7 +450,8 @@ void DockItemManager::onShowMultiWindowChanged() { if (m_appInter->showMultiWindow()) { // 如果当前设置支持窗口多开,那么就依次对每个APPItem加载多开窗口 - for (const QPointer &dockItem : m_itemList) { + for (int i = 0; i < m_itemList.size(); i++) { + const QPointer &dockItem = m_itemList[i]; if (dockItem->itemType() != DockItem::ItemType::App) continue; diff --git a/frame/item/appmultiitem.cpp b/frame/item/appmultiitem.cpp index 02f89f79b..f387912f8 100644 --- a/frame/item/appmultiitem.cpp +++ b/frame/item/appmultiitem.cpp @@ -34,21 +34,6 @@ #include #include -struct SHMInfo { - long shmid; - long width; - long height; - long bytesPerLine; - long format; - - struct Rect { - long x; - long y; - long width; - long height; - } rect; -}; - AppMultiItem::AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &windowInfo, QWidget *parent) : DockItem(parent) , m_appItem(appItem) @@ -90,113 +75,6 @@ DockItem::ItemType AppMultiItem::itemType() const return DockItem::AppMultiWindow; } -bool AppMultiItem::isKWinAvailable() const -{ - if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.KWin"))) { - QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), QStringLiteral("org.kde.kwin.Effects")); - QDBusReply reply = interface.call(QStringLiteral("isEffectLoaded"), "screenshot"); - - return reply.value(); - } - return false; -} - -QImage AppMultiItem::snapImage() const -{ - // 优先使用窗管进行窗口截图 - if (isKWinAvailable()) { - QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); - - QList args; - args << QVariant::fromValue(m_winId); - args << QVariant::fromValue(quint32(width() - 20)); - args << QVariant::fromValue(quint32(height() - 20)); - - QImage image; - QDBusReply reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("screenshotForWindowExtend"), args); - if(reply.isValid()){ - const QString tmpFile = reply.value(); - if (QFile::exists(tmpFile)) { - image.load(tmpFile); - qDebug() << "reply: " << tmpFile; - QFile::remove(tmpFile); - } else { - qDebug() << "get current workspace bckground error, file does not exist : " << tmpFile; - } - } else { - qDebug() << "get current workspace bckground error: "<< reply.error().message(); - } - return image; - } - - // get window image from shm(only for deepin app) - SHMInfo *info = getImageDSHM(); - QImage image; - uchar *image_data = 0; - if (info) { - qDebug() << "get Image from dxcbplugin SHM..."; - image_data = (uchar *)shmat(info->shmid, 0, 0); - if ((qint64)image_data != -1) - return QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format); - - qDebug() << "invalid pointer of shm!"; - image_data = nullptr; - } - - QImage qimage; - XImage *ximage; - if (!image_data || qimage.isNull()) { - ximage = getImageXlib(); - if (!ximage) - return QImage(); - - qimage = QImage((const uchar *)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32); - } - - return image; -} - -SHMInfo *AppMultiItem::getImageDSHM() const -{ - const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display(); - if (!display) { - qWarning() << "Error: get display failed!"; - return nullptr; - } - - Atom atom_prop = XInternAtom(display, "_DEEPIN_DXCB_SHM_INFO", true); - if (!atom_prop) { - return nullptr; - } - - Atom actual_type_return_deepin_shm; - int actual_format_return_deepin_shm; - unsigned long nitems_return_deepin_shm; - unsigned long bytes_after_return_deepin_shm; - unsigned char *prop_return_deepin_shm; - - XGetWindowProperty(display, m_winId, atom_prop, 0, 32 * 9, false, AnyPropertyType, - &actual_type_return_deepin_shm, &actual_format_return_deepin_shm, &nitems_return_deepin_shm, - &bytes_after_return_deepin_shm, &prop_return_deepin_shm); - - return reinterpret_cast(prop_return_deepin_shm); -} - -XImage *AppMultiItem::getImageXlib() const -{ - const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display(); - if (!display) { - qWarning() << "Error: get display failed!"; - return nullptr; - } - - Window unused_window; - int unused_int; - unsigned unused_uint, w, h; - XGetGeometry(display, m_winId, &unused_window, &unused_int, &unused_int, &w, &h, &unused_uint, &unused_uint); - return XGetImage(display, m_winId, 0, 0, w, h, AllPlanes, ZPixmap); -} - void AppMultiItem::initMenu() { QAction *actionOpen = new QAction(m_menu); @@ -232,7 +110,12 @@ void AppMultiItem::paintEvent(QPaintEvent *) painter.setRenderHint(QPainter::SmoothPixmapTransform, true); if (m_snapImage.isNull()) { - m_snapImage = snapImage(); +#ifdef USE_AM + if (Utils::IS_WAYLAND_DISPLAY) + m_snapImage = ImageUtil::loadWindowThumb(m_windowInfo.uuid, width() - 20, height() - 20); + else +#endif + m_snapImage = ImageUtil::loadWindowThumb(m_winId, width() - 20, height() - 20); } DStyleHelper dstyle(style()); diff --git a/frame/item/appmultiitem.h b/frame/item/appmultiitem.h index 36e261a89..ea9963f0c 100644 --- a/frame/item/appmultiitem.h +++ b/frame/item/appmultiitem.h @@ -24,9 +24,6 @@ #include "dockitem.h" #include "dbusutil.h" -struct SHMInfo; -struct _XImage; -typedef _XImage XImage; class AppItem; class AppMultiItem : public DockItem @@ -51,10 +48,6 @@ protected: void mouseReleaseEvent(QMouseEvent *event) override; private: - bool isKWinAvailable() const; - QImage snapImage() const; - SHMInfo *getImageDSHM() const; - XImage *getImageXlib() const; void initMenu(); void initConnection(); diff --git a/frame/item/components/appsnapshot.cpp b/frame/item/components/appsnapshot.cpp index fa5fcd509..dd598235a 100644 --- a/frame/item/components/appsnapshot.cpp +++ b/frame/item/components/appsnapshot.cpp @@ -23,6 +23,7 @@ #include "previewcontainer.h" #include "../widgets/tipswidget.h" #include "utils.h" +#include "imageutil.h" #include @@ -212,27 +213,13 @@ void AppSnapshot::fetchSnapshot() // 优先使用窗管进行窗口截图 if (isKWinAvailable()) { - QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); - qDebug() << "windowsID:"<< m_wid; +#ifdef USE_AM + if (Utils::IS_WAYLAND_DISPLAY) + m_snapshot = ImageUtil::loadWindowThumb(m_windowInfo.uuid, SNAP_WIDTH, SNAP_HEIGHT); + else +#endif + m_snapshot = ImageUtil::loadWindowThumb(m_wid, SNAP_WIDTH, SNAP_HEIGHT); - QList args; - args << QVariant::fromValue(m_wid); - args << QVariant::fromValue(quint32(SNAP_WIDTH)); - args << QVariant::fromValue(quint32(SNAP_HEIGHT)); - - QDBusReply reply = interface.callWithArgumentList(QDBus::Block,QStringLiteral("screenshotForWindowExtend"), args); - if(reply.isValid()){ - const QString tmpFile = reply.value(); - if (QFile::exists(tmpFile)) { - m_snapshot.load(tmpFile); - qDebug() << "reply: " << tmpFile; - QFile::remove(tmpFile); - } else { - qDebug() << "get current workspace bckground error, file does not exist : " << tmpFile; - } - } else { - qDebug() << "get current workspace bckground error: "<< reply.error().message(); - } m_snapshotSrcRect = m_snapshot.rect(); } else { do { diff --git a/frame/util/imageutil.cpp b/frame/util/imageutil.cpp index a2a3f2014..e3bc0a00c 100644 --- a/frame/util/imageutil.cpp +++ b/frame/util/imageutil.cpp @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include @@ -84,3 +87,53 @@ QCursor* ImageUtil::loadQCursorFromX11Cursor(const char* theme, const char* curs XcursorImagesDestroy(images); return cursor; } + +QImage ImageUtil::loadWindowThumb(const WId &windowId, int width, int height) +{ + QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); + + QList args; + args << QVariant::fromValue(windowId); + args << QVariant::fromValue(quint32(width)); + args << QVariant::fromValue(quint32(height)); + + QDBusReply reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("screenshotForWindowExtend"), args); + if(reply.isValid()){ + const QString tmpFile = reply.value(); + if (QFile::exists(tmpFile)) { + QImage image(tmpFile); + QFile::remove(tmpFile); + return image; + } + qDebug() << "get current workspace background error, file does not exist : " << tmpFile; + } else { + qDebug() << "get current workspace background error: "<< reply.error().message(); + } + + return QImage(); +} + +QImage ImageUtil::loadWindowThumb(const QString &uuid, int width, int height) +{ + QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); + + QList args; + args << QVariant::fromValue(uuid); + args << QVariant::fromValue(quint32(width)); + args << QVariant::fromValue(quint32(height)); + + QDBusReply reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("screenshotForWindowExtendUuid"), args); + if(reply.isValid()){ + const QString tmpFile = reply.value(); + if (QFile::exists(tmpFile)) { + QImage image(tmpFile); + QFile::remove(tmpFile); + return image; + } + qDebug() << "get current workspace background error, file does not exist : " << tmpFile; + } else { + qDebug() << "get current workspace background error: "<< reply.error().message(); + } + + return QImage(); +} diff --git a/frame/util/imageutil.h b/frame/util/imageutil.h index 0ed1b3c37..204b10153 100644 --- a/frame/util/imageutil.h +++ b/frame/util/imageutil.h @@ -35,6 +35,9 @@ public: static const QPixmap loadSvg(const QString &iconName, const QString &localPath, const int size, const qreal ratio); static const QPixmap loadSvg(const QString &iconName, const QSize size, const qreal ratio = qApp->devicePixelRatio()); static QCursor* loadQCursorFromX11Cursor(const char* theme, const char* cursorName, int cursorSize); + // 加载窗口的预览图 + static QImage loadWindowThumb(const WId &windowId, int width, int height); // x11下加载,用windowID + static QImage loadWindowThumb(const QString &uuid, int width, int height); // wayland下加载,用uuid }; #endif // IMAGEUTIL_H