fix: 修复自动关闭显示屏唤醒后任务栏显示位置的错误

问题原因:在自动关闭显示屏后,底层会先禁用掉显示器然后再开启显示器,前端收到禁用显示器的信号后,会把主屏幕设置为另外一个屏幕,这样任务栏就跑到副屏幕了
解决方案:增加一个类,专门用来处理这种情况,判断是否这种情况的方法是,删除显示器,更新主屏幕和新增显示器的操作在1.5秒之内发生;否则,认为是正常的新增删除调整主屏幕的操作,因为正常的这些操作下,屏幕会黑一下,而且这个黑的时间不止1.5秒

Log: 修复自动关闭显示器再唤醒后任务栏的位置的错误问题
Influence: 任务栏,设置屏幕为1分钟,自动关闭显示器为1分钟,任务栏设置为跟随鼠标,什么都不操作,等1分钟过后再唤醒,观察任务栏的位置
Bug: https://pms.uniontech.com/bug-view-114613.html
Change-Id: I6d2190f2e8394261185ef42d544fba338cbe0e14
This commit is contained in:
donghualin 2022-03-18 17:03:08 +08:00
parent 1564718c8a
commit 59b3628ba2
2 changed files with 125 additions and 0 deletions

View File

@ -57,6 +57,7 @@ MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *help
, m_monitorUpdateTimer(new QTimer(this))
, m_delayWakeTimer(new QTimer(this))
, m_ds(DIS_INS->primary())
, m_screenMonitor(new ScreenChangeMonitor(&m_ds, this))
, m_state(AutoHide)
{
qInfo() << "init dock screen: " << m_ds.current();
@ -1254,6 +1255,9 @@ QString MultiScreenWorker::getValidScreen(const Position &pos)
//TODO 考虑在主屏幕名变化时自动更新,是不是就不需要手动处理了
m_ds.updatePrimary(DIS_INS->primary());
if (m_screenMonitor->needUsedLastScreen())
return m_screenMonitor->lastScreen();
if (DIS_INS->canDock(DIS_INS->screen(m_ds.current()), pos))
return m_ds.current();
@ -1770,3 +1774,91 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY)
}
}
}
/**
* @brief
* @param ds
*/
#define TIMESPAN 1500
ScreenChangeMonitor::ScreenChangeMonitor(DockScreen *ds, QObject *parent)
: QObject (parent)
{
connect(qApp, &QApplication::primaryScreenChanged, this, [ this, ds ](QScreen *primaryScreen) {
if (!primaryScreen)
return;
// 在screenAdded之后又会发送一次主屏幕的变更的信息
qInfo() << "primary Screen Changed,primary Screen" << primaryScreen->name();
if (changedInSeconds())
return;
m_lastScreenName = ds->current();
m_changePrimaryName = primaryScreen->name();
m_changeTime = QDateTime::currentDateTime();
qInfo() << "primary Changed Info:lastScreen:" << m_lastScreenName << "changeTime:" << m_changeTime;
});
connect(qApp, &QApplication::screenAdded, this, [ this ](QScreen *newScreen) {
if (newScreen) {
m_newScreenName = newScreen->name();
m_newTime = QDateTime::currentDateTime();
qInfo() <<"screen added:" << m_newScreenName << ", added time:" << m_newTime;
}
});
connect(qApp, &QApplication::screenRemoved, this, [ this ](QScreen *rmScreen) {
if (rmScreen) {
m_removeScreenName = rmScreen->name();
m_removeTime = QDateTime::currentDateTime();
qInfo() <<"screen removed:" << m_removeScreenName << ", removed time:" << m_removeTime;
}
});
}
ScreenChangeMonitor::~ScreenChangeMonitor()
{
}
bool ScreenChangeMonitor::changedInSeconds()
{
// 如果上一次的主屏幕的名称为空,则认为未发送屏幕变化的信号
if (m_changePrimaryName.isEmpty() || !m_changeTime.isValid())
return false;
qint64 nowMsec = QDateTime::currentDateTime().toMSecsSinceEpoch();
qint64 preChangeMsec = m_changeTime.toMSecsSinceEpoch();
return (nowMsec - preChangeMsec <= TIMESPAN);
}
bool ScreenChangeMonitor::needUsedLastScreen() const
{
if (m_lastScreenName.isEmpty())
return false;
// 判断是否在关闭显示器的时候由系统发出来的先禁用显示器再开启显示器
if (!m_changeTime.isValid() || !m_removeTime.isValid() || !m_newTime.isValid())
return false;
// 如果禁用的掉的显示器和开启的显示器的名称不一样,则认为他们是正常的插拔操作
if (m_removeScreenName != m_newScreenName)
return false;
// 如果先插入显示器再拔掉显示器,则认为他们也是正常的插拔操作
if (m_removeTime > m_newTime)
return false;
// 只有在remove显示器在add显示器之前且时间小于1.5秒,才认为他们是由关闭显示器引起的
qint64 changeMsec = m_changeTime.toMSecsSinceEpoch();
// 获取现在的时间,如果现在的时间大于这三个时间一定的值,则认为是手动操作
qint64 nowMsec = QDateTime::currentDateTime().toMSecsSinceEpoch();
if (nowMsec - changeMsec > TIMESPAN)
return false;
qint64 addedMsec = m_newTime.toMSecsSinceEpoch();
qint64 removeMsec = m_removeTime.toMSecsSinceEpoch();
return ((addedMsec - removeMsec <= TIMESPAN) && qAbs(removeMsec - changeMsec) <= TIMESPAN);
}
const QString ScreenChangeMonitor::lastScreen()
{
return m_lastScreenName;
}

View File

@ -59,6 +59,7 @@ class QWidget;
class QTimer;
class MainWindow;
class QGSettings;
class ScreenChangeMonitor;
/**
* @brief The DockScreen class
@ -261,6 +262,7 @@ private:
QTimer *m_delayWakeTimer; // sp3需求切换屏幕显示延时默认2秒唤起任务栏
DockScreen m_ds; // 屏幕名称信息
ScreenChangeMonitor *m_screenMonitor; // 用于监视屏幕是否为系统先拔再插
// 任务栏属性
double m_opacity;
@ -282,4 +284,35 @@ private:
/*****************************************************************/
};
/**
*
*
*
*
*
*/
class ScreenChangeMonitor : public QObject
{
Q_OBJECT
public:
ScreenChangeMonitor(DockScreen *ds, QObject *parent);
~ScreenChangeMonitor();
bool needUsedLastScreen() const;
const QString lastScreen();
private:
bool changedInSeconds();
private:
QString m_lastScreenName;
QString m_changePrimaryName;
QDateTime m_changeTime;
QString m_newScreenName;
QDateTime m_newTime;
QString m_removeScreenName;
QDateTime m_removeTime;
};
#endif // MULTISCREENWORKER_H