mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-02 15:45:21 +00:00
fix: 修复wayland下窗口预览为空的问题
将获取窗口预览图的接口修改为CaptureWindow接口来获取,在wayland和x11下接口统一 Log: 修复wayland下窗口预览图为空的问题 Influence: 进入wayland,鼠标放入任务栏已经打开的窗口图标上,观察预览图是否显示 Bug: https://pms.uniontech.com/bug-view-140919.html Bug: https://pms.uniontech.com/bug-view-150475.html Change-Id: Idc18a356c8df19a73130362e839a61ed26108d23
This commit is contained in:
parent
ebccd73378
commit
cb96a7bab8
@ -109,20 +109,13 @@ void AppMultiItem::paintEvent(QPaintEvent *)
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
if (m_snapImage.isNull()) {
|
||||
#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);
|
||||
}
|
||||
if (m_pixmap.isNull())
|
||||
m_pixmap = ImageUtil::loadWindowThumb(Utils::IS_WAYLAND_DISPLAY ? m_windowInfo.uuid : QString::number(m_winId));
|
||||
|
||||
DStyleHelper dstyle(style());
|
||||
const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius);
|
||||
QRect itemRect = rect();
|
||||
itemRect.marginsRemoved(QMargins(6, 6, 6, 6));
|
||||
QPixmap pixmapWindowIcon = QPixmap::fromImage(m_snapImage);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(rect(), radius, radius);
|
||||
painter.fillPath(path, Qt::transparent);
|
||||
@ -133,12 +126,12 @@ void AppMultiItem::paintEvent(QPaintEvent *)
|
||||
painter.fillPath(path, backColor);
|
||||
}
|
||||
|
||||
itemRect = m_snapImage.rect();
|
||||
itemRect = m_pixmap.rect();
|
||||
int itemWidth = itemRect.width();
|
||||
int itemHeight = itemRect.height();
|
||||
int x = (rect().width() - itemWidth) / 2;
|
||||
int y = (rect().height() - itemHeight) / 2;
|
||||
painter.drawPixmap(QRect(x, y, itemWidth, itemHeight), pixmapWindowIcon);
|
||||
painter.drawPixmap(QRect(x, y, itemWidth, itemHeight), m_pixmap);
|
||||
|
||||
QPixmap pixmapAppIcon;
|
||||
ThemeAppIcon::getIcon(pixmapAppIcon, m_entryInter->icon(), qMin(width(), height()) * 0.8);
|
||||
|
@ -59,7 +59,7 @@ private:
|
||||
AppItem *m_appItem;
|
||||
WindowInfo m_windowInfo;
|
||||
DockEntryInter *m_entryInter;
|
||||
QImage m_snapImage;
|
||||
QPixmap m_pixmap;
|
||||
WId m_winId;
|
||||
QMenu *m_menu;
|
||||
};
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QSizeF>
|
||||
#include <QTimer>
|
||||
#include <QPainterPath>
|
||||
|
||||
struct SHMInfo {
|
||||
long shmid;
|
||||
@ -206,31 +207,24 @@ void AppSnapshot::fetchSnapshot()
|
||||
if (!m_wmHelper->hasComposite())
|
||||
return;
|
||||
|
||||
QImage qimage;
|
||||
SHMInfo *info = nullptr;
|
||||
uchar *image_data = nullptr;
|
||||
XImage *ximage = nullptr;
|
||||
|
||||
// 优先使用窗管进行窗口截图
|
||||
if (isKWinAvailable()) {
|
||||
#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);
|
||||
|
||||
m_snapshotSrcRect = m_snapshot.rect();
|
||||
const QString windowInfoId = Utils::IS_WAYLAND_DISPLAY ? m_windowInfo.uuid : QString::number(m_wid);
|
||||
m_pixmap = ImageUtil::loadWindowThumb(windowInfoId);
|
||||
} else {
|
||||
do {
|
||||
// get window image from shm(only for deepin app)
|
||||
QImage qimage;
|
||||
info = getImageDSHM();
|
||||
if (info) {
|
||||
qDebug() << "get Image from dxcbplugin SHM...";
|
||||
image_data = (uchar *)shmat(info->shmid, 0, 0);
|
||||
if ((qint64)image_data != -1) {
|
||||
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);
|
||||
qimage = QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format);
|
||||
break;
|
||||
}
|
||||
qDebug() << "invalid pointer of shm!";
|
||||
@ -253,23 +247,10 @@ void AppSnapshot::fetchSnapshot()
|
||||
|
||||
Q_ASSERT(!qimage.isNull());
|
||||
|
||||
// remove shadow frame
|
||||
m_snapshotSrcRect = rectRemovedShadow(qimage, nullptr);
|
||||
m_snapshot = qimage;
|
||||
m_pixmap = QPixmap::fromImage(qimage);
|
||||
} while (false);
|
||||
}
|
||||
|
||||
QSizeF size(rect().marginsRemoved(QMargins(8, 8, 8, 8)).size());
|
||||
const auto ratio = devicePixelRatioF();
|
||||
size = m_snapshotSrcRect.size().scaled(size * ratio, Qt::KeepAspectRatio);
|
||||
qreal scale = qreal(size.width()) / m_snapshotSrcRect.width();
|
||||
m_snapshot = m_snapshot.scaled(qRound(m_snapshot.width() * scale), qRound(m_snapshot.height() * scale),
|
||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
m_snapshotSrcRect.moveTop(m_snapshotSrcRect.top() * scale + 0.5);
|
||||
m_snapshotSrcRect.moveLeft(m_snapshotSrcRect.left() * scale + 0.5);
|
||||
m_snapshotSrcRect.setWidth(size.width() - 0.5);
|
||||
m_snapshotSrcRect.setHeight(size.height() - 0.5);
|
||||
|
||||
if (image_data) shmdt(image_data);
|
||||
if (ximage) XDestroyImage(ximage);
|
||||
if (info) XFree(info);
|
||||
@ -312,7 +293,7 @@ void AppSnapshot::paintEvent(QPaintEvent *e)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_snapshot.isNull())
|
||||
if (m_pixmap.isNull())
|
||||
return;
|
||||
|
||||
const auto ratio = devicePixelRatioF();
|
||||
@ -324,22 +305,20 @@ void AppSnapshot::paintEvent(QPaintEvent *e)
|
||||
painter.drawRoundedRect(rect(), 5, 5);
|
||||
}
|
||||
|
||||
// draw image
|
||||
const QImage &im = m_snapshot;
|
||||
|
||||
const qreal offset_x = width() / 2.0 - m_snapshotSrcRect.width() / ratio / 2 - m_snapshotSrcRect.left() / ratio;
|
||||
const qreal offset_y = height() / 2.0 - m_snapshotSrcRect.height() / ratio / 2 - m_snapshotSrcRect.top() / ratio;
|
||||
const qreal offset_x = width() / 2.0 - SNAP_WIDTH / ratio / 2;
|
||||
const qreal offset_y = height() / 2.0 - SNAP_HEIGHT / ratio / 2;
|
||||
|
||||
DStyleHelper dstyle(style());
|
||||
const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius);
|
||||
|
||||
QBrush brush;
|
||||
brush.setTextureImage(im);
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.scale(1 / ratio, 1 / ratio);
|
||||
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter.translate(QPoint(offset_x * ratio, offset_y * ratio));
|
||||
painter.drawRoundedRect(m_snapshotSrcRect, radius * ratio, radius * ratio);
|
||||
QRect imageRect(8, 8, width() - 16, height() - 16);
|
||||
painter.setPen(Qt::NoPen);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(imageRect, radius * ratio, radius * ratio);
|
||||
painter.setClipPath(path);
|
||||
painter.drawPixmap(imageRect, m_pixmap, m_pixmap.rect());
|
||||
}
|
||||
|
||||
void AppSnapshot::mousePressEvent(QMouseEvent *e)
|
||||
|
@ -68,8 +68,7 @@ public:
|
||||
inline bool attentioned() const { return m_windowInfo.attention; }
|
||||
inline bool closeAble() const { return m_closeAble; }
|
||||
inline void setCloseAble(const bool value) { m_closeAble = value; }
|
||||
inline const QImage snapshot() const { return m_snapshot; }
|
||||
inline const QRectF snapshotGeometry() const { return m_snapshotSrcRect; }
|
||||
inline const QPixmap snapshot() const { return m_pixmap; }
|
||||
inline const QString title() const { return m_windowInfo.title; }
|
||||
void setWindowState();
|
||||
void setTitleVisible(bool bVisible);
|
||||
@ -108,8 +107,7 @@ private:
|
||||
|
||||
bool m_closeAble;
|
||||
bool m_isWidowHidden;
|
||||
QImage m_snapshot;
|
||||
QRectF m_snapshotSrcRect;
|
||||
QPixmap m_pixmap;
|
||||
|
||||
Dock::TipsWidget *m_title;
|
||||
DPushButton *m_3DtitleBtn;
|
||||
|
@ -109,7 +109,7 @@ void FloatingPreview::paintEvent(QPaintEvent *e)
|
||||
if (m_tracked.isNull())
|
||||
return;
|
||||
|
||||
const QImage &snapshot = m_tracked->snapshot();
|
||||
const QPixmap &snapshot = m_tracked->snapshot();
|
||||
|
||||
if (snapshot.isNull())
|
||||
return;
|
||||
|
@ -32,9 +32,15 @@
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
#include <QFile>
|
||||
#include <QDBusUnixFileDescriptor>
|
||||
#include <QDir>
|
||||
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <iosfwd>
|
||||
|
||||
const QPixmap ImageUtil::loadSvg(const QString &iconName, const QString &localPath, const int size, const qreal ratio)
|
||||
{
|
||||
QIcon icon = QIcon::fromTheme(iconName);
|
||||
@ -88,52 +94,66 @@ QCursor* ImageUtil::loadQCursorFromX11Cursor(const char* theme, const char* curs
|
||||
return cursor;
|
||||
}
|
||||
|
||||
QImage ImageUtil::loadWindowThumb(const WId &windowId, int width, int height)
|
||||
QPixmap ImageUtil::loadWindowThumb(const QString &winInfoId)
|
||||
{
|
||||
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot"));
|
||||
// 在tmp下创建临时目录,用来存放缩略图
|
||||
QString thumbPath(imagePath());
|
||||
QDir dir(thumbPath);
|
||||
if (!dir.exists())
|
||||
dir.mkpath(thumbPath);
|
||||
|
||||
QList<QVariant> args;
|
||||
args << QVariant::fromValue(windowId);
|
||||
args << QVariant::fromValue(quint32(width));
|
||||
args << QVariant::fromValue(quint32(height));
|
||||
|
||||
QDBusReply<QString> 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();
|
||||
QString fileName = QString("%1/%2").arg(thumbPath).arg(winInfoId);
|
||||
int fileId = open(fileName.toLocal8Bit().data(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
||||
if (fileId < 0) {
|
||||
//打开文件失败
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/ScreenShot2"), QStringLiteral("org.kde.KWin.ScreenShot2"));
|
||||
// 第一个参数,winID或者UUID
|
||||
QList<QVariant> args;
|
||||
args << QVariant::fromValue(uuid);
|
||||
args << QVariant::fromValue(quint32(width));
|
||||
args << QVariant::fromValue(quint32(height));
|
||||
args << QVariant::fromValue(winInfoId);
|
||||
// 第二个参数,需要截图的选项
|
||||
QVariantMap option;
|
||||
option["include-decoration"] = true;
|
||||
option["include-cursor"] = false;
|
||||
option["native-resolution"] = true;
|
||||
args << QVariant::fromValue(option);
|
||||
// 第三个参数,文件描述符
|
||||
args << QVariant::fromValue(QDBusUnixFileDescriptor(fileId));
|
||||
|
||||
QDBusReply<QString> 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 {
|
||||
QDBusReply<QVariantMap> reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("CaptureWindow"), args);
|
||||
if(!reply.isValid()) {
|
||||
close(fileId);
|
||||
qDebug() << "get current workspace background error: "<< reply.error().message();
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
return QImage();
|
||||
QVariantMap imageInfo = reply.value();
|
||||
int imageWidth = imageInfo.value("width").toUInt();
|
||||
int imageHeight = imageInfo.value("height").toUInt();
|
||||
int imageStride = imageInfo.value("stride").toUInt();
|
||||
int imageFormat = imageInfo.value("format").toUInt();
|
||||
|
||||
QFile file;
|
||||
if (!file.open(fileId, QIODevice::ReadOnly)) {
|
||||
close(fileId);
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
if (file.size() == 0) {
|
||||
file.close();
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
QByteArray fileContent = file.readAll();
|
||||
QImage image(reinterpret_cast<uchar *>(fileContent.data()), imageWidth, imageHeight, imageStride, static_cast<QImage::Format>(imageFormat));
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
close(fileId);
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QString ImageUtil::imagePath()
|
||||
{
|
||||
return QString("%1/dde-dock/windowthumb").arg(QDir::tempPath());
|
||||
}
|
||||
|
@ -36,8 +36,10 @@ public:
|
||||
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
|
||||
static QPixmap loadWindowThumb(const QString &winInfoId); // 加载图片,参数为windowId或者窗口的UUID
|
||||
|
||||
private:
|
||||
static QString imagePath();
|
||||
};
|
||||
|
||||
#endif // IMAGEUTIL_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user