Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions panels/dock/taskmanager/package/AppItem.qml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ Item {
}
}

Timer {
id: previewTimer
interval: 500
running: false
repeat: false
property int xOffset: 0
property int yOffset: 0
onTriggered: {
taskmanager.Applet.showItemPreview(root.itemId, Panel.rootObject, xOffset, yOffset, Panel.position)
}
}

MouseArea {
id: mouseArea
anchors.fill: parent
Expand All @@ -194,6 +206,7 @@ Item {
})
}
toolTip.close()
closeItemPreview()
}
onClicked: function (mouse) {
if (mouse.button === Qt.RightButton) {
Expand Down Expand Up @@ -224,21 +237,31 @@ Item {
xOffset = (Panel.position == 1 ? -interval : interval + Panel.dockSize)
yOffset = itemPos.y + (root.height / 2)
}
taskmanager.Applet.showItemPreview(root.itemId, Panel.rootObject, xOffset, yOffset, Panel.position)
previewTimer.xOffset = xOffset
previewTimer.yOffset = yOffset
previewTimer.start()
}

onExited: {
if (windows.length === 0) {
toolTip.close()
return
}
taskmanager.Applet.hideItemPreview()
closeItemPreview()
}

PanelToolTip {
id: toolTip
text: root.name
}

function closeItemPreview() {
if (previewTimer.running) {
previewTimer.stop()
} else {
taskmanager.Applet.hideItemPreview()
}
}
}

onWindowsChanged: {
Expand Down
135 changes: 72 additions & 63 deletions panels/dock/taskmanager/x11preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ enum {
WindowIdRole = Qt::UserRole + 1,
WindowTitleRole,
WindowIconRole,
WindowPreviewContentRole,
};

class AppItemWindowModel : public QAbstractListModel
Expand Down Expand Up @@ -74,6 +75,9 @@ class AppItemWindowModel : public QAbstractListModel
case WindowIconRole: {
return m_item->getAppendWindows()[index.row()]->icon();
}
case WindowPreviewContentRole: {
return fetchWindowPreview(m_item->getAppendWindows()[index.row()]->id());
}
}

return QVariant();
Expand All @@ -95,6 +99,67 @@ class AppItemWindowModel : public QAbstractListModel
});
}

private:
QPixmap fetchWindowPreview(const uint32_t& winId) const
{
// TODO: check kwin is load screenshot plugin
if (!WM_HELPER->hasComposite()) return QPixmap();

// pipe read write fd
int fd[2];

if (pipe(fd) < 0) {
qDebug() << "failed to create pipe";
return QPixmap();
}

QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/ScreenShot2"), QStringLiteral("org.kde.KWin.ScreenShot2"));
// 第一个参数,winID或者UUID
QList<QVariant> args;
args << QVariant::fromValue(QString::number(winId));
// 第二个参数,需要截图的选项
QVariantMap option;
option["include-decoration"] = true;
option["include-cursor"] = false;
option["native-resolution"] = true;
args << QVariant::fromValue(option);
// 第三个参数,文件描述符
args << QVariant::fromValue(QDBusUnixFileDescriptor(fd[1]));

QDBusReply<QVariantMap> reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("CaptureWindow"), args);

// close write
::close(fd[1]);

if (!reply.isValid()) {
::close(fd[0]);
qDebug() << "get current workspace background error: "<< reply.error().message();
return QPixmap();
}

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(fd[0], QIODevice::ReadOnly)) {
file.close();
::close(fd[0]);
return QPixmap();
}

QImage::Format qimageFormat = static_cast<QImage::Format>(imageFormat);
int bitsCountPerPixel = QImage::toPixelFormat(qimageFormat).bitsPerPixel();

QByteArray fileContent = file.read(imageHeight * imageWidth * bitsCountPerPixel / 8);
QImage image(reinterpret_cast<uchar *>(fileContent.data()), imageWidth, imageHeight, imageStride, qimageFormat);
// close read
::close(fd[0]);
return QPixmap::fromImage(image);
}

private:
QPointer<AppItem> m_item;
};
Expand All @@ -115,7 +180,7 @@ class AppItemWindowDeletegate : public QAbstractItemDelegate
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
if (WM_HELPER->hasComposite()) {
auto pixmap = fetchWindowPreview(index.data(WindowIdRole).toUInt());
auto pixmap = index.data(WindowPreviewContentRole).value<QPixmap>();
auto size = pixmap.size().scaled(option.rect.size() - QSize(8, 8), Qt::KeepAspectRatio);
QRect imageRect((option.rect.left() + (option.rect.width() - size.width()) / 2), (option.rect.top() + (option.rect.height() - size.height()) / 2), size.width(), size.height());
painter->drawPixmap(imageRect, pixmap);
Expand Down Expand Up @@ -173,67 +238,6 @@ class AppItemWindowDeletegate : public QAbstractItemDelegate

return closeButton;
}

private:
QPixmap fetchWindowPreview(const uint32_t& winId) const
{
// TODO: check kwin is load screenshot plugin
if (!WM_HELPER->hasComposite()) return QPixmap();

// pipe read write fd
int fd[2];

if (pipe(fd) < 0) {
qDebug() << "failed to create pipe";
return QPixmap();
}

QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/ScreenShot2"), QStringLiteral("org.kde.KWin.ScreenShot2"));
// 第一个参数,winID或者UUID
QList<QVariant> args;
args << QVariant::fromValue(QString::number(winId));
// 第二个参数,需要截图的选项
QVariantMap option;
option["include-decoration"] = true;
option["include-cursor"] = false;
option["native-resolution"] = true;
args << QVariant::fromValue(option);
// 第三个参数,文件描述符
args << QVariant::fromValue(QDBusUnixFileDescriptor(fd[1]));

QDBusReply<QVariantMap> reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("CaptureWindow"), args);
if(!reply.isValid()) {
::close(fd[1]);
::close(fd[0]);
qDebug() << "get current workspace background error: "<< reply.error().message();
return QPixmap();
}

// close write
::close(fd[1]);

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(fd[0], QIODevice::ReadOnly)) {
file.close();
::close(fd[0]);
return QPixmap();
}

QImage::Format qimageFormat = static_cast<QImage::Format>(imageFormat);
int bitsCountPerPixel = QImage::toPixelFormat(qimageFormat).bitsPerPixel();

QByteArray fileContent = file.read(imageHeight * imageWidth * bitsCountPerPixel / 8);
QImage image(reinterpret_cast<uchar *>(fileContent.data()), imageWidth, imageHeight, imageStride, qimageFormat);
// close read
::close(fd[0]);
return QPixmap::fromImage(image);
}
};

X11WindowPreviewContainer::X11WindowPreviewContainer(X11WindowMonitor* monitor, QWidget *parent)
Expand All @@ -245,7 +249,7 @@ X11WindowPreviewContainer::X11WindowPreviewContainer(X11WindowMonitor* monitor,
{
m_hideTimer = new QTimer(this);
m_hideTimer->setSingleShot(true);
m_hideTimer->setInterval(300);
m_hideTimer->setInterval(500);

setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint);
setMouseTracking(true);
Expand Down Expand Up @@ -477,6 +481,11 @@ void X11WindowPreviewContainer::initUI()

void X11WindowPreviewContainer::updateSize()
{
if (m_previewItem->getAppendWindows().size() == 0) {
DBlurEffectWidget::hide();
return;
}

auto screenSize = screen()->size();
int height = 0, width = 0;

Expand Down