fix: 任务栏在仅主屏显示模式下切换主屏让其跟随主屏显示

跟随主屏模式下,在切换屏幕的处理中,让任务栏显示到切换后的主屏中,根据后台返回的任务栏的显示还是隐藏状态来当前任务栏显示或者隐藏

Log: 修复切换主屏幕任务栏没有跟着切换并且没有唤起的bug
Bug: https://pms.uniontech.com/zentao/bug-view-92020.html
Bug: https://pms.uniontech.com/zentao/bug-view-92089.html
Change-Id: I54f452f82b6e4ba2711e8c62433b396e4598c30d
This commit is contained in:
Dong Hualin 2021-08-20 21:36:02 +08:00 committed by yanghongwei
parent 6495a484da
commit be1f9b2be9
4 changed files with 92 additions and 10 deletions

View File

@ -138,6 +138,11 @@ bool DisplayManager::isCopyMode()
return true;
}
bool DisplayManager::onlyInPrimary()
{
return m_onlyInPrimary;
}
/**
* @brief DisplayManager::updateScreenDockInfo
*

View File

@ -50,6 +50,7 @@ public:
int screenRawHeight() const;
bool canDock(QScreen *s, Position pos) const;
bool isCopyMode();
bool onlyInPrimary();
private:
void updateScreenDockInfo();

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd.
*
* Author: fanpengcheng <fanpengcheng_cm@deepin.com>
@ -55,6 +55,7 @@ MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *help
, m_delayWakeTimer(new QTimer(this))
, m_ds(DIS_INS->primary())
, m_state(AutoHide)
, m_lastRect(QRect())
{
qInfo() << "init dock screen: " << m_ds.current();
@ -235,6 +236,13 @@ void MultiScreenWorker::onRegionMonitorChanged(int x, int y, const QString &key)
tryToShowDock(x, y);
}
bool MultiScreenWorker::mouseInCurrentScreen()
{
QScreen *currentScreen = DIS_INS->screen(m_ds.current());
QScreen *mouseScreen = DIS_INS->screen(getValidScreen(position()));
return (currentScreen == mouseScreen);
}
// 鼠标在任务栏之外移动时,任务栏该响应隐藏时需要隐藏
void MultiScreenWorker::onExtralRegionMonitorChanged(int x, int y, const QString &key)
{
@ -243,6 +251,19 @@ void MultiScreenWorker::onExtralRegionMonitorChanged(int x, int y, const QString
if (m_extralRegisterKey != key || testState(MousePress))
return;
// 如果当前正在移动鼠标,无需检测
if (testState(ChangePositionAnimationStart)
|| testState(HideAnimationStart)
|| testState(ShowAnimationStart)
|| testState(DockIsShowing)
|| testState(PrimaryScreenChangedForShowing))
return;
// 当双屏幕为扩展模式的时候,屏幕模式设置为一直显示,此时调整主屏,如果鼠标不在调整后的主屏上的时候,这个函数会触发一次(具体原因待查)
// 因此需要在此处判断当前鼠标的位置是否在主屏否则就会出现任务栏在调整前的屏幕上闪一下又回到调整后的主屏幕的bug
if (!mouseInCurrentScreen())
return;
// FIXME:每次都要重置一下是因为qt中的QScreen类缺少nameChanged信号后面会给上游提交patch修复
m_ds.updateDockedScreen(getValidScreen(position()));
@ -312,7 +333,24 @@ void MultiScreenWorker::primaryScreenChanged()
return;
}
m_monitorUpdateTimer->start();
// 如果当前任务栏是跟随主屏的模式,则先更新任务栏的所在的屏幕
if (DIS_INS->onlyInPrimary()) {
QTimer::singleShot(100, [ = ] {
resetDockScreen();
setStates(PrimaryScreenChangedForShowing);
// 通知后端
onRequestUpdateFrontendGeometry();
// 通知窗管
updateDockScreen();
// 更新当前屏幕
m_ds.updateDockedScreen(m_ds.primary());
// 更新主屏幕的锁定状态
updatePrimaryScreenDockStatus();
});
} else {
m_monitorUpdateTimer->start();
}
}
void MultiScreenWorker::updateParentGeometry(const QVariant &value, const Position &pos)
@ -696,13 +734,9 @@ void MultiScreenWorker::onRequestUpdateFrontendGeometry()
*/
void MultiScreenWorker::onRequestNotifyWindowManager()
{
static QRect lastRect = QRect();
static int lastScreenWidth = 0;
static int lastScreenHeight = 0;
/* 在非主屏或非一直显示状态时,清除任务栏区域,不挤占应用 */
if ((!DIS_INS->isCopyMode() && m_ds.current() != m_ds.primary()) || m_hideMode != HideMode::KeepShowing) {
lastRect = QRect();
m_lastRect = QRect();
const auto display = QX11Info::display();
if (!display) {
@ -714,14 +748,22 @@ void MultiScreenWorker::onRequestNotifyWindowManager()
return;
}
updateDockScreen();
}
void MultiScreenWorker::updateDockScreen()
{
static int lastScreenWidth = 0;
static int lastScreenHeight = 0;
QRect dockGeometry = getDockShowGeometry(m_ds.current(), m_position, m_displayMode, true);
if (lastRect == dockGeometry
if (m_lastRect == dockGeometry
&& lastScreenWidth == DIS_INS->screenRawWidth()
&& lastScreenHeight == DIS_INS->screenRawHeight()) {
return;
}
lastRect = dockGeometry;
m_lastRect = dockGeometry;
lastScreenWidth = DIS_INS->screenRawWidth();
lastScreenHeight = DIS_INS->screenRawHeight();
qDebug() << "dock real geometry:" << dockGeometry;
@ -775,6 +817,26 @@ void MultiScreenWorker::onRequestNotifyWindowManager()
static_cast<uint>(strutEnd)); // 设置任务栏终点坐标上下为x左右为y
}
void MultiScreenWorker::updatePrimaryScreenDockStatus()
{
const Dock::HideState state = Dock::HideState(m_dockInter->hideState());
if (state == Dock::Unknown)
return;
if (m_hideMode == HideMode::KeepShowing
|| ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) {
displayAnimation(m_ds.primary(), AniAction::Show);
} else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) {
if (getDockShowGeometry(m_ds.primary(), m_position, m_displayMode).contains(QCursor::pos()))
return;
displayAnimation(m_ds.primary(), AniAction::Hide);
} else {
Q_UNREACHABLE();
}
}
void MultiScreenWorker::onRequestUpdatePosition(const Position &fromPos, const Position &toPos)
{
qInfo() << "request change pos from: " << fromPos << " to: " << toPos;
@ -994,6 +1056,7 @@ void MultiScreenWorker::displayAnimation(const QString &screen, const Position &
* 1
*
*/
switch (act) {
case AniAction::Show:
if (pos == Position::Top || pos == Position::Bottom) {
@ -1063,6 +1126,12 @@ void MultiScreenWorker::displayAnimation(const QString &screen, const Position &
setStates(ShowAnimationStart, false);
else // 如果不是一直显示的状态则让其延时修改状态防止在resetDock的时候重复改变其高度引起任务栏闪烁导致无法唤醒
QTimer::singleShot(ANIMATIONTIME, [ = ] { setStates(DockIsShowing, false); });
QTimer::singleShot(ANIMATIONTIME, [ = ] {
// 如果当前是切换屏幕后,任务栏显示结束,则让这个标记移除
if (testState(PrimaryScreenChangedForShowing))
setStates(PrimaryScreenChangedForShowing, false);
});
}
break;
case AniAction::Hide:
@ -1240,7 +1309,8 @@ void MultiScreenWorker::resetDockScreen()
if (testState(ChangePositionAnimationStart)
|| testState(HideAnimationStart)
|| testState(ShowAnimationStart)
|| testState(DockIsShowing))
|| testState(DockIsShowing)
|| testState(PrimaryScreenChangedForShowing))
return;
m_ds.updateDockedScreen(getValidScreen(position()));

View File

@ -124,6 +124,7 @@ public:
TouchPress = 0x20, // 当前触摸屏下是否按下
LauncherDisplay = 0x40, // 启动器是否显示
DockIsShowing = 0x80, // 任务栏正在显示
PrimaryScreenChangedForShowing = 0x100, // 切换了主屏幕
// 如果要添加新的状态,可以在上面添加
RunState_Mask = 0xffffffff,
@ -239,6 +240,10 @@ private:
bool onScreenEdge(const QString &screenName, const QPoint &point);
const QPoint rawXPosition(const QPoint &scaledPos);
void updateDockScreen();
void updatePrimaryScreenDockStatus();
bool mouseInCurrentScreen();
private:
QWidget *m_parent;
DWindowManagerHelper *m_wmHelper;
@ -276,6 +281,7 @@ private:
QString m_delayScreen; // 任务栏将要切换到的屏幕名
RunStates m_state;
/*****************************************************************/
QRect m_lastRect;
};
#endif // MULTISCREENWORKER_H