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-03-28 15:44:13 +08:00
|
|
|
#include "previewcontainer.h"
|
2021-11-05 21:29:32 +08:00
|
|
|
#include "imageutil.h"
|
|
|
|
#include "utils.h"
|
2017-03-28 15:44:13 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
#include <QDesktopWidget>
|
|
|
|
#include <QScreen>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QDragEnterEvent>
|
2021-05-17 13:20:54 +08:00
|
|
|
#include <QDesktopWidget>
|
2021-11-05 21:29:32 +08:00
|
|
|
#include <QCursor>
|
|
|
|
#include <QGSettings>
|
2017-07-31 17:06:10 +08:00
|
|
|
|
|
|
|
#define SPACING 0
|
|
|
|
#define MARGIN 0
|
|
|
|
#define SNAP_HEIGHT_WITHOUT_COMPOSITE 30
|
2017-03-28 15:44:13 +08:00
|
|
|
|
|
|
|
PreviewContainer::PreviewContainer(QWidget *parent)
|
2021-03-12 13:20:13 +08:00
|
|
|
: QWidget(parent)
|
|
|
|
, m_needActivate(false)
|
|
|
|
, m_floatingPreview(new FloatingPreview(this))
|
|
|
|
, m_mouseLeaveTimer(new QTimer(this))
|
|
|
|
, m_wmHelper(DWindowManagerHelper::instance())
|
2021-09-14 17:08:36 +08:00
|
|
|
, m_titleMode(HoverShow)
|
2017-03-28 15:44:13 +08:00
|
|
|
{
|
2021-02-07 17:38:19 +08:00
|
|
|
m_windowListLayout = new QBoxLayout(QBoxLayout::LeftToRight, this);
|
2017-07-31 17:06:10 +08:00
|
|
|
m_windowListLayout->setSpacing(SPACING);
|
|
|
|
m_windowListLayout->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
|
2017-03-28 15:44:13 +08:00
|
|
|
|
2017-05-04 10:39:03 +08:00
|
|
|
m_mouseLeaveTimer->setSingleShot(true);
|
2017-07-31 17:06:10 +08:00
|
|
|
m_mouseLeaveTimer->setInterval(300);
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
m_floatingPreview->setVisible(false);
|
|
|
|
|
2019-04-23 18:17:07 +08:00
|
|
|
m_waitForShowPreviewTimer = new QTimer(this);
|
|
|
|
m_waitForShowPreviewTimer->setSingleShot(true);
|
|
|
|
m_waitForShowPreviewTimer->setInterval(200);
|
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
setAcceptDrops(true);
|
|
|
|
setFixedSize(SNAP_WIDTH, SNAP_HEIGHT);
|
2017-05-04 10:39:03 +08:00
|
|
|
|
|
|
|
connect(m_mouseLeaveTimer, &QTimer::timeout, this, &PreviewContainer::checkMouseLeave, Qt::QueuedConnection);
|
2019-04-23 18:17:07 +08:00
|
|
|
connect(m_waitForShowPreviewTimer, &QTimer::timeout, this, &PreviewContainer::previewFloating);
|
2017-03-28 15:44:13 +08:00
|
|
|
}
|
|
|
|
|
2018-08-13 14:17:45 +08:00
|
|
|
void PreviewContainer::setWindowInfos(const WindowInfoMap &infos, const WindowList &allowClose)
|
2017-03-28 15:44:13 +08:00
|
|
|
{
|
2017-07-31 17:06:10 +08:00
|
|
|
// check removed window
|
2021-02-07 17:38:19 +08:00
|
|
|
for (auto it(m_snapshots.begin()); it != m_snapshots.end();) {
|
2020-12-18 16:18:58 +08:00
|
|
|
//初始化预览界面边距
|
|
|
|
it.value()->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
if (!infos.contains(it.key())) {
|
2017-07-31 17:06:10 +08:00
|
|
|
m_windowListLayout->removeWidget(it.value());
|
|
|
|
it.value()->deleteLater();
|
|
|
|
it = m_snapshots.erase(it);
|
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
for (auto it(infos.cbegin()); it != infos.cend(); ++it) {
|
2018-08-13 14:17:45 +08:00
|
|
|
const WId key = it.key();
|
|
|
|
if (!m_snapshots.contains(key))
|
|
|
|
appendSnapWidget(key);
|
|
|
|
m_snapshots[key]->setWindowInfo(it.value());
|
2023-06-13 15:05:44 +08:00
|
|
|
m_snapshots[key]->setCloseAble(allowClose.contains(key));
|
2017-07-31 17:06:10 +08:00
|
|
|
}
|
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
if (m_snapshots.isEmpty()) {
|
2019-04-12 17:17:19 +08:00
|
|
|
emit requestCancelPreviewWindow();
|
|
|
|
emit requestHidePopup();
|
2021-02-07 17:38:19 +08:00
|
|
|
}
|
2017-12-28 16:57:49 +08:00
|
|
|
|
2021-08-25 21:03:30 +08:00
|
|
|
adjustSize(m_wmHelper->hasComposite());
|
2017-07-31 17:06:10 +08:00
|
|
|
}
|
|
|
|
|
2021-09-14 17:08:36 +08:00
|
|
|
void PreviewContainer::setTitleDisplayMode(int mode)
|
|
|
|
{
|
|
|
|
m_titleMode = static_cast<TitleDisplayMode>(mode);
|
|
|
|
|
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_floatingPreview->setFloatingTitleVisible(m_titleMode == HoverShow);
|
|
|
|
|
|
|
|
for (AppSnapshot *snap : m_snapshots) {
|
|
|
|
snap->setTitleVisible(m_titleMode == AlwaysShow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
void PreviewContainer::updateLayoutDirection(const Dock::Position dockPos)
|
|
|
|
{
|
|
|
|
if (m_wmHelper->hasComposite() && (dockPos == Dock::Top || dockPos == Dock::Bottom))
|
|
|
|
m_windowListLayout->setDirection(QBoxLayout::LeftToRight);
|
|
|
|
else
|
|
|
|
m_windowListLayout->setDirection(QBoxLayout::TopToBottom);
|
|
|
|
|
2021-08-25 21:03:30 +08:00
|
|
|
adjustSize(m_wmHelper->hasComposite());
|
2017-07-31 17:06:10 +08:00
|
|
|
}
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
void PreviewContainer::checkMouseLeave()
|
|
|
|
{
|
|
|
|
const bool hover = underMouse();
|
|
|
|
|
2017-11-29 10:33:42 +08:00
|
|
|
if (hover)
|
|
|
|
return;
|
2017-11-20 14:46:56 +08:00
|
|
|
|
2017-11-29 10:33:42 +08:00
|
|
|
m_floatingPreview->setVisible(false);
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2019-05-22 16:39:31 +08:00
|
|
|
if (m_wmHelper->hasComposite()) {
|
|
|
|
if (m_needActivate) {
|
|
|
|
m_needActivate = false;
|
|
|
|
emit requestActivateWindow(m_floatingPreview->trackedWid());
|
|
|
|
} else {
|
2020-10-24 11:03:03 +08:00
|
|
|
Q_EMIT requestHidePopup();
|
2019-05-22 16:39:31 +08:00
|
|
|
emit requestCancelPreviewWindow();
|
|
|
|
}
|
2017-05-04 10:39:03 +08:00
|
|
|
}
|
2019-04-12 17:56:04 +08:00
|
|
|
|
|
|
|
emit requestHidePopup();
|
2017-07-31 17:06:10 +08:00
|
|
|
}
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2017-08-18 13:13:56 +08:00
|
|
|
void PreviewContainer::prepareHide()
|
|
|
|
{
|
|
|
|
m_mouseLeaveTimer->start();
|
|
|
|
}
|
|
|
|
|
2022-01-13 09:15:56 +08:00
|
|
|
void PreviewContainer::adjustSize(bool composite)
|
2017-07-31 17:06:10 +08:00
|
|
|
{
|
2022-01-13 09:15:56 +08:00
|
|
|
int count = m_snapshots.size();
|
|
|
|
const int screenWidth = QDesktopWidget().screenGeometry(this).width();
|
|
|
|
const int screenHeight = QDesktopWidget().screenGeometry(this).height();
|
2021-01-06 17:52:20 +08:00
|
|
|
|
2022-01-13 09:15:56 +08:00
|
|
|
//先根据屏幕宽高计算出能预览的最大数量,然后根据数量计算界面宽高
|
2021-02-07 17:38:19 +08:00
|
|
|
if (composite) {
|
|
|
|
// 3D
|
|
|
|
const int padding = 20;
|
|
|
|
const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight;
|
|
|
|
if (horizontal) {
|
2022-01-25 10:22:59 +08:00
|
|
|
count = qMin(count, screenWidth * 2 / SNAP_WIDTH);
|
2022-01-13 09:15:56 +08:00
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
const int h = SNAP_HEIGHT + MARGIN * 2;
|
|
|
|
const int w = SNAP_WIDTH * count + MARGIN * 2 + SPACING * (count - 1);
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
setFixedHeight(h);
|
2022-01-13 09:15:56 +08:00
|
|
|
setFixedWidth(qMin(w, screenWidth - padding));
|
2021-02-07 17:38:19 +08:00
|
|
|
} else {
|
2022-01-25 10:22:59 +08:00
|
|
|
count = qMin(count, screenWidth * 2 / SNAP_HEIGHT);
|
2022-01-13 09:15:56 +08:00
|
|
|
|
2022-10-14 09:01:35 +06:00
|
|
|
const int w = SNAP_WIDTH + MARGIN * 2;
|
2021-02-07 17:38:19 +08:00
|
|
|
const int h = SNAP_HEIGHT * count + MARGIN * 2 + SPACING * (count - 1);
|
2017-03-28 16:52:38 +08:00
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
setFixedWidth(w);
|
2022-01-13 09:15:56 +08:00
|
|
|
setFixedHeight(qMin(h, screenHeight - padding));
|
2021-02-07 17:38:19 +08:00
|
|
|
}
|
|
|
|
} else if (m_windowListLayout->count()) {
|
|
|
|
// 2D
|
2022-01-13 09:15:56 +08:00
|
|
|
count = qMin(count, screenWidth / SNAP_HEIGHT_WITHOUT_COMPOSITE);
|
2021-02-07 17:38:19 +08:00
|
|
|
const int h = SNAP_HEIGHT_WITHOUT_COMPOSITE * count + MARGIN * 2 + SPACING * (count - 1);
|
2017-07-31 17:06:10 +08:00
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
auto appSnapshot = static_cast<AppSnapshot *>(m_windowListLayout->itemAt(0)->widget());
|
|
|
|
auto font = appSnapshot->layout()->itemAt(0)->widget()->font();
|
|
|
|
QFontMetrics fontMetrics(font);
|
2022-01-20 14:47:12 +08:00
|
|
|
|
|
|
|
// 获取 appitem title 的最大宽度
|
|
|
|
int titleWidth = fontMetrics.boundingRect(appSnapshot->title()).width();
|
|
|
|
for (int i = 0; i < m_windowListLayout->count(); i++) {
|
|
|
|
auto otherWidget = static_cast<AppSnapshot *>(m_windowListLayout->itemAt(i)->widget());
|
|
|
|
titleWidth = qMax(titleWidth, fontMetrics.boundingRect(otherWidget->title()).width());
|
|
|
|
}
|
|
|
|
|
2021-02-07 17:38:19 +08:00
|
|
|
// 关闭按键的宽度和边缘间距的和,调整标题居中
|
|
|
|
const int closeBtnMargin = 2 * (SNAP_CLOSE_BTN_WIDTH + SNAP_CLOSE_BTN_MARGIN);
|
2022-01-20 14:47:12 +08:00
|
|
|
if (titleWidth < SNAP_WIDTH - closeBtnMargin)
|
2021-02-07 17:38:19 +08:00
|
|
|
setFixedSize(titleWidth + closeBtnMargin, h);
|
2022-01-20 14:47:12 +08:00
|
|
|
else
|
2021-02-07 17:38:19 +08:00
|
|
|
setFixedSize(SNAP_WIDTH, h);
|
2017-03-28 15:44:13 +08:00
|
|
|
}
|
2022-01-13 09:15:56 +08:00
|
|
|
|
|
|
|
//根据计算的数量,将相应的预览界面添加到布局并显示,其他的暂时不添加,减少界面刷新次数
|
|
|
|
int i = 0;
|
|
|
|
for (AppSnapshot *snap : m_snapshots) {
|
|
|
|
if (i < count && m_windowListLayout->indexOf(snap) < 0 ) {
|
|
|
|
m_windowListLayout->addWidget(snap);
|
|
|
|
}
|
|
|
|
snap->setVisible(i < count);
|
|
|
|
i++;
|
|
|
|
}
|
2017-07-31 17:06:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewContainer::appendSnapWidget(const WId wid)
|
|
|
|
{
|
2022-01-13 09:15:56 +08:00
|
|
|
//创建预览界面,默认不显示,等计算出显示数量后再加入布局并显示
|
2017-07-31 17:06:10 +08:00
|
|
|
AppSnapshot *snap = new AppSnapshot(wid);
|
2022-01-13 09:15:56 +08:00
|
|
|
snap->setVisible(false);
|
2017-07-31 17:06:10 +08:00
|
|
|
|
2019-04-12 17:17:19 +08:00
|
|
|
connect(snap, &AppSnapshot::clicked, this, &PreviewContainer::onSnapshotClicked, Qt::QueuedConnection);
|
2017-07-31 17:06:10 +08:00
|
|
|
connect(snap, &AppSnapshot::entered, this, &PreviewContainer::previewEntered, Qt::QueuedConnection);
|
2019-05-29 14:25:35 +08:00
|
|
|
connect(snap, &AppSnapshot::requestCheckWindow, this, &PreviewContainer::requestCheckWindows, Qt::QueuedConnection);
|
2021-08-25 21:03:30 +08:00
|
|
|
connect(snap, &AppSnapshot::requestCloseAppSnapshot, this, &PreviewContainer::onRequestCloseAppSnapshot);
|
2017-05-02 19:33:07 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
m_snapshots.insert(wid, snap);
|
2017-03-28 15:44:13 +08:00
|
|
|
}
|
|
|
|
|
2021-12-31 15:09:12 +08:00
|
|
|
void PreviewContainer::enterEvent(QEvent *e)
|
2021-11-05 21:29:32 +08:00
|
|
|
{
|
2021-12-31 15:09:12 +08:00
|
|
|
if (Utils::IS_WAYLAND_DISPLAY) {
|
|
|
|
Utils::updateCursor(this);
|
2021-11-05 21:29:32 +08:00
|
|
|
}
|
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
QWidget::enterEvent(e);
|
2017-05-10 10:44:47 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
m_needActivate = false;
|
|
|
|
m_mouseLeaveTimer->stop();
|
2019-06-19 16:38:48 +08:00
|
|
|
|
|
|
|
if (m_wmHelper->hasComposite()) {
|
|
|
|
m_waitForShowPreviewTimer->start();
|
|
|
|
}
|
2017-03-28 15:44:13 +08:00
|
|
|
}
|
2017-04-25 20:28:11 +08:00
|
|
|
|
|
|
|
void PreviewContainer::leaveEvent(QEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::leaveEvent(e);
|
|
|
|
|
2017-05-04 10:39:03 +08:00
|
|
|
m_mouseLeaveTimer->start();
|
2019-04-23 18:17:07 +08:00
|
|
|
m_waitForShowPreviewTimer->stop();
|
2017-05-04 10:39:03 +08:00
|
|
|
}
|
2017-04-25 20:28:11 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
void PreviewContainer::dragEnterEvent(QDragEnterEvent *e)
|
2017-05-04 10:39:03 +08:00
|
|
|
{
|
2018-01-12 15:25:28 +08:00
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
return;
|
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
e->accept();
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
m_needActivate = false;
|
2017-05-04 10:39:03 +08:00
|
|
|
m_mouseLeaveTimer->stop();
|
2017-04-25 20:28:11 +08:00
|
|
|
}
|
2017-05-02 19:33:07 +08:00
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
void PreviewContainer::dragLeaveEvent(QDragLeaveEvent *e)
|
2017-05-02 19:33:07 +08:00
|
|
|
{
|
2017-07-31 17:06:10 +08:00
|
|
|
e->ignore();
|
|
|
|
|
|
|
|
m_needActivate = true;
|
2019-04-12 17:56:04 +08:00
|
|
|
m_mouseLeaveTimer->start();
|
2017-05-02 19:33:07 +08:00
|
|
|
}
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2019-04-12 17:17:19 +08:00
|
|
|
void PreviewContainer::onSnapshotClicked(const WId wid)
|
|
|
|
{
|
2020-07-02 06:45:02 +06:00
|
|
|
Q_EMIT requestActivateWindow(wid);
|
2019-04-12 17:17:19 +08:00
|
|
|
m_needActivate = true;
|
2020-07-02 06:45:02 +06:00
|
|
|
m_waitForShowPreviewTimer->stop();
|
|
|
|
requestHidePopup();
|
2019-04-12 17:17:19 +08:00
|
|
|
}
|
|
|
|
|
2017-07-31 17:06:10 +08:00
|
|
|
void PreviewContainer::previewEntered(const WId wid)
|
|
|
|
{
|
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
return;
|
|
|
|
|
|
|
|
AppSnapshot *snap = static_cast<AppSnapshot *>(sender());
|
2018-08-02 19:54:26 +08:00
|
|
|
if (!snap) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
snap->setContentsMargins(100, 0, 100, 0);
|
|
|
|
|
|
|
|
AppSnapshot *preSnap = m_floatingPreview->trackedWindow();
|
|
|
|
if (preSnap && preSnap != snap) {
|
|
|
|
preSnap->setContentsMargins(0, 0, 0, 0);
|
2020-08-28 10:39:24 +08:00
|
|
|
preSnap->setWindowState();
|
2018-08-02 19:54:26 +08:00
|
|
|
}
|
2017-07-31 17:06:10 +08:00
|
|
|
|
2019-04-23 18:17:07 +08:00
|
|
|
m_currentWId = wid;
|
2017-07-31 17:06:10 +08:00
|
|
|
|
2019-04-23 18:17:07 +08:00
|
|
|
m_floatingPreview->trackWindow(snap);
|
2019-05-29 14:25:35 +08:00
|
|
|
|
|
|
|
if (m_waitForShowPreviewTimer->isActive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
previewFloating();
|
2017-07-31 17:06:10 +08:00
|
|
|
}
|
|
|
|
|
2019-04-23 18:17:07 +08:00
|
|
|
void PreviewContainer::previewFloating()
|
|
|
|
{
|
2021-02-07 17:38:19 +08:00
|
|
|
if (!m_waitForShowPreviewTimer->isActive()) {
|
2020-07-02 06:45:02 +06:00
|
|
|
m_floatingPreview->setVisible(true);
|
|
|
|
m_floatingPreview->raise();
|
2019-04-23 18:17:07 +08:00
|
|
|
|
2020-07-02 06:45:02 +06:00
|
|
|
requestPreviewWindow(m_currentWId);
|
|
|
|
}
|
|
|
|
return;
|
2019-04-23 18:17:07 +08:00
|
|
|
}
|
2021-08-25 21:03:30 +08:00
|
|
|
|
|
|
|
void PreviewContainer::onRequestCloseAppSnapshot()
|
|
|
|
{
|
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
return ;
|
|
|
|
|
2021-12-06 14:28:59 +08:00
|
|
|
if (m_snapshots.keys().isEmpty()) {
|
2021-08-25 21:03:30 +08:00
|
|
|
Q_EMIT requestHidePopup();
|
|
|
|
Q_EMIT requestCancelPreviewWindow();
|
|
|
|
}
|
|
|
|
}
|