2023-02-16 13:51:55 +08:00
|
|
|
|
// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
|
|
|
|
|
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
2022-09-06 11:36:55 +08:00
|
|
|
|
//
|
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
2017-09-18 14:33:44 +08:00
|
|
|
|
|
2017-05-22 15:11:07 +08:00
|
|
|
|
#include "appsnapshot.h"
|
2017-07-31 17:06:10 +08:00
|
|
|
|
#include "previewcontainer.h"
|
2020-06-29 15:35:51 +08:00
|
|
|
|
#include "../widgets/tipswidget.h"
|
2023-06-13 15:05:44 +08:00
|
|
|
|
#include "taskmanager/taskmanager.h"
|
|
|
|
|
#include "taskmanager/xcbutils.h"
|
2021-11-05 21:48:33 +08:00
|
|
|
|
#include "utils.h"
|
2022-08-18 10:42:52 +00:00
|
|
|
|
#include "imageutil.h"
|
2017-05-22 15:11:07 +08:00
|
|
|
|
|
2019-08-27 15:03:40 +08:00
|
|
|
|
#include <DStyle>
|
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
#include <X11/X.h>
|
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
#include <X11/Xatom.h>
|
2018-07-30 11:22:56 +08:00
|
|
|
|
#include <sys/shm.h>
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
|
|
|
|
#include <QX11Info>
|
|
|
|
|
#include <QPainter>
|
2017-05-24 14:12:50 +08:00
|
|
|
|
#include <QVBoxLayout>
|
2018-07-30 11:22:56 +08:00
|
|
|
|
#include <QSizeF>
|
2018-11-07 15:26:56 +08:00
|
|
|
|
#include <QTimer>
|
2022-10-11 08:29:02 +00:00
|
|
|
|
#include <QPainterPath>
|
2023-06-13 15:05:44 +08:00
|
|
|
|
#include <QDBusConnectionInterface>
|
|
|
|
|
#include <QDBusInterface>
|
|
|
|
|
#include <QDBusReply>
|
2018-07-30 11:22:56 +08:00
|
|
|
|
|
2019-08-27 15:03:40 +08:00
|
|
|
|
struct SHMInfo {
|
2018-07-30 11:22:56 +08:00
|
|
|
|
long shmid;
|
|
|
|
|
long width;
|
|
|
|
|
long height;
|
|
|
|
|
long bytesPerLine;
|
|
|
|
|
long format;
|
|
|
|
|
|
2019-08-27 15:03:40 +08:00
|
|
|
|
struct Rect {
|
2018-07-30 11:22:56 +08:00
|
|
|
|
long x;
|
|
|
|
|
long y;
|
|
|
|
|
long width;
|
|
|
|
|
long height;
|
|
|
|
|
} rect;
|
|
|
|
|
};
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
2020-06-29 15:35:51 +08:00
|
|
|
|
using namespace Dock;
|
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
|
AppSnapshot::AppSnapshot(const WId wid, QWidget *parent)
|
2018-11-07 15:26:56 +08:00
|
|
|
|
: QWidget(parent)
|
|
|
|
|
, m_wid(wid)
|
2023-03-08 09:53:29 +08:00
|
|
|
|
, m_closeAble(true)
|
2020-08-28 10:39:24 +08:00
|
|
|
|
, m_isWidowHidden(false)
|
2021-02-07 17:38:19 +08:00
|
|
|
|
, m_title(new TipsWidget(this))
|
2021-09-14 17:08:36 +08:00
|
|
|
|
, m_3DtitleBtn(nullptr)
|
2018-11-07 15:26:56 +08:00
|
|
|
|
, m_waitLeaveTimer(new QTimer(this))
|
2020-06-13 11:39:32 +08:00
|
|
|
|
, m_closeBtn2D(new DIconButton(this))
|
2018-11-07 15:26:56 +08:00
|
|
|
|
, m_wmHelper(DWindowManagerHelper::instance())
|
2017-05-22 17:17:29 +08:00
|
|
|
|
{
|
2021-02-07 17:38:19 +08:00
|
|
|
|
m_closeBtn2D->setFixedSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH);
|
|
|
|
|
m_closeBtn2D->setIconSize(QSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH));
|
2020-05-06 17:28:16 +08:00
|
|
|
|
m_closeBtn2D->setObjectName("closebutton-2d");
|
2020-06-13 11:39:32 +08:00
|
|
|
|
m_closeBtn2D->setIcon(QIcon(":/icons/resources/close_round_normal.svg"));
|
2019-03-20 11:23:33 +08:00
|
|
|
|
m_closeBtn2D->setVisible(false);
|
2020-06-13 11:39:32 +08:00
|
|
|
|
m_closeBtn2D->setFlat(true);
|
|
|
|
|
m_closeBtn2D->installEventFilter(this);
|
|
|
|
|
|
2018-07-02 16:21:43 +08:00
|
|
|
|
m_title->setObjectName("AppSnapshotTitle");
|
2017-05-24 14:12:50 +08:00
|
|
|
|
|
|
|
|
|
QHBoxLayout *centralLayout = new QHBoxLayout;
|
|
|
|
|
centralLayout->addWidget(m_title);
|
|
|
|
|
centralLayout->setMargin(0);
|
|
|
|
|
|
|
|
|
|
setLayout(centralLayout);
|
2017-07-04 14:34:38 +08:00
|
|
|
|
setAcceptDrops(true);
|
2022-01-13 09:15:56 +08:00
|
|
|
|
resize(SNAP_WIDTH / 2, SNAP_HEIGHT / 2);
|
2017-05-24 14:12:50 +08:00
|
|
|
|
|
2020-06-13 11:39:32 +08:00
|
|
|
|
connect(m_closeBtn2D, &DIconButton::clicked, this, &AppSnapshot::closeWindow, Qt::QueuedConnection);
|
2017-05-24 14:12:50 +08:00
|
|
|
|
connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, &AppSnapshot::compositeChanged, Qt::QueuedConnection);
|
|
|
|
|
QTimer::singleShot(1, this, &AppSnapshot::compositeChanged);
|
2017-05-22 17:17:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 10:39:24 +08:00
|
|
|
|
void AppSnapshot::setWindowState()
|
|
|
|
|
{
|
|
|
|
|
if (m_isWidowHidden) {
|
2023-06-13 15:05:44 +08:00
|
|
|
|
TaskManager::instance()->MinimizeWindow(m_wid);
|
2020-08-28 10:39:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-14 17:08:36 +08:00
|
|
|
|
// 每次更新窗口信息时更新标题
|
|
|
|
|
void AppSnapshot::updateTitle()
|
|
|
|
|
{
|
|
|
|
|
// 2D不显示
|
|
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!m_3DtitleBtn) {
|
|
|
|
|
m_3DtitleBtn = new DPushButton(this);
|
|
|
|
|
m_3DtitleBtn->setAccessibleName("AppPreviewTitle");
|
|
|
|
|
m_3DtitleBtn->setBackgroundRole(QPalette::Base);
|
|
|
|
|
m_3DtitleBtn->setForegroundRole(QPalette::Text);
|
|
|
|
|
m_3DtitleBtn->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
m_3DtitleBtn->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
|
|
|
m_3DtitleBtn->setFixedHeight(36);
|
|
|
|
|
m_3DtitleBtn->setVisible(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QFontMetrics fm(m_3DtitleBtn->font());
|
2022-11-04 06:29:03 +00:00
|
|
|
|
int textWidth = fm.horizontalAdvance(title()) + 10 + BTN_TITLE_MARGIN;
|
2021-09-14 17:08:36 +08:00
|
|
|
|
int titleWidth = SNAP_WIDTH - (TITLE_MARGIN * 2 + BORDER_MARGIN);
|
|
|
|
|
|
|
|
|
|
if (textWidth < titleWidth) {
|
|
|
|
|
m_3DtitleBtn->setFixedWidth(textWidth);
|
|
|
|
|
m_3DtitleBtn->setText(title());
|
|
|
|
|
} else {
|
|
|
|
|
QString str = title();
|
|
|
|
|
/*某些特殊字符只显示一半 如"Q"," W",所以加一个空格保证字符显示完整,*/
|
|
|
|
|
str.insert(0, " ");
|
|
|
|
|
QString strTtile = m_3DtitleBtn->fontMetrics().elidedText(str, Qt::ElideRight, titleWidth - BTN_TITLE_MARGIN);
|
|
|
|
|
m_3DtitleBtn->setText(strTtile);
|
|
|
|
|
m_3DtitleBtn->setFixedWidth(titleWidth + BTN_TITLE_MARGIN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移动到预览图中下
|
|
|
|
|
m_3DtitleBtn->move(QPoint(SNAP_WIDTH / 2, SNAP_HEIGHT - m_3DtitleBtn->height() / 2 - TITLE_MARGIN) - m_3DtitleBtn->rect().center());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AppSnapshot::setTitleVisible(bool bVisible)
|
|
|
|
|
{
|
|
|
|
|
if (m_3DtitleBtn)
|
|
|
|
|
m_3DtitleBtn->setVisible(bVisible && m_wmHelper->hasComposite());
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-23 15:32:03 +08:00
|
|
|
|
void AppSnapshot::closeWindow() const
|
|
|
|
|
{
|
2021-12-09 18:46:27 +08:00
|
|
|
|
if (Utils::IS_WAYLAND_DISPLAY) {
|
2023-06-13 15:05:44 +08:00
|
|
|
|
TaskManager::instance()->closeWindow(static_cast<uint>(m_wid));
|
2021-12-09 18:46:27 +08:00
|
|
|
|
} else {
|
|
|
|
|
const auto display = QX11Info::display();
|
|
|
|
|
if (!display) {
|
|
|
|
|
qWarning() << "Error: get display failed!";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XEvent e;
|
|
|
|
|
|
|
|
|
|
memset(&e, 0, sizeof(e));
|
|
|
|
|
e.xclient.type = ClientMessage;
|
|
|
|
|
e.xclient.window = m_wid;
|
|
|
|
|
e.xclient.message_type = XInternAtom(display, "WM_PROTOCOLS", true);
|
|
|
|
|
e.xclient.format = 32;
|
|
|
|
|
e.xclient.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", false);
|
|
|
|
|
e.xclient.data.l[1] = CurrentTime;
|
|
|
|
|
|
|
|
|
|
Q_EMIT requestCloseAppSnapshot();
|
|
|
|
|
|
|
|
|
|
XSendEvent(display, m_wid, false, NoEventMask, &e);
|
|
|
|
|
XFlush(display);
|
2021-03-12 13:20:13 +08:00
|
|
|
|
}
|
2017-05-23 15:32:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-24 14:12:50 +08:00
|
|
|
|
void AppSnapshot::compositeChanged() const
|
|
|
|
|
{
|
|
|
|
|
const bool composite = m_wmHelper->hasComposite();
|
|
|
|
|
|
|
|
|
|
m_title->setVisible(!composite);
|
2018-02-22 17:19:55 +08:00
|
|
|
|
|
|
|
|
|
QTimer::singleShot(1, this, &AppSnapshot::fetchSnapshot);
|
2017-05-24 14:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 14:19:52 +08:00
|
|
|
|
void AppSnapshot::setWindowInfo(const WindowInfo &info)
|
2017-05-24 10:56:43 +08:00
|
|
|
|
{
|
2018-02-22 14:19:52 +08:00
|
|
|
|
m_windowInfo = info;
|
2019-12-20 10:22:08 +08:00
|
|
|
|
QFontMetrics fm(m_title->font());
|
2022-01-20 14:47:12 +08:00
|
|
|
|
QString strTtile = m_title->fontMetrics().elidedText(m_windowInfo.title, Qt::ElideRight, SNAP_WIDTH - SNAP_CLOSE_BTN_WIDTH - SNAP_CLOSE_BTN_MARGIN);
|
2019-12-20 10:22:08 +08:00
|
|
|
|
m_title->setText(strTtile);
|
2021-09-14 17:08:36 +08:00
|
|
|
|
updateTitle();
|
2021-11-05 21:53:23 +08:00
|
|
|
|
|
|
|
|
|
// 只有在X11下,才能通过XGetWindowProperty获取窗口属性
|
|
|
|
|
if (qEnvironmentVariable("XDG_SESSION_TYPE").contains("x11")) {
|
|
|
|
|
getWindowState();
|
|
|
|
|
}
|
2017-05-24 10:56:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-04 14:34:38 +08:00
|
|
|
|
void AppSnapshot::dragEnterEvent(QDragEnterEvent *e)
|
|
|
|
|
{
|
|
|
|
|
QWidget::dragEnterEvent(e);
|
|
|
|
|
|
|
|
|
|
if (m_wmHelper->hasComposite())
|
|
|
|
|
emit entered(m_wid);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
|
void AppSnapshot::fetchSnapshot()
|
|
|
|
|
{
|
2017-05-24 14:12:50 +08:00
|
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
|
return;
|
|
|
|
|
|
2018-07-30 11:22:56 +08:00
|
|
|
|
SHMInfo *info = nullptr;
|
|
|
|
|
uchar *image_data = nullptr;
|
|
|
|
|
XImage *ximage = nullptr;
|
|
|
|
|
|
2021-11-25 01:55:52 -04:00
|
|
|
|
// 优先使用窗管进行窗口截图
|
|
|
|
|
if (isKWinAvailable()) {
|
2022-10-11 08:29:02 +00:00
|
|
|
|
const QString windowInfoId = Utils::IS_WAYLAND_DISPLAY ? m_windowInfo.uuid : QString::number(m_wid);
|
|
|
|
|
m_pixmap = ImageUtil::loadWindowThumb(windowInfoId);
|
2021-11-05 21:53:23 +08:00
|
|
|
|
} else {
|
|
|
|
|
do {
|
|
|
|
|
// get window image from shm(only for deepin app)
|
2022-10-11 08:29:02 +00:00
|
|
|
|
QImage qimage;
|
2021-11-05 21:53:23 +08:00
|
|
|
|
info = getImageDSHM();
|
|
|
|
|
if (info) {
|
|
|
|
|
qDebug() << "get Image from dxcbplugin SHM...";
|
|
|
|
|
image_data = (uchar *)shmat(info->shmid, 0, 0);
|
|
|
|
|
if ((qint64)image_data != -1) {
|
2022-10-11 08:29:02 +00:00
|
|
|
|
qimage = QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format);
|
2022-08-11 11:31:16 +08:00
|
|
|
|
break;
|
2022-05-12 13:04:32 +08:00
|
|
|
|
}
|
2021-11-05 21:53:23 +08:00
|
|
|
|
qDebug() << "invalid pointer of shm!";
|
|
|
|
|
image_data = nullptr;
|
2022-02-28 19:08:05 +08:00
|
|
|
|
}
|
2022-05-12 13:04:32 +08:00
|
|
|
|
|
2021-11-05 21:53:23 +08:00
|
|
|
|
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...";
|
2021-11-25 01:55:52 -04:00
|
|
|
|
// guoyao note:这里会造成内存泄漏,而且是通过demo在X环境经过验证,改用xcb库同样会有内存泄漏,这里暂时未找到解决方案,所以优先使用kwin提供的接口
|
2021-11-05 21:53:23 +08:00
|
|
|
|
ximage = getImageXlib();
|
|
|
|
|
if (!ximage) {
|
|
|
|
|
qDebug() << "get Image from Xlib failed! giving up...";
|
|
|
|
|
emit requestCheckWindow();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-03-13 13:16:55 +08:00
|
|
|
|
qimage = QImage(reinterpret_cast<uchar*>(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32).copy();
|
2021-11-05 21:53:23 +08:00
|
|
|
|
}
|
2018-07-30 11:22:56 +08:00
|
|
|
|
|
2021-11-05 21:53:23 +08:00
|
|
|
|
Q_ASSERT(!qimage.isNull());
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
2022-10-11 08:29:02 +00:00
|
|
|
|
m_pixmap = QPixmap::fromImage(qimage);
|
2021-11-05 21:53:23 +08:00
|
|
|
|
} while (false);
|
2022-08-11 11:31:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 11:22:56 +08:00
|
|
|
|
if (image_data) shmdt(image_data);
|
|
|
|
|
if (ximage) XDestroyImage(ximage);
|
|
|
|
|
if (info) XFree(info);
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-22 17:54:59 +08:00
|
|
|
|
void AppSnapshot::enterEvent(QEvent *e)
|
|
|
|
|
{
|
|
|
|
|
QWidget::enterEvent(e);
|
|
|
|
|
|
2018-11-07 15:26:56 +08:00
|
|
|
|
if (!m_wmHelper->hasComposite()) {
|
2021-02-07 17:38:19 +08:00
|
|
|
|
m_closeBtn2D->move(width() - m_closeBtn2D->width() - SNAP_CLOSE_BTN_MARGIN, (height() - m_closeBtn2D->height()) / 2);
|
2019-03-20 11:23:33 +08:00
|
|
|
|
m_closeBtn2D->setVisible(true);
|
2019-08-27 15:03:40 +08:00
|
|
|
|
} else {
|
2019-04-23 18:17:07 +08:00
|
|
|
|
emit entered(wid());
|
2018-11-07 15:26:56 +08:00
|
|
|
|
}
|
2018-09-07 11:16:40 +08:00
|
|
|
|
|
|
|
|
|
update();
|
2017-05-24 14:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AppSnapshot::leaveEvent(QEvent *e)
|
|
|
|
|
{
|
|
|
|
|
QWidget::leaveEvent(e);
|
|
|
|
|
|
2019-03-20 11:23:33 +08:00
|
|
|
|
m_closeBtn2D->setVisible(false);
|
2019-04-23 18:17:07 +08:00
|
|
|
|
|
2018-09-07 11:16:40 +08:00
|
|
|
|
update();
|
2017-05-22 17:54:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
|
void AppSnapshot::paintEvent(QPaintEvent *e)
|
|
|
|
|
{
|
2021-12-31 15:09:12 +08:00
|
|
|
|
Q_UNUSED(e);
|
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
|
QPainter painter(this);
|
|
|
|
|
|
2019-08-27 15:03:40 +08:00
|
|
|
|
if (!m_wmHelper->hasComposite()) {
|
2017-05-25 10:13:38 +08:00
|
|
|
|
if (underMouse())
|
|
|
|
|
painter.fillRect(rect(), QColor(255, 255, 255, 255 * .2));
|
2017-05-24 14:12:50 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-11 08:29:02 +00:00
|
|
|
|
if (m_pixmap.isNull())
|
2017-05-22 17:17:29 +08:00
|
|
|
|
return;
|
|
|
|
|
|
2017-10-10 16:40:17 +08:00
|
|
|
|
const auto ratio = devicePixelRatioF();
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
2018-02-22 14:19:52 +08:00
|
|
|
|
// draw attention background
|
2019-08-27 15:03:40 +08:00
|
|
|
|
if (m_windowInfo.attention) {
|
2018-02-22 14:19:52 +08:00
|
|
|
|
painter.setBrush(QColor(241, 138, 46, 255 * .8));
|
|
|
|
|
painter.setPen(Qt::NoPen);
|
|
|
|
|
painter.drawRoundedRect(rect(), 5, 5);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-27 15:03:40 +08:00
|
|
|
|
DStyleHelper dstyle(style());
|
|
|
|
|
const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius);
|
|
|
|
|
|
2022-10-11 08:29:02 +00:00
|
|
|
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
|
|
|
|
QRect imageRect(8, 8, width() - 16, height() - 16);
|
2019-08-27 15:03:40 +08:00
|
|
|
|
painter.setPen(Qt::NoPen);
|
2022-10-11 08:29:02 +00:00
|
|
|
|
QPainterPath path;
|
|
|
|
|
path.addRoundedRect(imageRect, radius * ratio, radius * ratio);
|
|
|
|
|
painter.setClipPath(path);
|
|
|
|
|
painter.drawPixmap(imageRect, m_pixmap, m_pixmap.rect());
|
2017-05-22 17:17:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-22 17:54:59 +08:00
|
|
|
|
void AppSnapshot::mousePressEvent(QMouseEvent *e)
|
|
|
|
|
{
|
|
|
|
|
QWidget::mousePressEvent(e);
|
|
|
|
|
|
|
|
|
|
emit clicked(m_wid);
|
|
|
|
|
}
|
2018-07-30 11:22:56 +08:00
|
|
|
|
|
2020-06-13 11:39:32 +08:00
|
|
|
|
bool AppSnapshot::eventFilter(QObject *watched, QEvent *e)
|
|
|
|
|
{
|
2021-02-07 17:38:19 +08:00
|
|
|
|
if (watched == m_closeBtn2D) {
|
2023-03-08 09:53:29 +08:00
|
|
|
|
if (e->type() == QEvent::HoverEnter || e->type() == QEvent::HoverMove) {
|
2020-06-13 11:39:32 +08:00
|
|
|
|
m_closeBtn2D->setIcon(QIcon(":/icons/resources/close_round_hover.svg"));
|
2023-03-08 09:53:29 +08:00
|
|
|
|
} else if (e->type() == QEvent::HoverLeave) {
|
2020-06-13 11:39:32 +08:00
|
|
|
|
m_closeBtn2D->setIcon(QIcon(":/icons/resources/close_round_normal.svg"));
|
2023-03-08 09:53:29 +08:00
|
|
|
|
} else if (e->type() == QEvent::MouseButtonPress) {
|
2020-06-13 11:39:32 +08:00
|
|
|
|
m_closeBtn2D->setIcon(QIcon(":/icons/resources/close_round_press.svg"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-08 09:53:29 +08:00
|
|
|
|
return QWidget::eventFilter(watched, e);
|
2020-06-13 11:39:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-25 10:22:59 +08:00
|
|
|
|
void AppSnapshot::resizeEvent(QResizeEvent *event)
|
|
|
|
|
{
|
|
|
|
|
QWidget::resizeEvent(event);
|
|
|
|
|
fetchSnapshot();
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-27 15:03:40 +08:00
|
|
|
|
SHMInfo *AppSnapshot::getImageDSHM()
|
2018-07-30 11:22:56 +08:00
|
|
|
|
{
|
2021-11-05 21:48:33 +08:00
|
|
|
|
const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display();
|
2021-03-10 18:40:46 +08:00
|
|
|
|
if (!display) {
|
2021-11-05 21:48:33 +08:00
|
|
|
|
qWarning() << "Error: get display failed!";
|
2021-03-10 18:40:46 +08:00
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 11:22:56 +08:00
|
|
|
|
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_wid, atom_prop, 0, 32 * 9, false, AnyPropertyType,
|
2019-08-27 15:03:40 +08:00
|
|
|
|
&actual_type_return_deepin_shm, &actual_format_return_deepin_shm, &nitems_return_deepin_shm,
|
|
|
|
|
&bytes_after_return_deepin_shm, &prop_return_deepin_shm);
|
2018-07-30 11:22:56 +08:00
|
|
|
|
|
|
|
|
|
//qDebug() << 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 *AppSnapshot::getImageXlib()
|
|
|
|
|
{
|
2021-11-05 21:48:33 +08:00
|
|
|
|
const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display();
|
2021-03-10 18:40:46 +08:00
|
|
|
|
if (!display) {
|
2021-11-05 21:48:33 +08:00
|
|
|
|
qWarning() << "Error: get display failed!";
|
2021-03-10 18:40:46 +08:00
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 11:22:56 +08:00
|
|
|
|
Window unused_window;
|
|
|
|
|
int unused_int;
|
|
|
|
|
unsigned unused_uint, w, h;
|
|
|
|
|
XGetGeometry(display, m_wid, &unused_window, &unused_int, &unused_int, &w, &h, &unused_uint, &unused_uint);
|
|
|
|
|
return XGetImage(display, m_wid, 0, 0, w, h, AllPlanes, ZPixmap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRect AppSnapshot::rectRemovedShadow(const QImage &qimage, unsigned char *prop_to_return_gtk)
|
|
|
|
|
{
|
2021-11-05 21:48:33 +08:00
|
|
|
|
const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display();
|
2021-03-12 13:20:13 +08:00
|
|
|
|
if (!display) {
|
2021-11-05 21:48:33 +08:00
|
|
|
|
qWarning() << "Error: get display failed!";
|
2021-03-12 13:20:13 +08:00
|
|
|
|
return QRect();
|
|
|
|
|
}
|
2018-07-30 11:22:56 +08:00
|
|
|
|
|
|
|
|
|
const Atom gtk_frame_extents = XInternAtom(display, "_GTK_FRAME_EXTENTS", true);
|
|
|
|
|
Atom actual_type_return_gtk;
|
|
|
|
|
int actual_format_return_gtk;
|
|
|
|
|
unsigned long n_items_return_gtk;
|
|
|
|
|
unsigned long bytes_after_return_gtk;
|
|
|
|
|
|
|
|
|
|
const auto r = XGetWindowProperty(display, m_wid, gtk_frame_extents, 0, 4, false, XA_CARDINAL,
|
|
|
|
|
&actual_type_return_gtk, &actual_format_return_gtk, &n_items_return_gtk, &bytes_after_return_gtk, &prop_to_return_gtk);
|
2019-08-27 15:03:40 +08:00
|
|
|
|
if (!r && prop_to_return_gtk && n_items_return_gtk == 4 && actual_format_return_gtk == 32) {
|
2018-07-30 11:22:56 +08:00
|
|
|
|
qDebug() << "remove shadow frame...";
|
|
|
|
|
const unsigned long *extents = reinterpret_cast<const unsigned long *>(prop_to_return_gtk);
|
|
|
|
|
const int left = extents[0];
|
|
|
|
|
const int right = extents[1];
|
|
|
|
|
const int top = extents[2];
|
|
|
|
|
const int bottom = extents[3];
|
|
|
|
|
const int width = qimage.width();
|
|
|
|
|
const int height = qimage.height();
|
|
|
|
|
|
|
|
|
|
return QRect(left, top, width - left - right, height - top - bottom);
|
|
|
|
|
} else {
|
|
|
|
|
return QRect(0, 0, qimage.width(), qimage.height());
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-28 10:39:24 +08:00
|
|
|
|
|
|
|
|
|
void AppSnapshot::getWindowState()
|
|
|
|
|
{
|
|
|
|
|
Atom actual_type;
|
|
|
|
|
int actual_format;
|
|
|
|
|
unsigned long i, num_items, bytes_after;
|
|
|
|
|
unsigned char *properties = nullptr;
|
|
|
|
|
|
|
|
|
|
m_isWidowHidden = false;
|
|
|
|
|
|
2021-11-05 21:48:33 +08:00
|
|
|
|
const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display();
|
2021-03-12 13:20:13 +08:00
|
|
|
|
if (!display) {
|
2021-11-05 21:48:33 +08:00
|
|
|
|
qWarning() << "Error: get display failed!";
|
2021-03-12 13:20:13 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2020-08-28 10:39:24 +08:00
|
|
|
|
Atom atom_prop = XInternAtom(display, "_NET_WM_STATE", true);
|
|
|
|
|
if (!atom_prop) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Status status = XGetWindowProperty(display, m_wid, atom_prop, 0, LONG_MAX, False, AnyPropertyType, &actual_type, &actual_format, &num_items, &bytes_after, &properties);
|
|
|
|
|
if (status != Success) {
|
|
|
|
|
qDebug() << "Fail to get window state";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Atom *atoms = reinterpret_cast<Atom *>(properties);
|
2021-02-07 17:38:19 +08:00
|
|
|
|
for (i = 0; i < num_items; ++i) {
|
2020-08-28 10:39:24 +08:00
|
|
|
|
const char *atomName = XGetAtomName(display, atoms[i]);
|
|
|
|
|
|
|
|
|
|
if (strcmp(atomName, "_NET_WM_STATE_HIDDEN") == 0) {
|
|
|
|
|
m_isWidowHidden = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (properties) {
|
|
|
|
|
XFree(properties);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-05 21:53:23 +08:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|