fix: 新增在wayland环境下dock获取应用snap shot的逻辑

目前dock获取应用snap shot是通过函数getImageDSHM(),
该函数内部调用了XGetWindowProperty来获取窗口属性,
这将导致在wayland环境下无法正常运行。

Log: 修复wayland环境下获取应用snap shot导致任务栏崩溃的问题
Influence: 任务栏预览功能
Task: https://pms.uniontech.com/zentao/task-view-88921.html
Change-Id: Ic565c62512768fc3ba28c72a05cdd0f5162a8711
This commit is contained in:
范朋程 2021-11-05 21:53:23 +08:00
parent 828b6fb992
commit fe42f84253
2 changed files with 67 additions and 32 deletions

View File

@ -180,8 +180,12 @@ void AppSnapshot::setWindowInfo(const WindowInfo &info)
QFontMetrics fm(m_title->font()); QFontMetrics fm(m_title->font());
QString strTtile = m_title->fontMetrics().elidedText(m_windowInfo.title, Qt::ElideRight, width() - m_closeBtn2D->width()); QString strTtile = m_title->fontMetrics().elidedText(m_windowInfo.title, Qt::ElideRight, width() - m_closeBtn2D->width());
m_title->setText(strTtile); m_title->setText(strTtile);
getWindowState();
updateTitle(); updateTitle();
// 只有在X11下才能通过XGetWindowProperty获取窗口属性
if (qEnvironmentVariable("XDG_SESSION_TYPE").contains("x11")) {
getWindowState();
}
} }
void AppSnapshot::dragEnterEvent(QDragEnterEvent *e) void AppSnapshot::dragEnterEvent(QDragEnterEvent *e)
@ -202,41 +206,60 @@ void AppSnapshot::fetchSnapshot()
uchar *image_data = nullptr; uchar *image_data = nullptr;
XImage *ximage = nullptr; XImage *ximage = nullptr;
do { // wayland环境下使用KWin提供的接口
// get window image from shm(only for deepin app) if (isKWinAvailable() && Utils::IS_WAYLAND_DISPLAY) {
info = getImageDSHM(); QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot"));
if (info) { qDebug() << "windowsID:"<< m_wid;
qDebug() << "get Image from dxcbplugin SHM...";
//qDebug() << info->shmid << info->width << info->height << info->bytesPerLine << info->format << info->rect.x << info->rect.y << info->rect.width << info->rect.height; QList<QVariant> args;
image_data = (uchar *)shmat(info->shmid, 0, 0); args << QVariant::fromValue(m_wid);
if ((qint64)image_data != -1) { args << QVariant::fromValue(quint32(SNAP_WIDTH));
m_snapshot = QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format); args << QVariant::fromValue(quint32(SNAP_HEIGHT));
m_snapshotSrcRect = QRect(info->rect.x, info->rect.y, info->rect.width, info->rect.height);
break; QDBusReply<QString> reply = interface.callWithArgumentList(QDBus::Block,QStringLiteral("screenshotForWindowExtend"), args);
} if(reply.isValid()){
qDebug() << "invalid pointer of shm!"; m_snapshot.load(reply.value());
image_data = nullptr; qDebug() << "reply: "<<reply.value();
} else {
qDebug() << "get current workspace bckground error: "<< reply.error().message();
} }
m_snapshotSrcRect = m_snapshot.rect();
if (!image_data || qimage.isNull()) { } else {
// get window image from XGetImage(a little slow) do {
qDebug() << "get Image from dxcbplugin SHM failed!"; // get window image from shm(only for deepin app)
qDebug() << "get Image from Xlib..."; info = getImageDSHM();
ximage = getImageXlib(); if (info) {
if (!ximage) { qDebug() << "get Image from dxcbplugin SHM...";
qDebug() << "get Image from Xlib failed! giving up..."; image_data = (uchar *)shmat(info->shmid, 0, 0);
emit requestCheckWindow(); if ((qint64)image_data != -1) {
return; m_snapshot = QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format);
m_snapshotSrcRect = QRect(info->rect.x, info->rect.y, info->rect.width, info->rect.height);
break;
}
qDebug() << "invalid pointer of shm!";
image_data = nullptr;
} }
qimage = QImage((const uchar *)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32);
}
Q_ASSERT(!qimage.isNull()); if (!image_data || qimage.isNull()) {
// get window image from XGetImage(a little slow)
qDebug() << "get Image from dxcbplugin SHM failed!";
qDebug() << "get Image from Xlib...";
ximage = getImageXlib();
if (!ximage) {
qDebug() << "get Image from Xlib failed! giving up...";
emit requestCheckWindow();
return;
}
qimage = QImage((const uchar *)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32);
}
// remove shadow frame Q_ASSERT(!qimage.isNull());
m_snapshotSrcRect = rectRemovedShadow(qimage, nullptr);
m_snapshot = qimage; // remove shadow frame
} while (false); m_snapshotSrcRect = rectRemovedShadow(qimage, nullptr);
m_snapshot = qimage;
} while (false);
}
QSizeF size(rect().marginsRemoved(QMargins(8, 8, 8, 8)).size()); QSizeF size(rect().marginsRemoved(QMargins(8, 8, 8, 8)).size());
const auto ratio = devicePixelRatioF(); const auto ratio = devicePixelRatioF();
@ -463,3 +486,14 @@ void AppSnapshot::getWindowState()
XFree(properties); XFree(properties);
} }
} }
bool AppSnapshot::isKWinAvailable()
{
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.KWin"))) {
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), QStringLiteral("org.kde.kwin.Effects"));
QDBusReply<bool> reply = interface.call(QStringLiteral("isEffectLoaded"), "screenshot");
return reply.value();
}
return false;
}

View File

@ -77,6 +77,7 @@ public:
void setWindowState(); void setWindowState();
void setTitleVisible(bool bVisible); void setTitleVisible(bool bVisible);
QString appTitle() { return m_3DtitleBtn ? m_3DtitleBtn->text() : QString(); } QString appTitle() { return m_3DtitleBtn ? m_3DtitleBtn->text() : QString(); }
bool isKWinAvailable();
signals: signals:
void entered(const WId wid) const; void entered(const WId wid) const;