mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 09:23:03 +00:00
fix: 修复wayland环境下应用打开窗口无法显示预览的问题
wayland环境下,窗管无法提供windowId,原来通过windowID的方式获取截图的方式失效,因此窗管增加了通过窗体的UUID的方式来获取截图的接口,前端通过传入UUID的方式来获取截图 Log: 修复wayland环境下无法显示预览图的问题 Influence: wayland-任务栏打开一个应用窗口,鼠标放入到窗口上,查看预览图 Bug: https://pms.uniontech.com/bug-view-140919.html Change-Id: I3506e8edb8f875ba7c5d7b3d3471ad51a3170f58
This commit is contained in:
parent
d6f0860fcf
commit
fc8294c46c
@ -450,7 +450,8 @@ void DockItemManager::onShowMultiWindowChanged()
|
|||||||
{
|
{
|
||||||
if (m_appInter->showMultiWindow()) {
|
if (m_appInter->showMultiWindow()) {
|
||||||
// 如果当前设置支持窗口多开,那么就依次对每个APPItem加载多开窗口
|
// 如果当前设置支持窗口多开,那么就依次对每个APPItem加载多开窗口
|
||||||
for (const QPointer<DockItem> &dockItem : m_itemList) {
|
for (int i = 0; i < m_itemList.size(); i++) {
|
||||||
|
const QPointer<DockItem> &dockItem = m_itemList[i];
|
||||||
if (dockItem->itemType() != DockItem::ItemType::App)
|
if (dockItem->itemType() != DockItem::ItemType::App)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -34,21 +34,6 @@
|
|||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
|
|
||||||
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)
|
AppMultiItem::AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &windowInfo, QWidget *parent)
|
||||||
: DockItem(parent)
|
: DockItem(parent)
|
||||||
, m_appItem(appItem)
|
, m_appItem(appItem)
|
||||||
@ -90,113 +75,6 @@ DockItem::ItemType AppMultiItem::itemType() const
|
|||||||
return DockItem::AppMultiWindow;
|
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<bool> 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<QVariant> args;
|
|
||||||
args << QVariant::fromValue(m_winId);
|
|
||||||
args << QVariant::fromValue(quint32(width() - 20));
|
|
||||||
args << QVariant::fromValue(quint32(height() - 20));
|
|
||||||
|
|
||||||
QImage image;
|
|
||||||
QDBusReply<QString> 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<SHMInfo *>(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()
|
void AppMultiItem::initMenu()
|
||||||
{
|
{
|
||||||
QAction *actionOpen = new QAction(m_menu);
|
QAction *actionOpen = new QAction(m_menu);
|
||||||
@ -232,7 +110,12 @@ void AppMultiItem::paintEvent(QPaintEvent *)
|
|||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||||
|
|
||||||
if (m_snapImage.isNull()) {
|
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());
|
DStyleHelper dstyle(style());
|
||||||
|
@ -24,9 +24,6 @@
|
|||||||
#include "dockitem.h"
|
#include "dockitem.h"
|
||||||
#include "dbusutil.h"
|
#include "dbusutil.h"
|
||||||
|
|
||||||
struct SHMInfo;
|
|
||||||
struct _XImage;
|
|
||||||
typedef _XImage XImage;
|
|
||||||
class AppItem;
|
class AppItem;
|
||||||
|
|
||||||
class AppMultiItem : public DockItem
|
class AppMultiItem : public DockItem
|
||||||
@ -51,10 +48,6 @@ protected:
|
|||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isKWinAvailable() const;
|
|
||||||
QImage snapImage() const;
|
|
||||||
SHMInfo *getImageDSHM() const;
|
|
||||||
XImage *getImageXlib() const;
|
|
||||||
void initMenu();
|
void initMenu();
|
||||||
void initConnection();
|
void initConnection();
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "previewcontainer.h"
|
#include "previewcontainer.h"
|
||||||
#include "../widgets/tipswidget.h"
|
#include "../widgets/tipswidget.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "imageutil.h"
|
||||||
|
|
||||||
#include <DStyle>
|
#include <DStyle>
|
||||||
|
|
||||||
@ -212,27 +213,13 @@ void AppSnapshot::fetchSnapshot()
|
|||||||
|
|
||||||
// 优先使用窗管进行窗口截图
|
// 优先使用窗管进行窗口截图
|
||||||
if (isKWinAvailable()) {
|
if (isKWinAvailable()) {
|
||||||
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot"));
|
#ifdef USE_AM
|
||||||
qDebug() << "windowsID:"<< m_wid;
|
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<QVariant> args;
|
|
||||||
args << QVariant::fromValue(m_wid);
|
|
||||||
args << QVariant::fromValue(quint32(SNAP_WIDTH));
|
|
||||||
args << QVariant::fromValue(quint32(SNAP_HEIGHT));
|
|
||||||
|
|
||||||
QDBusReply<QString> 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();
|
m_snapshotSrcRect = m_snapshot.rect();
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QRegion>
|
#include <QRegion>
|
||||||
#include <QBitmap>
|
#include <QBitmap>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusReply>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
|
||||||
@ -84,3 +87,53 @@ QCursor* ImageUtil::loadQCursorFromX11Cursor(const char* theme, const char* curs
|
|||||||
XcursorImagesDestroy(images);
|
XcursorImagesDestroy(images);
|
||||||
return cursor;
|
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<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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<QVariant> args;
|
||||||
|
args << QVariant::fromValue(uuid);
|
||||||
|
args << QVariant::fromValue(quint32(width));
|
||||||
|
args << QVariant::fromValue(quint32(height));
|
||||||
|
|
||||||
|
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 {
|
||||||
|
qDebug() << "get current workspace background error: "<< reply.error().message();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
@ -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 QString &localPath, const int size, const qreal ratio);
|
||||||
static const QPixmap loadSvg(const QString &iconName, const QSize size, const qreal ratio = qApp->devicePixelRatio());
|
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 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
|
#endif // IMAGEUTIL_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user