feat: Optimize animation code structure

优化任务栏初始化时显示与隐藏动画的执行逻辑。

Log: 优化任务栏初始化时显示与隐藏动画的执行逻辑。
Change-Id: If82eba947ae429d3de8b208d32bd31c24c88fd34
Reviewed-on: http://gerrit.uniontech.com/c/dde-dock/+/6852
Reviewed-by: fanpengcheng <fanpengcheng@uniontech.com>
Tested-by: fanpengcheng <fanpengcheng@uniontech.com>
This commit is contained in:
Zhang Qipeng 2020-09-29 17:22:23 +08:00 committed by fanpengcheng
parent 7f9aa7d6e1
commit 240cf938ae
2 changed files with 166 additions and 155 deletions

View File

@ -52,9 +52,9 @@ MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *help
, m_monitorUpdateTimer(new QTimer(this))
, m_delayTimer(new QTimer(this))
, m_monitorSetting(nullptr)
, m_showAni(new QVariantAnimation(this))
, m_hideAni(new QVariantAnimation(this))
, m_ds(m_displayInter->primary())
, m_showAniStart(false)
, m_hideAniStart(false)
, m_aniStart(false)
, m_draging(false)
, m_autoHide(true)
@ -86,7 +86,7 @@ void MultiScreenWorker::initShow()
emit requestUpdateLayout();
if (m_hideMode == HideMode::KeepShowing)
showAni(m_ds.current());
displayAnimation(m_ds.current(), AniAction::Show);
else if (m_hideMode == HideMode::KeepHidden) {
QRect rect = getDockShowGeometry(m_ds.current(), m_position, m_displayMode);
parent()->panel()->setFixedSize(rect.size());
@ -97,9 +97,9 @@ void MultiScreenWorker::initShow()
parent()->setGeometry(rect);
} else if (m_hideMode == HideMode::SmartHide) {
if (m_hideState == HideState::Show)
showAni(m_ds.current());
displayAnimation(m_ds.current(), AniAction::Show);
else if (m_hideState == HideState::Hide)
hideAni(m_ds.current());
displayAnimation(m_ds.current(), AniAction::Hide);
}
}
@ -126,28 +126,34 @@ QRect MultiScreenWorker::dockRectWithoutScale(const QString &screenName, const P
void MultiScreenWorker::onAutoHideChanged(bool autoHide)
{
m_autoHide = autoHide;
if (m_autoHide != autoHide) {
m_autoHide = autoHide;
}
if (m_autoHide) {
switch (m_hideMode) {
case HideMode::KeepHidden: {
// 这时候鼠标如果在任务栏上,就不能隐藏
if (!parent()->geometry().contains(QCursor::pos()))
hideAni(m_ds.current());
}
break;
case HideMode::SmartHide: {
if (m_hideState == HideState::Show) {
showAni(m_ds.current());
} else if (m_hideState == HideState::Hide) {
hideAni(m_ds.current());
/**
* DBus服务去修改m_hideMode的值
* KeepHidden
* 500ms任务栏才执行动画
*/
QTimer::singleShot(500, [=] {
switch (m_hideMode) {
case HideMode::KeepHidden: {
// 这时候鼠标如果在任务栏上,就不能隐藏
if (!parent()->geometry().contains(QCursor::pos()))
displayAnimation(m_ds.current(), AniAction::Hide);
} break;
case HideMode::SmartHide: {
if (m_hideState == HideState::Show) {
displayAnimation(m_ds.current(), AniAction::Show);
} else if (m_hideState == HideState::Hide) {
displayAnimation(m_ds.current(), AniAction::Hide);
}
} break;
case HideMode::KeepShowing:
displayAnimation(m_ds.current(), AniAction::Show);
break;
}
}
break;
case HideMode::KeepShowing:
showAni(m_ds.current());
break;
}
});
}
}
@ -195,15 +201,9 @@ void MultiScreenWorker::handleDbusSignal(QDBusMessage msg)
void MultiScreenWorker::onRegionMonitorChanged(int x, int y, const QString &key)
{
if (m_registerKey != key)
if (m_registerKey != key || m_btnPress)
return;
// 鼠标按下状态不响应唤醒
if (m_btnPress) {
qDebug() << "mouse pressed, should return";
return;
}
tryToShowDock(x, y);
}
@ -215,14 +215,16 @@ void MultiScreenWorker::onExtralRegionMonitorChanged(int x, int y, const QString
if (m_extralRegisterKey != key)
return;
// 鼠标移动到任务栏界面之外,不再唤起
// 鼠标移动到任务栏界面之外,停止计时器延时2秒改变任务栏所在屏幕
m_delayTimer->stop();
if (m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) {
if (!m_launcherInter->IsVisible() && m_autoHide && !m_draging && !m_aniStart) {
if (m_hideMode == HideMode::KeepHidden || (m_hideMode == HideMode::SmartHide && m_hideState == HideState::Hide))
hideAni(m_ds.current());
}
if (m_hideMode == HideMode::KeepShowing
|| ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) {
displayAnimation(m_ds.current(), AniAction::Show);
} else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) {
displayAnimation(m_ds.current(), AniAction::Hide);
} else {
Q_UNREACHABLE();
}
}
@ -385,6 +387,9 @@ void MultiScreenWorker::updateParentGeometry(const QVariant &value, const Positi
void MultiScreenWorker::updateParentGeometry(const QVariant &value)
{
if (!m_showAniStart && !m_hideAniStart)
return;
updateParentGeometry(value, m_position);
}
@ -413,7 +418,7 @@ void MultiScreenWorker::onPositionChanged()
if (m_hideMode == HideMode::KeepHidden || (m_hideMode == HideMode::SmartHide && m_hideState == HideState::Hide)) {
// 这种情况切换位置,任务栏不需要显示
hideAni(m_ds.current(), lastPos, m_displayMode);
displayAnimation(m_ds.current(), lastPos, AniAction::Hide);
// 更新当前屏幕信息,下次显示从目标屏幕显示
m_ds.updateDockedScreen(getValidScreen(m_position));
// 需要更新frontendWindowRect接口数据否则会造成HideState属性值不变
@ -472,8 +477,16 @@ void MultiScreenWorker::onHideModeChanged()
m_hideMode = hideMode;
emit requestUpdateFrontendGeometry();
if (m_hideMode == HideMode::KeepShowing
|| ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) {
displayAnimation(m_ds.current(), AniAction::Show);
} else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) {
displayAnimation(m_ds.current(), AniAction::Hide);
} else {
Q_UNREACHABLE();
}
emit requestUpdateFrontendGeometry();
emit requestNotifyWindowManager();
}
@ -484,8 +497,6 @@ void MultiScreenWorker::onHideStateChanged()
if (state == Dock::Unknown)
return;
qDebug() << "hidestate change:" << state;
m_hideState = state;
// 检查当前屏幕的当前位置是否允许显示,不允许需要更新显示信息(这里应该在函数外部就处理好,不应该走到这里)
@ -500,14 +511,15 @@ void MultiScreenWorker::onHideStateChanged()
m_ds.updateDockedScreen(getValidScreen(m_position));
}
// 两种隐藏模式下都可以被唤醒
if (m_hideMode == HideMode::SmartHide || m_hideMode == HideMode::KeepHidden) {
if (m_hideState == HideState::Show)
showAni(m_ds.current());
else if (m_hideState == HideState::Hide)
hideAni(m_ds.current());
} else if (m_hideMode == HideMode::KeepShowing) {
showAni(m_ds.current());
qDebug() << "hidestate change:" << m_hideMode << m_hideState;
if (m_hideMode == HideMode::KeepShowing
|| ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) {
displayAnimation(m_ds.current(), AniAction::Show);
} else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) {
displayAnimation(m_ds.current(), AniAction::Hide);
} else {
Q_UNREACHABLE();
}
}
@ -881,7 +893,7 @@ void MultiScreenWorker::onRequestDelayShowDock(const QString &screenName)
// 检查边缘是否允许停靠
if (currentMonitor->dockPosition().docked(m_position)) {
if (m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) {
showAni(m_ds.current());
displayAnimation(m_ds.current(), AniAction::Show);
} else if (m_hideMode == HideMode::KeepShowing) {
changeDockPosition(m_ds.last(), m_ds.current(), m_position, m_position);
}
@ -899,21 +911,6 @@ void MultiScreenWorker::initMembers()
// 设置应用角色为任务栏
XcbMisc::instance()->set_window_type(xcb_window_t(parent()->winId()), XcbMisc::Dock);
// 初始化动画信息
m_showAni->setEasingCurve(QEasingCurve::InOutCubic);
m_hideAni->setEasingCurve(QEasingCurve::InOutCubic);
const bool composite = m_wmHelper->hasComposite();
#ifndef DISABLE_SHOW_ANIMATION
const int duration = composite ? ANIMATIONTIME : 0;
#else
const int duration = 0;
#endif
m_showAni->setDuration(duration);
m_hideAni->setDuration(duration);
// init check
checkDaemonDockService();
checkDaemonDisplayService();
@ -942,24 +939,6 @@ void MultiScreenWorker::initGSettingConfig()
void MultiScreenWorker::initConnection()
{
connect(m_showAni, &QVariantAnimation::valueChanged, this, static_cast<void (MultiScreenWorker::*)(const QVariant &value)>(&MultiScreenWorker::updateParentGeometry));
connect(m_hideAni, &QVariantAnimation::valueChanged, this, static_cast<void (MultiScreenWorker::*)(const QVariant &value)>(&MultiScreenWorker::updateParentGeometry));
connect(m_showAni, &QVariantAnimation::finished, this, &MultiScreenWorker::showAniFinished);
connect(m_hideAni, &QVariantAnimation::finished, this, &MultiScreenWorker::hideAniFinished);
connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, [ = ] {
const bool composite = m_wmHelper->hasComposite();
#ifndef DISABLE_SHOW_ANIMATION
const int duration = composite ? ANIMATIONTIME : 0;
#else
const int duration = 0;
#endif
m_showAni->setDuration(duration);
m_hideAni->setDuration(duration);
});
//FIX: 这里关联信号有时候收不到,未查明原因,handleDbusSignal处理
#if 0
// connect(m_dockInter, &DBusDock::PositionChanged, this, &MultiScreenWorker::onPositionChanged);
@ -1081,61 +1060,105 @@ void MultiScreenWorker::reInitDisplayData()
initDisplayData();
}
void MultiScreenWorker::showAni(const QString &screen)
/**
* @brief MultiScreenWorker::displayAnimation
*
* @param screen
* @param pos 0123
* @param act
* @return void
*/
void MultiScreenWorker::displayAnimation(const QString &screen, const Position &pos, AniAction act)
{
if (m_showAni->state() == QVariantAnimation::Running || m_aniStart)
if (!m_autoHide || m_draging || m_aniStart || m_hideAniStart || m_showAniStart)
return;
emit requestUpdateFrontendGeometry();
/************************************************************************
*
************************************************************************/
//1 先停掉其他的动画,否则这里的修改可能会被其他的动画覆盖掉
if (m_hideAni->state() == QVariantAnimation::Running)
m_hideAni->stop();
QVariantAnimation *ani = new QVariantAnimation(this);
ani->setEasingCurve(QEasingCurve::InOutCubic);
const bool composite = m_wmHelper->hasComposite(); // 判断是否开启特效模式
#ifndef DISABLE_SHOW_ANIMATION
const int duration = composite ? ANIMATIONTIME : 0;
#else
const int duration = 0;
#endif
ani->setDuration(duration);
ani->setStartValue(getDockHideGeometry(screen, pos, m_displayMode));
ani->setEndValue(getDockShowGeometry(screen, pos, m_displayMode));
switch (act) {
case AniAction::Show:
if (getDockShowGeometry(screen, pos, m_displayMode) == parent()->geometry()) {
emit requestNotifyWindowManager();
return;
}
ani->setDirection(QAbstractAnimation::Forward);
connect(ani, &QVariantAnimation::finished, this, &MultiScreenWorker::showAniFinished);
connect(this, &MultiScreenWorker::requestStopShowAni, ani, &QVariantAnimation::stop);
break;
case AniAction::Hide:
if (getDockHideGeometry(screen, pos, m_displayMode) == parent()->geometry()) {
emit requestNotifyWindowManager();
return;
}
ani->setDirection(QAbstractAnimation::Backward); // 隐藏时动画反向走
connect(ani, &QVariantAnimation::finished, this, &MultiScreenWorker::hideAniFinished);
connect(this, &MultiScreenWorker::requestStopHideAni, ani, &QVariantAnimation::stop);
break;
default:
Q_UNREACHABLE();
break;
}
connect(ani, &QVariantAnimation::valueChanged, this, static_cast<void (MultiScreenWorker::*)(const QVariant &value)>(&MultiScreenWorker::updateParentGeometry));
connect(ani, &QVariantAnimation::stateChanged, this, [=](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) {
// 更新动画是否正在进行的信号值
switch (act) {
case AniAction::Show:
if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) {
m_showAniStart = true;
}
if (newState == QVariantAnimation::Stopped && oldState == QVariantAnimation::Running) {
m_showAniStart = false;
}
break;
case AniAction::Hide:
if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) {
m_hideAniStart = true;
}
if (newState == QVariantAnimation::Stopped && oldState == QVariantAnimation::Running) {
m_hideAniStart = false;
}
break;
default:
break;
}
});
parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size());
parent()->panel()->move(0, 0);
//2 任务栏位置已经正确就不需要再重复一次动画了
if (getDockShowGeometry(screen, m_position, m_displayMode) == parent()->geometry()) {
emit requestNotifyWindowManager();
return;
}
// 显示之前先更新
emit requestStopShowAni();
emit requestStopHideAni();
emit requestUpdateLayout();
m_showAni->setStartValue(getDockHideGeometry(screen, m_position, m_displayMode));
m_showAni->setEndValue(getDockShowGeometry(screen, m_position, m_displayMode));
m_showAni->start();
ani->start(QVariantAnimation::DeleteWhenStopped);
}
void MultiScreenWorker::hideAni(const QString &screen, const Position &pos, const DisplayMode &displayMode)
/**
* @brief MultiScreenWorker::displayAnimation
*
* @param screen
* @param act
* @return void
*/
void MultiScreenWorker::displayAnimation(const QString &screen, AniAction act)
{
if (m_hideAni->state() == QVariantAnimation::Running || m_aniStart)
return;
/************************************************************************
*
************************************************************************/
//1 先停掉其他的动画,否则这里的修改可能会被其他的动画覆盖掉
if (m_showAni->state() == QVariantAnimation::Running)
m_showAni->stop();
parent()->panel()->setFixedSize(dockRect(m_ds.current(), pos, HideMode::KeepShowing, displayMode).size());
parent()->panel()->move(0, 0);
//2 任务栏位置已经正确就不需要再重复一次动画了
const QRect destRect = getDockHideGeometry(screen, pos, displayMode);
if (destRect == parent()->geometry()) {
emit requestNotifyWindowManager();
return;
}
m_hideAni->setStartValue(getDockShowGeometry(screen, pos, displayMode));
m_hideAni->setEndValue(destRect);
m_hideAni->start();
return displayAnimation(screen, m_position, act);
}
void MultiScreenWorker::changeDockPosition(QString fromScreen, QString toScreen, const Position &fromPos, const Position &toPos)
@ -1790,7 +1813,7 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY)
return;
}
if (m_showAni->state() == QVariantAnimation::Running) {
if (m_showAniStart) {
qDebug() << "animation is running";
return;
}
@ -1799,16 +1822,11 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY)
qDebug() << "boundRect:" << boundRect;
if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide)
&& (boundRect.size().isEmpty())) {
showAni(m_ds.current());
displayAnimation(m_ds.current(), AniAction::Show);
}
}
}
void MultiScreenWorker::hideAni(const QString &screen)
{
return hideAni(screen, m_position, m_displayMode);
}
void MultiScreenWorker::onConfigChange(const QString &changeKey)
{
if (changeKey == MonitorsSwitchTime) {

View File

@ -198,6 +198,11 @@ public:
Key = 1 << 2
};
enum AniAction {
Show = 0,
Hide
};
MultiScreenWorker(QWidget *parent, DWindowManagerHelper *helper);
~MultiScreenWorker();
@ -279,6 +284,9 @@ signals:
void requestUpdateMonitorInfo(); // 屏幕信息发生变化,需要更新任务栏大小,拖拽区域,所在屏幕,监控区域,通知窗管,通知后端,
void requestDelayShowDock(const QString &screenName); // 延时唤醒任务栏
void requestStopShowAni();
void requestStopHideAni();
public slots:
void onAutoHideChanged(bool autoHide);
/**
@ -358,29 +366,16 @@ private:
* ,
*/
void reInitDisplayData();
/**
* @brief showAni
* @param screen
*/
void showAni(const QString &screen);
void displayAnimation(const QString &screen, const Position &pos, AniAction act);
void displayAnimation(const QString &screen, AniAction act);
/**
* @brief tryToShowDock xEvent监控区域信号的xy坐标处理任务栏唤醒显示
* @param eventX x坐标
* @param eventY y坐标
*/
void tryToShowDock(int eventX, int eventY);
/**
* @brief hideAni
* @param screen ,使
*/
void hideAni(const QString &screen);
/**
* @brief hideAni
* @param screen
* @param pos
* @param displayMode
*/
void hideAni(const QString &screen, const Position &pos, const DisplayMode &displayMode);
/**
* @brief changeDockPosition
* @param lastScreen
@ -459,10 +454,6 @@ private:
QGSettings *m_monitorSetting; // 多屏配置控制
// animation
QVariantAnimation *m_showAni;
QVariantAnimation *m_hideAni;
// 屏幕名称信息
DockScreen m_ds;
// 显示器信息
@ -481,6 +472,8 @@ private:
QString m_registerKey;
QString m_extralRegisterKey;
QString m_touchRegisterKey; // 触控屏唤起任务栏监控区域key
bool m_showAniStart; // 动画显示过程正在执行标志
bool m_hideAniStart; // 动画隐藏过程正在执行标志
bool m_aniStart; // changeDockPosition是否正在运行中
bool m_draging; // 鼠标是否正在调整任务栏的宽度或高度
bool m_autoHide; // 和MenuWorker保持一致,为false时表示菜单已经打开