2017-09-18 14:33:44 +08:00
|
|
|
/*
|
2018-02-07 11:52:47 +08:00
|
|
|
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
|
2017-09-18 14:33:44 +08:00
|
|
|
*
|
|
|
|
* Author: sbw <sbw@sbw.so>
|
|
|
|
*
|
|
|
|
* Maintainer: sbw <sbw@sbw.so>
|
2018-06-04 21:09:41 +08:00
|
|
|
* listenerri <listenerri@gmail.com>
|
2017-09-18 14:33:44 +08:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2016-06-03 16:06:11 +08:00
|
|
|
#include "appitem.h"
|
|
|
|
|
2016-06-14 16:01:01 +08:00
|
|
|
#include "util/themeappicon.h"
|
2016-06-27 20:16:35 +08:00
|
|
|
#include "util/imagefactory.h"
|
2016-07-22 14:59:43 +08:00
|
|
|
#include "xcb/xcb_misc.h"
|
2018-07-04 14:18:12 +08:00
|
|
|
#include "components/appswingeffectbuilder.h"
|
2018-07-10 15:21:10 +08:00
|
|
|
#include "components/appspreviewprovider.h"
|
2016-06-14 16:01:01 +08:00
|
|
|
|
2017-06-09 16:18:15 +08:00
|
|
|
#include <X11/X.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
2016-06-03 16:06:11 +08:00
|
|
|
#include <QPainter>
|
2016-06-07 14:40:45 +08:00
|
|
|
#include <QDrag>
|
|
|
|
#include <QMouseEvent>
|
2017-03-28 16:52:38 +08:00
|
|
|
#include <QApplication>
|
2017-04-26 17:59:35 +08:00
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QGraphicsScene>
|
|
|
|
#include <QTimeLine>
|
2018-02-22 11:44:57 +08:00
|
|
|
#include <QX11Info>
|
2016-06-03 16:06:11 +08:00
|
|
|
|
2016-06-07 14:40:45 +08:00
|
|
|
#define APP_DRAG_THRESHOLD 20
|
|
|
|
|
2016-06-21 17:24:03 +08:00
|
|
|
int AppItem::IconBaseSize;
|
2016-06-15 16:17:51 +08:00
|
|
|
QPoint AppItem::MousePressPos;
|
2016-06-06 14:57:07 +08:00
|
|
|
|
2016-06-03 16:06:11 +08:00
|
|
|
AppItem::AppItem(const QDBusObjectPath &entry, QWidget *parent)
|
2016-08-08 09:52:05 +08:00
|
|
|
: DockItem(parent),
|
2018-07-02 16:21:43 +08:00
|
|
|
m_appNameTips(new TipsWidget(this)),
|
2018-07-10 15:21:10 +08:00
|
|
|
m_appPreviewTips(nullptr),
|
2018-02-22 11:44:57 +08:00
|
|
|
m_itemEntryInter(new DockEntryInter("com.deepin.dde.daemon.Dock", entry.path(), QDBusConnection::sessionBus(), this)),
|
2017-04-26 17:59:35 +08:00
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
m_swingEffectView(nullptr),
|
|
|
|
m_itemAnimation(nullptr),
|
2017-04-26 17:59:35 +08:00
|
|
|
|
2018-06-04 21:09:41 +08:00
|
|
|
m_wmHelper(DWindowManagerHelper::instance()),
|
|
|
|
|
|
|
|
m_drag(nullptr),
|
|
|
|
|
2018-03-20 15:32:33 +08:00
|
|
|
m_dragging(false),
|
2017-06-16 09:00:53 +08:00
|
|
|
|
2018-08-30 12:03:25 +08:00
|
|
|
m_retryTimes(0),
|
|
|
|
|
2017-12-28 16:21:10 +08:00
|
|
|
m_appIcon(QPixmap()),
|
2017-06-16 09:00:53 +08:00
|
|
|
|
2016-07-12 16:33:01 +08:00
|
|
|
m_horizontalIndicator(QPixmap(":/indicator/resources/indicator.png")),
|
|
|
|
m_verticalIndicator(QPixmap(":/indicator/resources/indicator_ver.png")),
|
|
|
|
m_activeHorizontalIndicator(QPixmap(":/indicator/resources/indicator_active.png")),
|
2016-07-22 14:59:43 +08:00
|
|
|
m_activeVerticalIndicator(QPixmap(":/indicator/resources/indicator_active_ver.png")),
|
2017-06-16 15:26:20 +08:00
|
|
|
m_updateIconGeometryTimer(new QTimer(this)),
|
2018-08-30 12:03:25 +08:00
|
|
|
m_retryObtainIconTimer(new QTimer(this)),
|
2017-06-16 15:26:20 +08:00
|
|
|
|
|
|
|
m_smallWatcher(new QFutureWatcher<QPixmap>(this)),
|
|
|
|
m_largeWatcher(new QFutureWatcher<QPixmap>(this))
|
2016-06-03 16:06:11 +08:00
|
|
|
{
|
2017-04-26 17:59:35 +08:00
|
|
|
QHBoxLayout *centralLayout = new QHBoxLayout;
|
|
|
|
centralLayout->setMargin(0);
|
2017-05-02 16:32:38 +08:00
|
|
|
centralLayout->setSpacing(0);
|
2017-04-26 17:59:35 +08:00
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
setAccessibleName(m_itemEntryInter->name());
|
2016-06-23 14:45:57 +08:00
|
|
|
setAcceptDrops(true);
|
2017-04-26 17:59:35 +08:00
|
|
|
setLayout(centralLayout);
|
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
m_id = m_itemEntryInter->id();
|
|
|
|
m_active = m_itemEntryInter->isActive();
|
2016-06-06 14:28:28 +08:00
|
|
|
|
2018-07-02 16:21:43 +08:00
|
|
|
m_appNameTips->setObjectName("AppItemTips");
|
2018-02-22 11:44:57 +08:00
|
|
|
m_appNameTips->setAccessibleName(m_itemEntryInter->name() + "-tips");
|
2016-07-18 14:13:36 +08:00
|
|
|
m_appNameTips->setVisible(false);
|
2018-07-02 16:21:43 +08:00
|
|
|
m_appNameTips->installEventFilter(this);
|
2016-07-18 14:13:36 +08:00
|
|
|
|
2016-07-22 14:59:43 +08:00
|
|
|
m_updateIconGeometryTimer->setInterval(500);
|
|
|
|
m_updateIconGeometryTimer->setSingleShot(true);
|
|
|
|
|
2018-08-30 12:03:25 +08:00
|
|
|
m_retryObtainIconTimer->setInterval(500);
|
|
|
|
m_retryObtainIconTimer->setSingleShot(true);
|
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, &AppItem::activeChanged);
|
|
|
|
connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, static_cast<void (AppItem::*)()>(&AppItem::update));
|
|
|
|
connect(m_itemEntryInter, &DockEntryInter::WindowInfosChanged, this, &AppItem::updateWindowInfos, Qt::QueuedConnection);
|
|
|
|
connect(m_itemEntryInter, &DockEntryInter::IconChanged, this, &AppItem::refershIcon);
|
2016-06-14 16:01:01 +08:00
|
|
|
|
2017-05-02 10:49:27 +08:00
|
|
|
connect(m_updateIconGeometryTimer, &QTimer::timeout, this, &AppItem::updateWindowIconGeometries, Qt::QueuedConnection);
|
2018-08-30 12:03:25 +08:00
|
|
|
connect(m_retryObtainIconTimer, &QTimer::timeout, this, &AppItem::refershIcon, Qt::QueuedConnection);
|
2017-05-02 10:49:27 +08:00
|
|
|
|
2018-02-22 14:19:52 +08:00
|
|
|
updateWindowInfos(m_itemEntryInter->windowInfos());
|
2017-06-23 16:57:02 +08:00
|
|
|
refershIcon();
|
2016-06-14 11:22:19 +08:00
|
|
|
}
|
|
|
|
|
2017-04-12 15:31:36 +08:00
|
|
|
AppItem::~AppItem()
|
|
|
|
{
|
2018-03-19 11:33:16 +08:00
|
|
|
stopSwingEffect();
|
|
|
|
|
2017-04-12 15:31:36 +08:00
|
|
|
m_appNameTips->deleteLater();
|
|
|
|
}
|
|
|
|
|
2016-06-14 11:22:19 +08:00
|
|
|
const QString AppItem::appId() const
|
|
|
|
{
|
|
|
|
return m_id;
|
2016-06-03 16:06:11 +08:00
|
|
|
}
|
|
|
|
|
2018-12-25 14:52:32 +08:00
|
|
|
const bool AppItem::isValid() const
|
|
|
|
{
|
|
|
|
return m_itemEntryInter->isValid() && !m_itemEntryInter->id().isEmpty();
|
|
|
|
}
|
|
|
|
|
2016-07-22 14:59:43 +08:00
|
|
|
// Update _NET_WM_ICON_GEOMETRY property for windows that every item
|
|
|
|
// that manages, so that WM can do proper animations for specific
|
|
|
|
// window behaviors like minimization.
|
|
|
|
void AppItem::updateWindowIconGeometries()
|
|
|
|
{
|
2017-06-06 11:06:02 +08:00
|
|
|
const QRect r(mapToGlobal(QPoint(0, 0)),
|
|
|
|
mapToGlobal(QPoint(width(),height())));
|
|
|
|
auto *xcb_misc = XcbMisc::instance();
|
2016-07-22 14:59:43 +08:00
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
for (auto it(m_windowInfos.cbegin()); it != m_windowInfos.cend(); ++it)
|
2017-06-06 11:06:02 +08:00
|
|
|
xcb_misc->set_window_icon_geometry(it.key(), r);
|
2016-07-22 14:59:43 +08:00
|
|
|
}
|
|
|
|
|
2016-06-21 17:24:03 +08:00
|
|
|
void AppItem::setIconBaseSize(const int size)
|
|
|
|
{
|
|
|
|
IconBaseSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
int AppItem::iconBaseSize()
|
|
|
|
{
|
|
|
|
return IconBaseSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
int AppItem::itemBaseWidth()
|
|
|
|
{
|
2016-06-23 14:28:47 +08:00
|
|
|
if (DockDisplayMode == Dock::Fashion)
|
|
|
|
return itemBaseHeight() * 1.1;
|
|
|
|
else
|
|
|
|
return itemBaseHeight() * 1.4;
|
2016-06-21 17:24:03 +08:00
|
|
|
}
|
|
|
|
|
2018-06-04 21:09:41 +08:00
|
|
|
void AppItem::undock()
|
|
|
|
{
|
|
|
|
m_itemEntryInter->RequestUndock();
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *AppItem::appDragWidget()
|
|
|
|
{
|
2019-01-17 11:00:40 +08:00
|
|
|
if (m_drag) {
|
|
|
|
return m_drag->appDragWidget();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2018-06-04 21:09:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppItem::setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry)
|
|
|
|
{
|
2019-01-17 11:00:40 +08:00
|
|
|
if (m_drag) {
|
|
|
|
m_drag->appDragWidget()->setDockInfo(dockPosition, dockGeometry);
|
|
|
|
}
|
2018-06-04 21:09:41 +08:00
|
|
|
}
|
|
|
|
|
2017-06-08 16:19:12 +08:00
|
|
|
void AppItem::moveEvent(QMoveEvent *e)
|
|
|
|
{
|
|
|
|
DockItem::moveEvent(e);
|
|
|
|
|
2019-01-17 11:00:40 +08:00
|
|
|
if (m_drag) {
|
|
|
|
m_drag->appDragWidget()->setOriginPos(mapToGlobal(appIconPosition()));
|
|
|
|
}
|
|
|
|
|
2017-06-08 16:19:12 +08:00
|
|
|
m_updateIconGeometryTimer->start();
|
|
|
|
}
|
|
|
|
|
2016-06-21 17:24:03 +08:00
|
|
|
int AppItem::itemBaseHeight()
|
|
|
|
{
|
2016-07-11 17:17:32 +08:00
|
|
|
if (DockDisplayMode == Efficient)
|
|
|
|
return IconBaseSize * 1.2;
|
|
|
|
else
|
|
|
|
return IconBaseSize * 1.5;
|
2016-06-21 17:24:03 +08:00
|
|
|
}
|
|
|
|
|
2016-06-03 16:06:11 +08:00
|
|
|
void AppItem::paintEvent(QPaintEvent *e)
|
|
|
|
{
|
|
|
|
DockItem::paintEvent(e);
|
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
if (m_dragging || (m_swingEffectView != nullptr && DockDisplayMode != Fashion))
|
2016-06-07 16:01:37 +08:00
|
|
|
return;
|
|
|
|
|
2016-06-03 16:06:11 +08:00
|
|
|
QPainter painter(this);
|
2016-06-21 19:25:30 +08:00
|
|
|
if (!painter.isActive())
|
|
|
|
return;
|
2016-09-08 15:53:51 +08:00
|
|
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
2016-06-21 19:25:30 +08:00
|
|
|
|
2017-05-02 16:32:38 +08:00
|
|
|
const QRectF itemRect = rect();
|
2016-06-06 14:28:28 +08:00
|
|
|
|
2016-06-14 16:01:01 +08:00
|
|
|
// draw background
|
2017-05-02 16:32:38 +08:00
|
|
|
QRectF backgroundRect = itemRect;
|
2016-07-11 17:17:32 +08:00
|
|
|
|
2016-06-23 14:28:47 +08:00
|
|
|
if (DockDisplayMode == Efficient)
|
2016-06-23 10:50:26 +08:00
|
|
|
{
|
2018-02-27 15:25:15 +08:00
|
|
|
backgroundRect = itemRect.marginsRemoved(QMargins(1, 1, 1, 1));
|
|
|
|
|
2016-06-23 14:28:47 +08:00
|
|
|
if (m_active)
|
2016-06-23 10:50:26 +08:00
|
|
|
{
|
2016-07-11 17:17:32 +08:00
|
|
|
painter.fillRect(backgroundRect, QColor(44, 167, 248, 255 * 0.3));
|
2016-06-23 14:28:47 +08:00
|
|
|
|
2016-07-11 17:17:32 +08:00
|
|
|
const int activeLineWidth = itemRect.height() > 50 ? 4 : 2;
|
2017-05-02 16:32:38 +08:00
|
|
|
QRectF activeRect = backgroundRect;
|
2016-06-23 14:28:47 +08:00
|
|
|
switch (DockPosition)
|
|
|
|
{
|
|
|
|
case Top: activeRect.setBottom(activeRect.top() + activeLineWidth); break;
|
|
|
|
case Bottom: activeRect.setTop(activeRect.bottom() - activeLineWidth); break;
|
|
|
|
case Left: activeRect.setRight(activeRect.left() + activeLineWidth); break;
|
|
|
|
case Right: activeRect.setLeft(activeRect.right() - activeLineWidth); break;
|
|
|
|
}
|
|
|
|
|
2016-07-11 17:17:32 +08:00
|
|
|
painter.fillRect(activeRect, QColor(44, 167, 248, 255));
|
2016-06-23 14:28:47 +08:00
|
|
|
}
|
2018-02-22 11:44:57 +08:00
|
|
|
else if (!m_windowInfos.isEmpty())
|
2018-02-22 14:19:52 +08:00
|
|
|
{
|
|
|
|
if (hasAttention())
|
|
|
|
painter.fillRect(backgroundRect, QColor(241, 138, 46, 255 * .8));
|
|
|
|
else
|
|
|
|
painter.fillRect(backgroundRect, QColor(255, 255, 255, 255 * 0.2));
|
|
|
|
}
|
2016-06-23 14:28:47 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-02-22 11:44:57 +08:00
|
|
|
if (!m_windowInfos.isEmpty())
|
2016-06-23 14:28:47 +08:00
|
|
|
{
|
2016-07-12 16:33:01 +08:00
|
|
|
QPoint p;
|
|
|
|
QPixmap pixmap;
|
|
|
|
QPixmap activePixmap;
|
2016-06-23 14:28:47 +08:00
|
|
|
switch (DockPosition)
|
|
|
|
{
|
|
|
|
case Top:
|
2016-07-12 16:33:01 +08:00
|
|
|
pixmap = m_horizontalIndicator;
|
|
|
|
activePixmap = m_activeHorizontalIndicator;
|
|
|
|
p.setX((itemRect.width() - pixmap.width()) / 2);
|
|
|
|
p.setY(1);
|
2016-06-23 14:28:47 +08:00
|
|
|
break;
|
|
|
|
case Bottom:
|
2016-07-12 16:33:01 +08:00
|
|
|
pixmap = m_horizontalIndicator;
|
|
|
|
activePixmap = m_activeHorizontalIndicator;
|
|
|
|
p.setX((itemRect.width() - pixmap.width()) / 2);
|
|
|
|
p.setY(itemRect.height() - pixmap.height() - 1);
|
2016-06-23 14:28:47 +08:00
|
|
|
break;
|
|
|
|
case Left:
|
2016-07-12 16:33:01 +08:00
|
|
|
pixmap = m_verticalIndicator;
|
|
|
|
activePixmap = m_activeVerticalIndicator;
|
|
|
|
p.setX(1);
|
|
|
|
p.setY((itemRect.height() - pixmap.height()) / 2);
|
2016-06-23 14:28:47 +08:00
|
|
|
break;
|
|
|
|
case Right:
|
2016-07-12 16:33:01 +08:00
|
|
|
pixmap = m_verticalIndicator;
|
|
|
|
activePixmap = m_activeVerticalIndicator;
|
|
|
|
p.setX(itemRect.width() - pixmap.width() - 1);
|
|
|
|
p.setY((itemRect.height() - pixmap.height()) / 2);
|
2016-06-23 14:28:47 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-07-12 16:33:01 +08:00
|
|
|
if (m_active)
|
|
|
|
painter.drawPixmap(p, activePixmap);
|
|
|
|
else
|
|
|
|
painter.drawPixmap(p, pixmap);
|
2016-06-23 10:50:26 +08:00
|
|
|
}
|
|
|
|
}
|
2016-06-06 14:28:28 +08:00
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
if (m_swingEffectView != nullptr)
|
2018-02-27 15:25:15 +08:00
|
|
|
return;
|
|
|
|
|
2016-06-27 20:16:35 +08:00
|
|
|
// icon
|
2019-01-17 11:00:40 +08:00
|
|
|
if (m_appIcon.isNull())
|
2017-06-16 09:00:53 +08:00
|
|
|
return;
|
|
|
|
|
2019-01-17 11:00:40 +08:00
|
|
|
painter.drawPixmap(appIconPosition(), m_appIcon);
|
2016-06-03 16:06:11 +08:00
|
|
|
}
|
2016-06-06 14:28:28 +08:00
|
|
|
|
|
|
|
void AppItem::mouseReleaseEvent(QMouseEvent *e)
|
|
|
|
{
|
2017-02-15 16:34:30 +08:00
|
|
|
if (e->button() == Qt::MiddleButton) {
|
2018-02-22 11:44:57 +08:00
|
|
|
m_itemEntryInter->NewInstance(QX11Info::getTimestamp());
|
2018-11-30 14:57:11 +08:00
|
|
|
|
|
|
|
// play launch effect
|
|
|
|
if (m_windowInfos.isEmpty())
|
|
|
|
playSwingEffect();
|
|
|
|
|
2017-02-15 16:34:30 +08:00
|
|
|
} else if (e->button() == Qt::LeftButton) {
|
2018-11-30 17:47:08 +08:00
|
|
|
if (checkAndResetTapHoldGestureState() && e->source() == Qt::MouseEventSynthesizedByQt) {
|
2018-11-13 16:01:36 +08:00
|
|
|
qDebug() << "tap and hold gesture detected, ignore the synthesized mouse release event";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-31 16:06:34 +08:00
|
|
|
qDebug() << "app item clicked, name:" << m_itemEntryInter->name()
|
|
|
|
<< "id:" << m_itemEntryInter->id() << "my-id:" << m_id << "icon:" << m_itemEntryInter->icon();
|
2017-04-26 17:59:35 +08:00
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
m_itemEntryInter->Activate(QX11Info::getTimestamp());
|
2016-09-08 15:53:51 +08:00
|
|
|
|
2018-02-27 15:25:15 +08:00
|
|
|
// play launch effect
|
|
|
|
if (m_windowInfos.isEmpty())
|
|
|
|
playSwingEffect();
|
2017-02-15 16:34:30 +08:00
|
|
|
}
|
2016-06-07 14:40:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppItem::mousePressEvent(QMouseEvent *e)
|
|
|
|
{
|
2016-08-09 10:58:47 +08:00
|
|
|
m_updateIconGeometryTimer->stop();
|
2017-05-18 15:41:17 +08:00
|
|
|
hidePopup();
|
2016-08-09 10:58:47 +08:00
|
|
|
|
2016-06-15 16:17:51 +08:00
|
|
|
if (e->button() == Qt::LeftButton)
|
|
|
|
MousePressPos = e->pos();
|
2018-12-17 14:38:09 +08:00
|
|
|
|
|
|
|
// context menu will handle in DockItem
|
|
|
|
DockItem::mousePressEvent(e);
|
2016-06-07 14:40:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppItem::mouseMoveEvent(QMouseEvent *e)
|
|
|
|
{
|
2016-06-14 15:17:25 +08:00
|
|
|
e->accept();
|
|
|
|
|
2017-05-02 16:57:58 +08:00
|
|
|
// handle preview
|
2017-05-04 10:39:03 +08:00
|
|
|
// if (e->buttons() == Qt::NoButton)
|
|
|
|
// return showPreview();
|
2017-05-02 16:57:58 +08:00
|
|
|
|
2016-06-07 14:40:45 +08:00
|
|
|
// handle drag
|
|
|
|
if (e->buttons() != Qt::LeftButton)
|
|
|
|
return;
|
|
|
|
|
2017-04-27 15:34:04 +08:00
|
|
|
const QPoint pos = e->pos();
|
|
|
|
if (!rect().contains(pos))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const QPoint distance = pos - MousePressPos;
|
2017-05-02 16:57:58 +08:00
|
|
|
if (distance.manhattanLength() > APP_DRAG_THRESHOLD)
|
|
|
|
return startDrag();
|
2016-06-07 14:40:45 +08:00
|
|
|
}
|
|
|
|
|
2016-08-30 16:34:02 +08:00
|
|
|
void AppItem::wheelEvent(QWheelEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::wheelEvent(e);
|
|
|
|
|
2018-12-17 10:04:15 +08:00
|
|
|
if (qAbs(e->angleDelta().y()) > 20) {
|
|
|
|
m_itemEntryInter->PresentWindows();
|
|
|
|
}
|
2016-08-30 16:34:02 +08:00
|
|
|
}
|
|
|
|
|
2016-06-15 11:20:05 +08:00
|
|
|
void AppItem::resizeEvent(QResizeEvent *e)
|
|
|
|
{
|
|
|
|
DockItem::resizeEvent(e);
|
|
|
|
|
2017-03-13 08:02:33 +08:00
|
|
|
refershIcon();
|
2016-06-15 11:20:05 +08:00
|
|
|
}
|
|
|
|
|
2016-06-23 14:45:57 +08:00
|
|
|
void AppItem::dragEnterEvent(QDragEnterEvent *e)
|
|
|
|
{
|
2016-06-23 15:30:06 +08:00
|
|
|
// ignore drag from panel
|
2018-11-05 11:26:20 +08:00
|
|
|
if (e->source()) {
|
|
|
|
return e->ignore();
|
|
|
|
}
|
2016-06-23 15:30:06 +08:00
|
|
|
|
2016-07-18 17:10:15 +08:00
|
|
|
// ignore request dock event
|
2018-08-22 12:52:47 +08:00
|
|
|
QString draggingMimeKey = e->mimeData()->formats().contains("RequestDock") ? "RequestDock" : "text/plain";
|
|
|
|
if (QMimeDatabase().mimeTypeForFile(e->mimeData()->data(draggingMimeKey)).name() == "application/x-desktop") {
|
2018-11-05 11:26:20 +08:00
|
|
|
return e->ignore();
|
2018-08-22 12:52:47 +08:00
|
|
|
}
|
2016-07-18 17:10:15 +08:00
|
|
|
|
2016-06-23 15:30:06 +08:00
|
|
|
e->accept();
|
|
|
|
}
|
|
|
|
|
2017-04-25 20:28:11 +08:00
|
|
|
void AppItem::dragMoveEvent(QDragMoveEvent *e)
|
|
|
|
{
|
|
|
|
DockItem::dragMoveEvent(e);
|
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
if (m_windowInfos.isEmpty())
|
2017-04-25 20:28:11 +08:00
|
|
|
return;
|
|
|
|
|
2018-07-10 15:21:10 +08:00
|
|
|
if (!PopupWindow->isVisible() || !m_appPreviewTips)
|
2017-04-25 20:28:11 +08:00
|
|
|
showPreview();
|
|
|
|
}
|
|
|
|
|
2016-06-23 15:30:06 +08:00
|
|
|
void AppItem::dropEvent(QDropEvent *e)
|
|
|
|
{
|
|
|
|
QStringList uriList;
|
2017-02-27 15:04:49 +08:00
|
|
|
for (auto uri : e->mimeData()->urls()) {
|
|
|
|
uriList << uri.toEncoded();
|
|
|
|
}
|
2016-06-23 15:30:06 +08:00
|
|
|
|
2017-02-27 15:04:49 +08:00
|
|
|
qDebug() << "accept drop event with URIs: " << uriList;
|
2018-02-22 11:44:57 +08:00
|
|
|
m_itemEntryInter->HandleDragDrop(QX11Info::getTimestamp(), uriList);
|
2016-06-23 14:45:57 +08:00
|
|
|
}
|
|
|
|
|
2017-08-18 13:13:56 +08:00
|
|
|
void AppItem::leaveEvent(QEvent *e)
|
|
|
|
{
|
|
|
|
DockItem::leaveEvent(e);
|
|
|
|
|
2018-07-10 15:21:10 +08:00
|
|
|
if (m_appPreviewTips) {
|
|
|
|
if (m_appPreviewTips->isVisible()) {
|
|
|
|
m_appPreviewTips->prepareHide();
|
|
|
|
}
|
|
|
|
}
|
2017-08-18 13:13:56 +08:00
|
|
|
}
|
|
|
|
|
2018-07-03 12:33:31 +08:00
|
|
|
void AppItem::showEvent(QShowEvent *e)
|
|
|
|
{
|
|
|
|
DockItem::showEvent(e);
|
|
|
|
|
|
|
|
refershIcon();
|
|
|
|
}
|
|
|
|
|
2017-05-04 10:39:03 +08:00
|
|
|
void AppItem::showHoverTips()
|
|
|
|
{
|
2018-02-22 11:44:57 +08:00
|
|
|
if (!m_windowInfos.isEmpty())
|
2017-05-04 10:39:03 +08:00
|
|
|
return showPreview();
|
|
|
|
|
|
|
|
DockItem::showHoverTips();
|
|
|
|
}
|
|
|
|
|
2016-06-15 16:17:51 +08:00
|
|
|
void AppItem::invokedMenuItem(const QString &itemId, const bool checked)
|
|
|
|
{
|
2016-06-21 10:12:43 +08:00
|
|
|
Q_UNUSED(checked);
|
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
m_itemEntryInter->HandleMenuItem(QX11Info::getTimestamp(), itemId);
|
2016-06-15 16:17:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const QString AppItem::contextMenu() const
|
|
|
|
{
|
2018-02-22 11:44:57 +08:00
|
|
|
return m_itemEntryInter->menu();
|
2016-06-15 16:17:51 +08:00
|
|
|
}
|
|
|
|
|
2016-07-18 14:13:36 +08:00
|
|
|
QWidget *AppItem::popupTips()
|
|
|
|
{
|
2018-03-20 15:32:33 +08:00
|
|
|
if (m_dragging)
|
2016-07-18 17:10:15 +08:00
|
|
|
return nullptr;
|
2016-07-18 14:13:36 +08:00
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
if (!m_windowInfos.isEmpty())
|
2016-07-19 15:11:28 +08:00
|
|
|
{
|
2018-02-22 11:44:57 +08:00
|
|
|
const quint32 currentWindow = m_itemEntryInter->currentWindow();
|
|
|
|
Q_ASSERT(m_windowInfos.contains(currentWindow));
|
2018-02-22 14:19:52 +08:00
|
|
|
m_appNameTips->setText(m_windowInfos[currentWindow].title);
|
2016-07-19 15:11:28 +08:00
|
|
|
} else {
|
2018-02-22 11:44:57 +08:00
|
|
|
m_appNameTips->setText(m_itemEntryInter->name());
|
2016-07-19 15:11:28 +08:00
|
|
|
}
|
2016-07-18 14:13:36 +08:00
|
|
|
|
|
|
|
return m_appNameTips;
|
|
|
|
}
|
|
|
|
|
2016-06-07 14:40:45 +08:00
|
|
|
void AppItem::startDrag()
|
|
|
|
{
|
2018-03-20 15:32:33 +08:00
|
|
|
m_dragging = true;
|
2016-06-07 16:01:37 +08:00
|
|
|
update();
|
|
|
|
|
2017-12-28 16:21:10 +08:00
|
|
|
const QPixmap &dragPix = m_appIcon;
|
2016-08-09 16:50:48 +08:00
|
|
|
|
2018-06-04 21:09:41 +08:00
|
|
|
m_drag = new AppDrag(this);
|
|
|
|
m_drag->setMimeData(new QMimeData);
|
|
|
|
|
2019-01-17 11:00:40 +08:00
|
|
|
// handle drag finished here
|
|
|
|
connect(m_drag->appDragWidget(), &AppDragWidget::destroyed, this, [=] {
|
|
|
|
m_dragging = false;
|
2019-07-15 15:30:06 +08:00
|
|
|
m_drag.clear();
|
2019-01-17 11:00:40 +08:00
|
|
|
setVisible(true);
|
|
|
|
update();
|
|
|
|
});
|
|
|
|
|
2018-06-04 21:09:41 +08:00
|
|
|
if (m_wmHelper->hasComposite()) {
|
|
|
|
m_drag->setPixmap(dragPix);
|
2019-01-17 11:00:40 +08:00
|
|
|
m_drag->appDragWidget()->setOriginPos(mapToGlobal(appIconPosition()));
|
2018-06-04 21:09:41 +08:00
|
|
|
emit dragStarted();
|
|
|
|
m_drag->exec(Qt::MoveAction);
|
|
|
|
} else {
|
|
|
|
m_drag->QDrag::setPixmap(dragPix);
|
|
|
|
m_drag->setHotSpot(dragPix.rect().center() / dragPix.devicePixelRatioF());
|
|
|
|
emit dragStarted();
|
|
|
|
m_drag->QDrag::exec(Qt::MoveAction);
|
|
|
|
}
|
2016-06-07 14:40:45 +08:00
|
|
|
|
2018-06-04 21:09:41 +08:00
|
|
|
// MainPanel will put this item to Item-Container when received this signal(MainPanel::itemDropped)
|
|
|
|
//emit itemDropped(m_drag->target());
|
2016-06-20 16:46:53 +08:00
|
|
|
|
2018-06-04 21:09:41 +08:00
|
|
|
if (!m_wmHelper->hasComposite()) {
|
|
|
|
if (!m_drag->target()) {
|
|
|
|
m_itemEntryInter->RequestUndock();
|
|
|
|
}
|
|
|
|
}
|
2016-06-06 14:28:28 +08:00
|
|
|
}
|
|
|
|
|
2018-02-22 14:19:52 +08:00
|
|
|
bool AppItem::hasAttention() const
|
|
|
|
{
|
|
|
|
for (const auto &info : m_windowInfos)
|
|
|
|
if (info.attention)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-17 11:00:40 +08:00
|
|
|
QPoint AppItem::appIconPosition() const
|
|
|
|
{
|
2019-04-23 14:28:09 +08:00
|
|
|
const auto ratio = devicePixelRatioF();
|
2019-01-17 11:00:40 +08:00
|
|
|
const QRectF itemRect = rect();
|
|
|
|
const QRectF iconRect = m_appIcon.rect();
|
|
|
|
const qreal iconX = itemRect.center().x() - iconRect.center().x() / ratio;
|
|
|
|
const qreal iconY = itemRect.center().y() - iconRect.center().y() / ratio;
|
|
|
|
|
|
|
|
return QPoint(iconX, iconY);
|
|
|
|
}
|
|
|
|
|
2018-02-22 14:19:52 +08:00
|
|
|
void AppItem::updateWindowInfos(const WindowInfoMap &info)
|
2016-06-06 14:28:28 +08:00
|
|
|
{
|
2018-02-22 14:19:52 +08:00
|
|
|
m_windowInfos = info;
|
2018-08-13 14:17:45 +08:00
|
|
|
if (m_appPreviewTips) m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value());
|
2017-06-06 11:06:02 +08:00
|
|
|
m_updateIconGeometryTimer->start();
|
2017-04-25 20:28:11 +08:00
|
|
|
|
2018-02-27 15:25:15 +08:00
|
|
|
// process attention effect
|
|
|
|
if (hasAttention())
|
|
|
|
{
|
|
|
|
if (DockDisplayMode == DisplayMode::Fashion)
|
|
|
|
playSwingEffect();
|
|
|
|
} else {
|
2018-03-19 11:33:16 +08:00
|
|
|
stopSwingEffect();
|
2018-02-27 15:25:15 +08:00
|
|
|
}
|
|
|
|
|
2016-06-14 15:01:27 +08:00
|
|
|
update();
|
2016-06-06 14:28:28 +08:00
|
|
|
}
|
2016-06-14 16:01:01 +08:00
|
|
|
|
2017-03-13 08:02:33 +08:00
|
|
|
void AppItem::refershIcon()
|
2016-06-14 16:01:01 +08:00
|
|
|
{
|
2018-07-03 12:33:31 +08:00
|
|
|
if (!isVisible())
|
|
|
|
return;
|
|
|
|
|
2018-02-22 11:44:57 +08:00
|
|
|
const QString icon = m_itemEntryInter->icon();
|
2016-06-23 14:28:47 +08:00
|
|
|
const int iconSize = qMin(width(), height());
|
|
|
|
|
2016-07-11 17:17:32 +08:00
|
|
|
if (DockDisplayMode == Efficient)
|
2019-04-23 14:28:09 +08:00
|
|
|
m_appIcon = ThemeAppIcon::getIcon(icon, iconSize * 0.7, devicePixelRatioF());
|
2017-12-28 16:21:10 +08:00
|
|
|
else
|
2019-04-23 14:28:09 +08:00
|
|
|
m_appIcon = ThemeAppIcon::getIcon(icon, iconSize * 0.8, devicePixelRatioF());
|
2017-03-13 08:02:33 +08:00
|
|
|
|
2018-08-30 12:03:25 +08:00
|
|
|
if (m_appIcon.isNull()) {
|
|
|
|
if (m_retryTimes < 5) {
|
|
|
|
m_retryTimes++;
|
2018-08-31 16:06:34 +08:00
|
|
|
qDebug() << m_itemEntryInter->name() << "obtain app icon(" << icon << ")failed, retry times:" << m_retryTimes;
|
2018-08-30 12:03:25 +08:00
|
|
|
m_retryObtainIconTimer->start();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} else if (m_retryTimes > 0) {
|
|
|
|
// reset times
|
|
|
|
m_retryTimes = 0;
|
|
|
|
}
|
|
|
|
|
2017-06-23 16:57:02 +08:00
|
|
|
update();
|
|
|
|
|
2017-06-06 11:06:02 +08:00
|
|
|
m_updateIconGeometryTimer->start();
|
2016-06-23 14:28:47 +08:00
|
|
|
}
|
2016-06-14 16:01:01 +08:00
|
|
|
|
2016-06-23 14:28:47 +08:00
|
|
|
void AppItem::activeChanged()
|
|
|
|
{
|
|
|
|
m_active = !m_active;
|
2016-06-14 16:01:01 +08:00
|
|
|
}
|
2017-03-28 15:44:13 +08:00
|
|
|
|
2017-04-25 16:36:58 +08:00
|
|
|
void AppItem::showPreview()
|
2017-03-28 15:44:13 +08:00
|
|
|
{
|
2018-02-22 11:44:57 +08:00
|
|
|
if (m_windowInfos.isEmpty())
|
2017-05-02 16:57:58 +08:00
|
|
|
return;
|
|
|
|
|
2018-08-13 14:17:45 +08:00
|
|
|
m_appPreviewTips = PreviewWindow(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value(), DockPosition);
|
2017-05-04 10:39:03 +08:00
|
|
|
|
2018-07-10 15:21:10 +08:00
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, this, &AppItem::requestActivateWindow, Qt::QueuedConnection);
|
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestPreviewWindow, this, &AppItem::requestPreviewWindow, Qt::QueuedConnection);
|
2019-04-12 17:17:19 +08:00
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestCancelPreviewWindow, this, &AppItem::requestCancelPreview);
|
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestHidePopup, this, &AppItem::hidePopup);
|
2018-07-10 15:21:10 +08:00
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestCheckWindows, m_itemEntryInter, &DockEntryInter::Check);
|
2017-03-28 16:52:38 +08:00
|
|
|
|
2018-07-30 15:09:36 +08:00
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, [=]() { m_appPreviewTips = nullptr; });
|
2019-04-12 17:17:19 +08:00
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestCancelPreviewWindow, [=]() { m_appPreviewTips = nullptr; });
|
|
|
|
connect(m_appPreviewTips, &PreviewContainer::requestHidePopup, [=]() { m_appPreviewTips = nullptr; });
|
2018-07-30 15:09:36 +08:00
|
|
|
|
2018-02-22 17:19:55 +08:00
|
|
|
showPopupWindow(m_appPreviewTips, true);
|
2017-03-28 15:44:13 +08:00
|
|
|
}
|
2017-06-15 16:41:40 +08:00
|
|
|
|
2018-02-27 15:25:15 +08:00
|
|
|
void AppItem::playSwingEffect()
|
|
|
|
{
|
2018-03-19 14:25:46 +08:00
|
|
|
// NOTE(sbw): return if animation view already playing
|
2018-07-04 14:18:12 +08:00
|
|
|
if (m_swingEffectView != nullptr)
|
2018-03-19 14:25:46 +08:00
|
|
|
return;
|
|
|
|
|
2018-03-19 11:33:16 +08:00
|
|
|
stopSwingEffect();
|
2018-03-14 11:24:57 +08:00
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
QPair<QGraphicsView *, QGraphicsItemAnimation *> pair = SwingEffect(
|
2019-04-23 14:28:09 +08:00
|
|
|
this, m_appIcon, rect(), devicePixelRatioF());
|
2018-03-09 14:59:33 +08:00
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
m_swingEffectView = pair.first;
|
|
|
|
m_itemAnimation = pair.second;
|
2018-02-27 15:25:15 +08:00
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
QTimeLine *tl = m_itemAnimation->timeLine();
|
|
|
|
connect(tl, &QTimeLine::stateChanged, [=](QTimeLine::State newState) {
|
|
|
|
if (newState == QTimeLine::NotRunning) {
|
|
|
|
m_swingEffectView->hide();
|
|
|
|
layout()->removeWidget(m_swingEffectView);
|
|
|
|
m_swingEffectView = nullptr;
|
|
|
|
m_itemAnimation = nullptr;
|
|
|
|
checkAttentionEffect();
|
|
|
|
}
|
|
|
|
});
|
2018-02-27 15:25:15 +08:00
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
layout()->addWidget(m_swingEffectView);
|
2018-03-02 11:59:03 +08:00
|
|
|
tl->start();
|
2018-02-27 15:25:15 +08:00
|
|
|
}
|
|
|
|
|
2018-03-19 11:33:16 +08:00
|
|
|
void AppItem::stopSwingEffect()
|
|
|
|
{
|
2018-07-04 14:18:12 +08:00
|
|
|
if (m_swingEffectView == nullptr || m_itemAnimation == nullptr)
|
|
|
|
return;
|
|
|
|
|
2018-03-19 11:33:16 +08:00
|
|
|
// stop swing effect
|
|
|
|
m_swingEffectView->setVisible(false);
|
|
|
|
|
2018-07-04 14:18:12 +08:00
|
|
|
if (m_itemAnimation->timeLine() && m_itemAnimation->timeLine()->state() != QTimeLine::NotRunning)
|
|
|
|
m_itemAnimation->timeLine()->stop();
|
2018-03-19 11:33:16 +08:00
|
|
|
}
|
|
|
|
|
2018-02-27 15:25:15 +08:00
|
|
|
void AppItem::checkAttentionEffect()
|
|
|
|
{
|
|
|
|
QTimer::singleShot(1000, this, [=] {
|
|
|
|
if (DockDisplayMode == DisplayMode::Fashion && hasAttention())
|
|
|
|
playSwingEffect();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|