fix(frame): 动画异常

旧代码动画实现方式是采用延时触发,以设定的300毫秒动画时间为参照,动画相关的功能逻辑均是或先于或晚于该时间执行,当遇到机器运算较慢,或瞬时CPU负荷较重时,程序地执行流程会出现紊乱,而背离预期行为,出现一些特定情况下BUG,且难以分析,复现和调试。现删除所有以特定时间为先后顺序,来控制动画相关功能实现方式,改为以事件结束为依据地触发方式

Log: 修复dock栏位置和显示都出错的问题
Bug: https://pms.uniontech.com/zentao/bug-view-12178.html
Bug: https://pms.uniontech.com/zentao/bug-view-25873.html
Task: https://pms.uniontech.com/zentao/task-view-25153.html
Bug: https://pms.uniontech.com/zentao/bug-view-28993.html
This commit is contained in:
zhaolong 2020-06-10 21:24:38 +08:00
parent 9f45c93872
commit 44cf2dd47d
4 changed files with 113 additions and 136 deletions

View File

@ -262,9 +262,9 @@ const QRect DockSettings::windowRect(const Position position, const bool hide)
if (hide) {
switch (position) {
case Top:
case Bottom: size.setHeight(2); break;
case Bottom: size.setHeight(0); break;
case Left:
case Right: size.setWidth(2); break;
case Right: size.setWidth(0); break;
}
}
@ -412,23 +412,14 @@ void DockSettings::onGSettingsChanged(const QString &key)
void DockSettings::onPositionChanged()
{
const Position prevPos = m_position;
const Position nextPos = Dock::Position(m_dockInter->position());
if (prevPos == nextPos)
if (m_position == nextPos)
return;
m_position = nextPos;
emit positionChanged(prevPos, nextPos);
QTimer::singleShot(200, this, [this, nextPos] {
m_position = nextPos;
DockItem::setDockPosition(nextPos);
qApp->setProperty(PROP_POSITION, QVariant::fromValue(nextPos));
calculateWindowConfig();
m_itemManager->refershItemsIcon();
});
// 通知主窗口改变位置
emit positionChanged();
}
void DockSettings::onDisplayModeChanged()
@ -467,7 +458,7 @@ void DockSettings::hideStateChanged()
void DockSettings::dockItemCountChanged()
{
emit windowGeometryChanged();
// emit windowGeometryChanged();
}
void DockSettings::primaryScreenChanged()
@ -646,6 +637,16 @@ void DockSettings::checkService()
}
}
void DockSettings::posChangedUpdateSettings()
{
DockItem::setDockPosition(m_position);
qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position));
calculateWindowConfig();
m_itemManager->refershItemsIcon();
}
void DockSettings::calculateMultiScreensPos()
{
QList<Monitor *> monitors = m_monitors.keys();

View File

@ -76,13 +76,15 @@ public:
bool setDockScreen(const QString &scrName);
QString &currentDockScreen() { return m_currentScreen; }
void posChangedUpdateSettings();
QSize m_mainWindowSize;
DBusDock *m_dockInter;
bool m_menuVisible;
signals:
void dataChanged() const;
void positionChanged(const Position prevPosition, const Position nextPosition) const;
void positionChanged() const;
void autoHideChanged(const bool autoHide) const;
void displayModeChanegd() const;
void windowVisibleChanged() const;

View File

@ -178,10 +178,9 @@ MainWindow::MainWindow(QWidget *parent)
m_dragWidget->setMouseTracking(true);
m_dragWidget->setFocusPolicy(Qt::NoFocus);
m_curDockPos = m_settings->position();
m_newDockPos = m_curDockPos;
m_dockPosition = m_settings->position();
if ((Top == m_curDockPos) || (Bottom == m_curDockPos)) {
if ((Top == m_dockPosition) || (Bottom == m_dockPosition)) {
m_dragWidget->setCursor(Qt::SizeVerCursor);
} else {
m_dragWidget->setCursor(Qt::SizeHorCursor);
@ -195,12 +194,12 @@ MainWindow::MainWindow(QWidget *parent)
// dock的宽度或高度值
int val = value.toInt();
// 当前dock尺寸
const QRectF windowRect = m_settings->windowRect(m_curDockPos, false);
const QRect windowRect = m_settings->windowRect(m_dockPosition, false);
switch (m_curDockPos) {
switch (m_dockPosition) {
case Dock::Top:
m_mainPanel->move(0, val - windowRect.height());
QWidget::move(windowRect.left(), windowRect.top());
QWidget::move(windowRect.topLeft());
break;
case Dock::Bottom:
m_mainPanel->move(0, 0);
@ -208,7 +207,7 @@ MainWindow::MainWindow(QWidget *parent)
break;
case Dock::Left:
m_mainPanel->move(val - windowRect.width(), 0);
QWidget::move(windowRect.left(), windowRect.top());
QWidget::move(windowRect.topLeft());
break;
case Dock::Right:
m_mainPanel->move(0, 0);
@ -217,7 +216,7 @@ MainWindow::MainWindow(QWidget *parent)
default: break;
}
if (m_curDockPos == Dock::Top || m_curDockPos == Dock::Bottom) {
if (m_dockPosition == Dock::Top || m_dockPosition == Dock::Bottom) {
QWidget::setFixedHeight(val);
} else {
QWidget::setFixedWidth(val);
@ -232,11 +231,11 @@ MainWindow::MainWindow(QWidget *parent)
// dock的宽度或高度
int val = value.toInt();
// dock隐藏后的rect
const QRectF windowRect = m_settings->windowRect(m_curDockPos, false);
const QRect windowRect = m_settings->windowRect(m_dockPosition, false);
const int margin = m_settings->dockMargin();
if (!m_mouseCauseDock) {
switch (m_curDockPos) {
switch (m_dockPosition) {
case Dock::Top:
m_mainPanel->move(0, val - windowRect.height());
QWidget::move(windowRect.left(), windowRect.top() - margin);
@ -257,35 +256,32 @@ MainWindow::MainWindow(QWidget *parent)
}
}
if (m_curDockPos == Dock::Top || m_curDockPos == Dock::Bottom) {
if (m_dockPosition == Dock::Top || m_dockPosition == Dock::Bottom) {
QWidget::setFixedHeight(val);
} else {
QWidget::setFixedWidth(val);
}
});
connect(m_panelShowAni, &QVariantAnimation::finished, [ this ]() {
const QRect windowRect = m_settings->windowRect(m_curDockPos, false);
QWidget::move(windowRect.left(), windowRect.top());
QWidget::setFixedSize(windowRect.size());
m_mainPanel->move(QPoint(0, 0));
resizeMainPanelWindow();
});
// connect(m_panelShowAni, &QVariantAnimation::finished, [ this ]() {
// });
connect(m_panelHideAni, &QVariantAnimation::finished, [ this ]() {
m_mouseCauseDock = false;
m_curDockPos = m_newDockPos;
const QRect windowRect = m_settings->windowRect(m_curDockPos, true);
Position settingPosition = m_settings->position();
// 位置是否更新
if (m_dockPosition != settingPosition) {
// 动画完成更新dock位置
m_dockPosition = settingPosition;
// 动画完成更新dock设置
m_settings->posChangedUpdateSettings();
QWidget::move(windowRect.left(), windowRect.top());
QWidget::setFixedSize(windowRect.size());
m_mainPanel->move(QPoint(0, 0));
if (m_settings->hideMode() != KeepShowing)
this->setVisible(false);
const QRect windowRect = m_settings->windowRect(m_dockPosition, true);
QWidget::move(windowRect.topLeft());
QWidget::setFixedSize(windowRect.size());
m_mainPanel->move(QPoint(0, 0));
}
});
updateRegionMonitorWatch();
@ -302,10 +298,10 @@ void MainWindow::launch()
QTimer::singleShot(400, this, [&] {
m_launched = true;
qApp->processEvents();
QWidget::move(m_settings->windowRect(m_curDockPos).topLeft());
QWidget::move(m_settings->windowRect(m_dockPosition).topLeft());
setVisible(true);
updatePanelVisible();
resetPanelEnvironment(false);
resetPanelEnvironment();
});
}
@ -369,10 +365,6 @@ void MainWindow::enterEvent(QEvent *e)
{
QWidget::enterEvent(e);
m_leaveDelayTimer->stop();
if (m_settings->hideState() != Show && m_panelShowAni->state() != QPropertyAnimation::Running)
m_expandDelayTimer->start();
if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != Qt::ArrowCursor)
QApplication::restoreOverrideCursor();
}
@ -478,7 +470,7 @@ void MainWindow::initConnections()
connect(m_settings, &DockSettings::windowGeometryChanged, this, &MainWindow::updateGeometry, Qt::DirectConnection);
connect(m_settings, &DockSettings::trayCountChanged, this, &MainWindow::getTrayVisableItemCount, Qt::DirectConnection);
connect(m_settings, &DockSettings::windowHideModeChanged, this, &MainWindow::setStrutPartial, Qt::QueuedConnection);
connect(m_settings, &DockSettings::windowHideModeChanged, [this] { resetPanelEnvironment(true); });
connect(m_settings, &DockSettings::windowHideModeChanged, [this] { resetPanelEnvironment(); });
connect(m_settings, &DockSettings::windowHideModeChanged, m_leaveDelayTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
connect(m_settings, &DockSettings::windowVisibleChanged, this, &MainWindow::updatePanelVisible, Qt::QueuedConnection);
connect(m_settings, &DockSettings::displayModeChanegd, m_positionUpdateTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
@ -542,35 +534,13 @@ void MainWindow::x11MoveResizeWindow(const int x, const int y, const int w, cons
XFlush(disp);
}
void MainWindow::positionChanged(const Position prevPos, const Position nextPos)
void MainWindow::positionChanged()
{
m_newDockPos = nextPos;
// paly hide animation and disable other animation
clearStrutPartial();
narrow(prevPos);
narrow();
// set strut
QTimer::singleShot(400, this, [&] {
setStrutPartial();
});
// reset to right environment when animation finished
QTimer::singleShot(500, this, [&] {
m_mainPanel->setPositonValue(m_curDockPos);
resetPanelEnvironment(true);
if ((Top == m_curDockPos) || (Bottom == m_curDockPos))
{
m_dragWidget->setCursor(Qt::SizeVerCursor);
} else
{
m_dragWidget->setCursor(Qt::SizeHorCursor);
}
updatePanelVisible();
});
updateRegionMonitorWatch();
connect(m_panelHideAni, &QVariantAnimation::finished, this, &MainWindow::newPositionExpand);
}
void MainWindow::updatePosition()
@ -595,11 +565,11 @@ void MainWindow::updateGeometry()
setStrutPartial();
m_mainPanel->setDisplayMode(m_settings->displayMode());
m_mainPanel->setPositonValue(m_curDockPos);
m_mainPanel->setPositonValue(m_dockPosition);
bool isHide = m_settings->hideState() == Hide && !testAttribute(Qt::WA_UnderMouse);
const QRect windowRect = m_settings->windowRect(m_curDockPos, isHide);
const QRect windowRect = m_settings->windowRect(m_dockPosition, isHide);
internalMove(windowRect.topLeft());
@ -616,6 +586,25 @@ void MainWindow::getTrayVisableItemCount()
m_mainPanel->getTrayVisableItemCount();
}
void MainWindow::newPositionExpand()
{
// set strut
setStrutPartial();
// reset to right environment when animation finished
m_mainPanel->setPositonValue(m_dockPosition);
resetPanelEnvironment();
if ((Top == m_dockPosition) || (Bottom == m_dockPosition)) {
m_dragWidget->setCursor(Qt::SizeVerCursor);
} else {
m_dragWidget->setCursor(Qt::SizeHorCursor);
}
updatePanelVisible();
disconnect(m_panelHideAni, &QVariantAnimation::finished, this, &MainWindow::newPositionExpand);
}
void MainWindow::clearStrutPartial()
{
m_xcbMisc->clear_strut_partial(winId());
@ -635,8 +624,7 @@ void MainWindow::setStrutPartial()
const auto ratio = devicePixelRatioF();
const int maxScreenHeight = m_settings->screenRawHeight();
const int maxScreenWidth = m_settings->screenRawWidth();
const Position side = m_curDockPos;
const QPoint &p = rawXPosition(m_settings->windowRect(m_curDockPos).topLeft());
const QPoint &p = rawXPosition(m_settings->windowRect(m_dockPosition).topLeft());
const QSize &s = m_settings->windowSize();
const QRect &primaryRawRect = m_settings->currentRawRect();
@ -646,7 +634,7 @@ void MainWindow::setStrutPartial()
uint strutEnd = 0;
QRect strutArea(0, 0, maxScreenWidth, maxScreenHeight);
switch (side) {
switch (m_dockPosition) {
case Position::Top:
orientation = XcbMisc::OrientationTop;
strut = p.y() + s.height() * ratio;
@ -701,7 +689,7 @@ void MainWindow::setStrutPartial()
// }
// if (count > 0) {
// qWarning() << "strutArea is intersects with another screen.";
// qWarning() << maxScreenHeight << maxScreenWidth << side << p << s;
// qWarning() << maxScreenHeight << maxScreenWidth << m_dockPosition << p << s;
// return;
// }
@ -710,9 +698,6 @@ void MainWindow::setStrutPartial()
void MainWindow::expand()
{
qApp->processEvents();
setVisible(true);
if (m_panelHideAni->state() == QPropertyAnimation::Running) {
m_panelHideAni->stop();
emit m_panelHideAni->finished();
@ -720,14 +705,13 @@ void MainWindow::expand()
const auto showAniState = m_panelShowAni->state();
int startValue = 2;
int endValue = 2;
int startValue = 0;
int endValue = 0;
resetPanelEnvironment(true, false);
if (showAniState != QPropertyAnimation::Running /*&& pos() != m_panelShowAni->currentValue()*/) {
bool isHide = m_settings->hideState() == Hide && !testAttribute(Qt::WA_UnderMouse);
const QRectF windowRect = m_settings->windowRect(m_curDockPos, isHide);
switch (m_curDockPos) {
resetPanelEnvironment();
if (showAniState != QPropertyAnimation::Running && pos() != m_panelShowAni->currentValue()) {
const QRect windowRect = m_settings->windowRect(m_dockPosition);
switch (m_dockPosition) {
case Top:
case Bottom:
startValue = height();
@ -754,21 +738,21 @@ void MainWindow::expand()
}
}
void MainWindow::narrow(const Position prevPos)
void MainWindow::narrow()
{
int startValue = 2;
int endValue = 2;
int startValue = 0;
int endValue = 0;
switch (prevPos) {
switch (m_dockPosition) {
case Top:
case Bottom:
startValue = height();
endValue = 2;
endValue = 0;
break;
case Left:
case Right:
startValue = width();
endValue = 2;
endValue = 0;
break;
}
@ -778,7 +762,7 @@ void MainWindow::narrow(const Position prevPos)
m_panelHideAni->start();
}
void MainWindow::resetPanelEnvironment(const bool visible, const bool resetPosition)
void MainWindow::resetPanelEnvironment()
{
if (!m_launched)
return;
@ -806,16 +790,10 @@ void MainWindow::updatePanelVisible()
const Dock::HideState state = m_settings->hideState();
do {
if (state != Hide)
break;
if (!m_settings->autoHide())
break;
if (state == Hide && m_settings->autoHide()) {
QRectF r(pos(), size());
const int margin = m_settings->dockMargin();
switch (m_curDockPos) {
switch (m_dockPosition) {
case Dock::Top:
r.setY(r.y() - margin);
break;
@ -829,16 +807,10 @@ void MainWindow::updatePanelVisible()
r.setWidth(r.width() + margin);
break;
}
if (r.contains(QCursor::pos())) {
break;
if (!r.contains(QCursor::pos())) {
return narrow();
}
// const QRect windowRect = m_settings->windowRect(m_curDockPos, true);
// move(windowRect.topLeft());
return narrow(m_curDockPos);
} while (false);
}
return expand();
}
@ -905,9 +877,8 @@ bool MainWindow::appIsOnDock(const QString &appDesktop)
void MainWindow::resizeMainWindow()
{
const Position position = m_curDockPos;
QSize size = m_settings->windowSize();
const QRect windowRect = m_settings->windowRect(position, false);
const QRect windowRect = m_settings->windowRect(m_dockPosition, false);
internalMove(windowRect.topLeft());
resizeMainPanelWindow();
QWidget::setFixedSize(size);
@ -917,7 +888,7 @@ void MainWindow::resizeMainPanelWindow()
{
m_mainPanel->setFixedSize(m_settings->m_mainWindowSize);
switch (m_curDockPos) {
switch (m_dockPosition) {
case Dock::Top:
m_dragWidget->setGeometry(0, height() - DRAG_AREA_SIZE, width(), DRAG_AREA_SIZE);
break;
@ -944,13 +915,13 @@ void MainWindow::updateDisplayMode()
void MainWindow::onMainWindowSizeChanged(QPoint offset)
{
if (Dock::Top == m_curDockPos) {
if (Dock::Top == m_dockPosition) {
m_settings->m_mainWindowSize.setHeight(qBound(MAINWINDOW_MIN_SIZE, m_size.height() + offset.y(), MAINWINDOW_MAX_SIZE));
m_settings->m_mainWindowSize.setWidth(width());
} else if (Dock::Bottom == m_curDockPos) {
} else if (Dock::Bottom == m_dockPosition) {
m_settings->m_mainWindowSize.setHeight(qBound(MAINWINDOW_MIN_SIZE, m_size.height() - offset.y(), MAINWINDOW_MAX_SIZE));
m_settings->m_mainWindowSize.setWidth(width());
} else if (Dock::Left == m_curDockPos) {
} else if (Dock::Left == m_dockPosition) {
m_settings->m_mainWindowSize.setHeight(height());
m_settings->m_mainWindowSize.setWidth(qBound(MAINWINDOW_MIN_SIZE, m_size.width() + offset.x(), MAINWINDOW_MAX_SIZE));
} else {
@ -970,7 +941,7 @@ void MainWindow::onDragFinished()
m_size = m_settings->m_mainWindowSize;
if (m_settings->displayMode() == Fashion) {
if (Dock::Top == m_curDockPos || Dock::Bottom == m_curDockPos) {
if (Dock::Top == m_dockPosition || Dock::Bottom == m_dockPosition) {
m_settings->m_dockInter->setWindowSizeFashion(m_settings->m_mainWindowSize.height());
m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.height());
} else {
@ -978,7 +949,7 @@ void MainWindow::onDragFinished()
m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.width());
}
} else {
if (Dock::Top == m_curDockPos || Dock::Bottom == m_curDockPos) {
if (Dock::Top == m_dockPosition || Dock::Bottom == m_dockPosition) {
m_settings->m_dockInter->setWindowSizeEfficient(m_settings->m_mainWindowSize.height());
m_settings->m_dockInter->setWindowSize(m_settings->m_mainWindowSize.height());
} else {
@ -1013,13 +984,16 @@ void MainWindow::onRegionMonitorChanged(int x, int y, const QString &key)
if (m_settings->hideMode() == KeepShowing)
return;
if (!isVisible())
setVisible(true);
if (m_panelShowAni->state() == QPropertyAnimation::Running)
return;
// 一直隐藏模式不用通过时间延迟的方式调用,影响离开动画的响应
expand();
} else {
// 移动Dock至相应屏相应位置
m_mouseCauseDock = true;
if (m_settings->setDockScreen(screen->name()))
positionChanged(m_curDockPos, m_curDockPos);
positionChanged();
}
}
@ -1049,7 +1023,7 @@ void MainWindow::updateRegionMonitorWatch()
if (screensRect.size()) {
MonitRect monitRect;
switch (m_curDockPos) {
switch (m_dockPosition) {
case Dock::Top: {
for (QRect rect : screensRect) {
x = rect.x();
@ -1097,5 +1071,4 @@ void MainWindow::updateRegionMonitorWatch()
}
}
#include "mainwindow.moc"

View File

@ -96,7 +96,7 @@ signals:
void panelGeometryChanged();
private slots:
void positionChanged(const Position prevPos, const Position nextPos);
void positionChanged();
void updatePosition();
void updateGeometry();
void clearStrutPartial();
@ -106,8 +106,8 @@ private slots:
void updateDisplayMode();
void expand();
void narrow(const Position prevPos);
void resetPanelEnvironment(const bool visible, const bool resetPosition = true);
void narrow();
void resetPanelEnvironment();
void updatePanelVisible();
void adjustShadowMask();
@ -118,6 +118,8 @@ private slots:
void onDragFinished();
void themeTypeChanged(DGuiApplicationHelper::ColorType themeType);
void newPositionExpand();
private:
bool m_launched;
MainPanelControl *m_mainPanel;
@ -143,8 +145,7 @@ private:
QString m_sniHostService;
QSize m_size;
DragWidget *m_dragWidget;
Position m_curDockPos;
Position m_newDockPos;
Position m_dockPosition;
bool m_mouseCauseDock;
};