From 1e3d90f62b9272b54c9267c68cb32aafbc526660 Mon Sep 17 00:00:00 2001 From: Fan PengCheng Date: Mon, 12 Apr 2021 16:53:03 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=8E=BB=E9=99=A4=E5=AF=B9?= =?UTF-8?q?=E5=90=8E=E7=AB=AFDisplay=E6=9C=8D=E5=8A=A1=E7=9A=84=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端服务数据变化有快有慢,可能导致任务栏不正确时间进行响应,从而导致显示异常,对应的单元测试代码已添加 Log: 重构显示逻辑,保障任务栏显示正常 Change-Id: I62f06c133945a625c2c2ec2b2e21809be27543b6 --- CMakeLists.txt | 3 + frame/CMakeLists.txt | 1 + frame/display/displaymanager.cpp | 307 ++++++++ frame/display/displaymanager.h | 75 ++ frame/item/components/previewcontainer.cpp | 2 +- frame/util/multiscreenworker.cpp | 768 +++++---------------- frame/util/multiscreenworker.h | 140 +--- frame/util/singleton.h | 31 + frame/window/mainwindow.cpp | 71 +- frame/window/mainwindow.h | 6 +- gen_report.sh | 2 +- plugins/tray/xembedtraywidget.cpp | 2 +- tests/display/ut_displaymanager.cpp | 60 ++ tests/{ut_main.cpp => main.cpp} | 0 14 files changed, 694 insertions(+), 774 deletions(-) create mode 100644 frame/display/displaymanager.cpp create mode 100644 frame/display/displaymanager.h create mode 100644 frame/util/singleton.h create mode 100644 tests/display/ut_displaymanager.cpp rename tests/{ut_main.cpp => main.cpp} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4caf1515..168aca4ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ include_directories( frame/controller frame/dbus frame/dbus/sni + frame/display frame/item frame/item/components frame/item/resources @@ -68,6 +69,7 @@ aux_source_directory(frame/accessible ACCESSIBLE) aux_source_directory(frame/controller CONTROLLER) aux_source_directory(frame/dbus DBUS) aux_source_directory(frame/dbus/sni SNI) +aux_source_directory(frame/display DISPLAY) aux_source_directory(frame/item ITEM) aux_source_directory(frame/item/components COMPONENTS) aux_source_directory(frame/item/resources RESOURCES) @@ -80,6 +82,7 @@ file(GLOB SRC_PATH ${CONTROLLER} ${DBUS} ${SNI} + ${DISPLAY} ${ITEM} ${COMPONENTS} ${UTIL} diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt index 0206ee1c1..f6a5f7e0e 100644 --- a/frame/CMakeLists.txt +++ b/frame/CMakeLists.txt @@ -39,6 +39,7 @@ target_include_directories(${BIN_NAME} PUBLIC accessible controller dbus + display item item/components util diff --git a/frame/display/displaymanager.cpp b/frame/display/displaymanager.cpp new file mode 100644 index 000000000..7c372b995 --- /dev/null +++ b/frame/display/displaymanager.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2018 ~ 2028 Uniontech Technology Co., Ltd. + * + * Author: fanpengcheng + * + * Maintainer: fanpengcheng + * + * 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 . + */ + +#include "displaymanager.h" +#include "utils.h" + +#include +#include +#include +#include + +DisplayManager::DisplayManager(QObject *parent) + : QObject(parent) + , m_display(new DisplayInter("com.deepin.daemon.Display", "/com/deepin/daemon/Display", QDBusConnection::sessionBus(), this)) + , m_delayTimer(new QTimer(this)) + , m_gsettings(Utils::SettingsPtr("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", this)) + , m_onlyInPrimary(Utils::SettingValue("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", "onlyShowPrimary", false).toBool()) +{ + connect(qApp, &QApplication::primaryScreenChanged, this, &DisplayManager::primaryScreenChanged); + connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &DisplayManager::screenCountChanged); + connect(m_delayTimer, &QTimer::timeout, this, [ = ] { + updateScreenDockInfo(); + +#ifdef QT_DEBUG + qInfo() << m_screenPositionMap; +#endif + + Q_EMIT screenInfoChanged(); + }); + if (m_gsettings) + connect(m_gsettings, &QGSettings::changed, this, &DisplayManager::onGSettingsChanged); + + m_delayTimer->setInterval(10); + m_delayTimer->setSingleShot(true); + + screenCountChanged(); + updateScreenDockInfo(); +} + +/** + * @brief DisplayManager::screens + * @return 返回当前可用的QScreen指针列表 + */ +QList DisplayManager::screens() const +{ + return m_screens; +} + +/** + * @brief DisplayManager::screen + * @param screenName + * @return 根据screenName参数找到对应的QScreen指针返回,否则返回nullptr + */ +QScreen *DisplayManager::screen(const QString &screenName) const +{ + for (auto s : m_screens) { + if (s->name() == screenName) + return s; + } + + qWarning() << "Screen: " << screenName << " can`t be found!"; + return nullptr; +} + +/** + * @brief DisplayManager::primary + * @return 主屏幕名称 + */ +QString DisplayManager::primary() const +{ + return qApp->primaryScreen() ? qApp->primaryScreen()->name() : QString(); +} + +/** + * @brief Display::screenWidth + * @return 所有屏幕逻辑宽度之和 + */ +int DisplayManager::screenRawWidth() const +{ + int width = 0; + for (auto s : m_screens) { + width = qMax(width, s->geometry().x() + int(s->geometry().width() * s->devicePixelRatio())); + } + + return width; +} +/** + * @brief Display::screenHeight + * @return 所有屏幕逻辑高度之和 + */ + +int DisplayManager::screenRawHeight() const +{ + int height = 0; + for (auto s : m_screens) { + height = qMax(height, s->geometry().y() + int(s->geometry().height() * s->devicePixelRatio())); + } + + return height; +} + +/** + * @brief DisplayManager::canDock + * @param s QScreen指针 + * @param pos 任务栏位置(上下左右) + * @return 判断当前s屏幕上pos位置任务栏位置是否允许停靠 + */ +bool DisplayManager::canDock(QScreen *s, Position pos) const +{ + return s ? m_screenPositionMap[s].value(pos) : false; +} + +/** + * @brief DisplayManager::updateScreenDockInfo + * 更新屏幕停靠信息 + */ +void DisplayManager::updateScreenDockInfo() +{ + // TODO 目前仅仅支持双屏,如果超过双屏,会出现异常,这里可以考虑做成通用的处理规则 + + // 先清除原先的数据,然后再更新 + m_screenPositionMap.clear(); + + if (m_screens.isEmpty()) + return; + + // reset map + for (auto s : m_screens) { + QMap map; + map.insert(Position::Top, true); + map.insert(Position::Bottom, true); + map.insert(Position::Left, true); + map.insert(Position::Right, true); + m_screenPositionMap.insert(s, map); + } + + // 仅显示在主屏时的处理 + if (m_onlyInPrimary) { + for (auto s : m_screens) { + if (s != qApp->primaryScreen()) { + QMap map; + map.insert(Position::Top, false); + map.insert(Position::Bottom, false); + map.insert(Position::Left, false); + map.insert(Position::Right, false); + m_screenPositionMap.insert(s, map); + } + } + } + + if (m_screens.size() == 1) { + return; + } + + // 最多支持双屏,这里只计算双屏,单屏默认四边均可停靠任务栏 + if (m_screens.size() == 2) { + QRect s0 = m_screens.at(0)->geometry(); + s0.setSize(s0.size() * m_screens.at(0)->devicePixelRatio()); + QRect s1 = m_screens.at(1)->geometry(); + s1.setSize(s1.size() * m_screens.at(1)->devicePixelRatio()); + + qInfo() << "monitor info changed" << m_screens.at(0)->name() << s0 << m_screens.at(1)->name() << s1; + + int s0top = s0.y(); + int s0bottom = s0.y() + s0.height(); + int s0left = s0.x(); + int s0Right = s0.x() + s0.width(); + + int s1top = s1.y(); + int s1bottom = s1.y() + s1.height(); + int s1left = s1.x(); + int s1Right = s1.x() + s1.width(); + + QPoint s0topLeft = QPoint(s0.x(), s0.y()); + QPoint s0topRight = QPoint(s0.x()+ s0.width(), s0.y()); + QPoint s0bottomRight = QPoint(s0.x()+ s0.width(), s0.y() + s0.height()); + QPoint s0bottomLeft = QPoint(s0.x(), s0.y() + s0.height()); + + QPoint s1topLeft = QPoint(s1.x(), s1.y()); + QPoint s1topRight = QPoint(s1.x() + s1.width(), s1.y()); + QPoint s1bottomRight = QPoint(s1.x() + s1.width(), s1.y() + s1.height()); + QPoint s1bottomLeft = QPoint(s1.x(), s1.y() + s1.height()); + + // 对角拼接,重置,默认均可停靠 + if (s0bottomRight == s1topLeft + || s0topRight == s1bottomRight) { + return; + } + + // 左右拼接,s0左,s1右 + if (s0Right == s1left + && (s0topRight == s1topLeft || s0bottomRight == s1bottomLeft)) { + m_screenPositionMap[m_screens.at(0)].insert(Position::Right, false); + m_screenPositionMap[m_screens.at(1)].insert(Position::Left, false); + return; + } + + // 左右拼接,s0右,s1左 + if (s0left== s1Right + && (s0topRight == s1topRight || s0bottomLeft == s1bottomRight)) { + m_screenPositionMap[m_screens.at(0)].insert(Position::Left, false); + m_screenPositionMap[m_screens.at(1)].insert(Position::Right, false); + return; + } + + // 上下拼接,s0上,s1下 + if (s0bottom == s1top + && (s0bottomLeft == s1topLeft || s0bottomRight == s1topRight)) { + m_screenPositionMap[m_screens.at(0)].insert(Position::Bottom, false); + m_screenPositionMap[m_screens.at(1)].insert(Position::Top, false); + return; + } + + // 上下拼接,s0下,s1上 + if (s0top == s1bottom + && (s0topLeft == s1bottomLeft || s0topRight == s1bottomRight)) { + m_screenPositionMap[m_screens.at(0)].insert(Position::Top, false); + m_screenPositionMap[m_screens.at(1)].insert(Position::Bottom, false); + return; + } + return; + } + + // 目前不支持链接超过两个以上的显示器 + Q_UNREACHABLE(); +} + +/** + * @brief DisplayManager::screenCountChanged + * 屏幕数量发生变化时,此函数应被调用,更新屏幕相关信息 + * @note 除初始化时需要手动调用一次外,其他时间会自动被调用 + */ +void DisplayManager::screenCountChanged() +{ + // 找到过期的screen指针 + QList to_remove_list; + for (auto s : m_screens) { + if (!qApp->screens().contains(s)) + to_remove_list.append(s); + } + + // 找出新增的screen指针 + QList to_add_list; + for (auto s : qApp->screens()) { + if (!m_screens.contains(s)) { + to_add_list.append(s); + } + } + + // 取消关联 + for (auto s : to_remove_list) { + disconnect(s); + m_screens.removeOne(s); + } + + // 创建关联 + for (auto s : to_add_list) { + s->setOrientationUpdateMask(Qt::PrimaryOrientation + | Qt::LandscapeOrientation + | Qt::PortraitOrientation + | Qt::InvertedLandscapeOrientation + | Qt::InvertedPortraitOrientation); + + connect(s, &QScreen::geometryChanged, m_delayTimer, static_cast(&QTimer::start)); + connect(s, &QScreen::primaryOrientationChanged, m_delayTimer, static_cast(&QTimer::start)); + connect(s, &QScreen::orientationChanged, m_delayTimer, static_cast(&QTimer::start)); + + m_screens.append(s); + } + + // 屏幕数量发生变化,应该刷新一下任务栏的显示 + m_delayTimer->start(); +} + +/** + * @brief DisplayManager::onGSettingsChanged + * @param key + * 监听onlyShowPrimary配置的变化,此时有变化时应该刷新一下任务栏的显示信息 + */ +void DisplayManager::onGSettingsChanged(const QString &key) +{ + if (key == "onlyShowPrimary") { + m_onlyInPrimary = Utils::SettingValue("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", "onlyShowPrimary", false).toBool(); + + updateScreenDockInfo(); + + m_delayTimer->start(); + } +} diff --git a/frame/display/displaymanager.h b/frame/display/displaymanager.h new file mode 100644 index 000000000..739657624 --- /dev/null +++ b/frame/display/displaymanager.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2018 ~ 2028 Uniontech Technology Co., Ltd. + * + * Author: fanpengcheng + * + * Maintainer: fanpengcheng + * + * 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 . + */ + +#ifndef DISPLAYMANAGER_H +#define DISPLAYMANAGER_H + +#include + +#include "singleton.h" +#include "constants.h" + +#include +#include +#include + +using DisplayInter = com::deepin::daemon::Display; +using namespace Dock; + +class QScreen; +class QTimer; +class QGSettings; +class DisplayManager: public QObject, public Singleton +{ + Q_OBJECT + friend class Singleton; + +public: + explicit DisplayManager(QObject *parent = Q_NULLPTR); + + QList screens() const; + QScreen *screen(const QString &screenName) const; + QString primary() const; + int screenRawWidth() const; + int screenRawHeight() const; + bool canDock(QScreen *s, Position pos) const; + +private: + void updateScreenDockInfo(); + +private Q_SLOTS: + void screenCountChanged(); + void onGSettingsChanged(const QString &key); + +Q_SIGNALS: + void primaryScreenChanged(); + void screenInfoChanged(); // 屏幕信息发生变化,需要调整任务栏显示,只需要这一个信号,其他的都不要,简化流程 + +private: + DisplayInter *m_display; + QTimer *m_delayTimer; + QList m_screens; + QMap > m_screenPositionMap; + const QGSettings *m_gsettings; // 多屏配置控制 + bool m_onlyInPrimary; +}; + +#endif // DISPLAYMANAGER_H diff --git a/frame/item/components/previewcontainer.cpp b/frame/item/components/previewcontainer.cpp index 6adedddb1..eba32688e 100644 --- a/frame/item/components/previewcontainer.cpp +++ b/frame/item/components/previewcontainer.cpp @@ -139,7 +139,7 @@ void PreviewContainer::adjustSize() if (composite) { // 3D - const QRect r = qApp->primaryScreen()->geometry(); + const QRect r = qApp->primaryScreen() ? qApp->primaryScreen()->geometry() : QRect(); const int padding = 20; const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight; diff --git a/frame/util/multiscreenworker.cpp b/frame/util/multiscreenworker.cpp index be9ada850..cc75e522f 100644 --- a/frame/util/multiscreenworker.cpp +++ b/frame/util/multiscreenworker.cpp @@ -22,6 +22,7 @@ #include "multiscreenworker.h" #include "mainwindow.h" #include "utils.h" +#include "displaymanager.h" #include #include @@ -38,8 +39,6 @@ const QString OnlyShowPrimary = "onlyShowPrimary"; // 保证以下数据更新顺序(大环节顺序不要变,内部还有一些小的调整,比如任务栏显示区域更新的时候,里面内容的布局方向可能也要更新...) // Monitor数据->屏幕是否可停靠更新->监视唤醒区域更新,任务栏显示区域更新->拖拽区域更新->通知后端接口,通知窗管 -// TODO 后续需要去除使用qt的接口获取屏幕信息,统一使用从com.deepin.daemon.Display服务中给定的数据 - MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *helper) : QObject(nullptr) , m_parent(parent) @@ -48,23 +47,19 @@ MultiScreenWorker::MultiScreenWorker(QWidget *parent, DWindowManagerHelper *help , m_extralEventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus())) , m_touchEventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus())) , m_dockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) - , m_displayInter(new DisplayInter("com.deepin.daemon.Display", "/com/deepin/daemon/Display", QDBusConnection::sessionBus(), this)) , m_launcherInter(new DBusLuncher("com.deepin.dde.Launcher", "/com/deepin/dde/Launcher", QDBusConnection::sessionBus())) , m_monitorUpdateTimer(new QTimer(this)) , m_delayWakeTimer(new QTimer(this)) - , m_gsettings(Utils::SettingsPtr("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", this)) - , m_ds(m_displayInter->primary()) - , m_monitorRotation(1) + , m_ds(DisplayManager::instance()->primary()) , m_showAniStart(false) , m_hideAniStart(false) , m_aniStart(false) - , m_draging(false) , m_autoHide(true) , m_btnPress(false) { qInfo() << "init dock screen: " << m_ds.current(); + initMembers(); - initGSettingConfig(); initDBus(); initConnection(); initDisplayData(); @@ -193,14 +188,6 @@ void MultiScreenWorker::updateDaemonDockSize(int dockSize) m_dockInter->setWindowSizeEfficient(uint(dockSize)); } -void MultiScreenWorker::onDragStateChanged(bool draging) -{ - if (m_draging == draging) - return; - - m_draging = draging; -} - void MultiScreenWorker::handleDbusSignal(QDBusMessage msg) { QList arguments = msg.arguments(); @@ -223,17 +210,6 @@ void MultiScreenWorker::handleDbusSignal(QDBusMessage msg) onHideStateChanged(); } } - } else if (interfaceName == "com.deepin.daemon.Display") { - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - QStringList keys = changedProps.keys(); - foreach (const QString &prop, keys) { - if (prop == "ScreenHeight") { - m_screenRawHeight = m_displayInter->screenHeight(); - } else if (prop == "ScreenWidth") { - m_screenRawWidth = m_displayInter->screenWidth(); - } - } - updateScreenSize(); } } @@ -266,90 +242,6 @@ void MultiScreenWorker::onExtralRegionMonitorChanged(int x, int y, const QString } } -void MultiScreenWorker::onMonitorListChanged(const QList &mons) -{ - if (mons.isEmpty()) - return; - - QList ops; - for (const auto *mon : m_mtrInfo.data().keys()) - ops << mon->path(); - - QList pathList; - for (auto op : mons) { - const QString path = op.path(); - pathList << path; - if (!ops.contains(path)) - monitorAdded(path); - } - - for (auto op : ops) - if (!pathList.contains(op)) - monitorRemoved(op); -} - -void MultiScreenWorker::monitorAdded(const QString &path) -{ - MonitorInter *inter = new MonitorInter("com.deepin.daemon.Display", path, QDBusConnection::sessionBus(), this); - Monitor *mon = new Monitor(this); - - connect(inter, &MonitorInter::XChanged, mon, &Monitor::setX); - connect(inter, &MonitorInter::YChanged, mon, &Monitor::setY); - connect(inter, &MonitorInter::WidthChanged, mon, &Monitor::setW); - connect(inter, &MonitorInter::HeightChanged, mon, &Monitor::setH); - connect(inter, &MonitorInter::NameChanged, mon, &Monitor::setName); - connect(inter, &MonitorInter::EnabledChanged, mon, &Monitor::setMonitorEnable); - - // 这里有可能在使用Monitor中的数据时,但实际上Monitor数据还未准备好.以Monitor中的信号为准,不能以MonitorInter中信号为准, - connect(mon, &Monitor::geometryChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); - connect(mon, &Monitor::enableChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); - connect(mon, &Monitor::nameChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); - - // NOTE: DO NOT using async dbus call. because we need to have a unique name to distinguish each monitor - Q_ASSERT(inter->isValid()); - mon->setName(inter->name()); - -#if 0 // 模拟屏幕名称中途发生变化的情况,测试任务栏是否还能正常显示 - QTimer::singleShot(5000, this, [ = ]{ - if (mon->name() == "VGA-0") - mon->setName(":0.0"); - }); - QTimer::singleShot(10000, this, [ = ]{ - if (mon->name() == ":0.0") - mon->setName("VGA-0"); - }); -#endif - - mon->setMonitorEnable(inter->enabled()); - mon->setPath(path); - mon->setX(inter->x()); - mon->setY(inter->y()); - mon->setW(inter->width()); - mon->setH(inter->height()); - - m_mtrInfo.insert(mon, inter); - - inter->setSync(false); -} - -void MultiScreenWorker::monitorRemoved(const QString &path) -{ - Monitor *monitor = nullptr; - for (auto it(m_mtrInfo.data().cbegin()); it != m_mtrInfo.data().cend(); ++it) { - if (it.key()->path() == path) { - monitor = it.key(); - break; - } - } - if (!monitor) - return; - - m_mtrInfo.data().value(monitor)->deleteLater(); - m_mtrInfo.remove(monitor); - - monitor->deleteLater(); -} - void MultiScreenWorker::showAniFinished() { const QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); @@ -362,7 +254,6 @@ void MultiScreenWorker::showAniFinished() emit requestUpdateFrontendGeometry(); emit requestNotifyWindowManager(); - emit requestUpdateDragArea(); } void MultiScreenWorker::hideAniFinished() @@ -394,26 +285,13 @@ void MultiScreenWorker::onWindowSizeChanged(uint value) void MultiScreenWorker::primaryScreenChanged() { - QString primaryName = m_displayInter->primary(); - if (primaryName.isEmpty() && qApp->primaryScreen()->name().isEmpty()) { - qWarning() << "current primary screen:" << primaryName; - return; - } - - // 后端数据不准确,使用qt获取的数据 - if (primaryName.isEmpty()) - primaryName = qApp->primaryScreen()->name(); - // 先更新主屏信息 - m_ds.updatePrimary(primaryName); - m_mtrInfo.setPrimary(primaryName); - - const int screenRawHeight = m_displayInter->screenHeight(); - const int screenRawWidth = m_displayInter->screenWidth(); + m_ds.updatePrimary(DisplayManager::instance()->primary()); // 无效值 - if (screenRawHeight == 0 || screenRawWidth == 0) { - qWarning() << "screen raw data is not valid:" << screenRawHeight << screenRawWidth; + if (DisplayManager::instance()->screenRawHeight() == 0 || DisplayManager::instance()->screenRawWidth() == 0) { + qWarning() << "screen raw data is not valid:" + << DisplayManager::instance()->screenRawHeight() << DisplayManager::instance()->screenRawWidth(); return; } @@ -487,8 +365,6 @@ void MultiScreenWorker::onPositionChanged() // 一直显示的模式才需要显示 emit requestUpdatePosition(lastPos, position); } - - emit requestUpdateRegionMonitor(); } void MultiScreenWorker::onDisplayModeChanged() @@ -520,10 +396,8 @@ void MultiScreenWorker::onDisplayModeChanged() parent()->panel()->setDisplayMode(m_displayMode); emit displayModeChanegd(); - emit requestUpdateRegionMonitor(); emit requestUpdateFrontendGeometry(); emit requestNotifyWindowManager(); - emit requestUpdateDragArea(); } void MultiScreenWorker::onHideModeChanged() @@ -560,13 +434,11 @@ void MultiScreenWorker::onHideStateChanged() m_hideState = state; // 检查当前屏幕的当前位置是否允许显示,不允许需要更新显示信息(这里应该在函数外部就处理好,不应该走到这里) - Monitor *currentMonitor = waitAndGetScreen(m_ds.current()); - if (!currentMonitor) { - return; - } - if (!currentMonitor->dockPosition().docked(m_position)) { - Q_ASSERT(false); + //TODO 这里是否存在屏幕找不到的问题,m_ds的当前屏幕是否可以做成实时同步的,公用一个指针? + //TODO 这里真的有必要加以下代码吗,只是隐藏模式的切换,理论上不需要检查屏幕是否允许任务栏停靠 + QScreen *curScreen = DisplayManager::instance()->screen(m_ds.current()); + if (!DisplayManager::instance()->canDock(curScreen, m_position)) { m_ds.updateDockedScreen(getValidScreen(m_position)); } @@ -631,141 +503,153 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor() // 任务栏唤起区域 m_monitorRectList.clear(); - foreach (Monitor *inter, m_mtrInfo.validMonitor()) { - // 屏幕不可用或此位置不可停靠时,不用监听这块区域 - if (!inter->enable() || !inter->dockPosition().docked(m_position)) - continue; + for (auto s : DisplayManager::instance()->screens()) { + // 屏幕此位置不可停靠时,不用监听这块区域 + if (!DisplayManager::instance()->canDock(s, m_position)) + return; + + MonitRect monitorRect; + QRect screenRect = s->geometry(); + screenRect.setSize(screenRect.size() * s->devicePixelRatio()); - MonitRect rect; switch (m_position) { case Top: { - rect.x1 = inter->x(); - rect.y1 = inter->y(); - rect.x2 = inter->x() + inter->w(); - rect.y2 = inter->y() + monitorHeight; + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + monitorHeight; } break; case Bottom: { - rect.x1 = inter->x(); - rect.y1 = inter->y() + inter->h() - monitorHeight; - rect.x2 = inter->x() + inter->w(); - rect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y() + screenRect.height() - monitorHeight; + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; case Left: { - rect.x1 = inter->x(); - rect.y1 = inter->y(); - rect.x2 = inter->x() + monitorHeight; - rect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + monitorHeight; + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; case Right: { - rect.x1 = inter->x() + inter->w() - monitorHeight; - rect.y1 = inter->y(); - rect.x2 = inter->x() + inter->w(); - rect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x() + screenRect.width() - monitorHeight; + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; } - if (!m_monitorRectList.contains(rect)) { - m_monitorRectList << rect; + if (!m_monitorRectList.contains(monitorRect)) { + m_monitorRectList << monitorRect; #ifdef QT_DEBUG - qDebug() << "监听区域:" << rect.x1 << rect.y1 << rect.x2 << rect.y2; + qDebug() << "监听区域:" << monitorRect.x1 << monitorRect.y1 << monitorRect.x2 << monitorRect.y2; #endif } } m_extralRectList.clear(); - foreach (Monitor *inter, m_mtrInfo.validMonitor()) { - // 屏幕不可用或此位置不可停靠时,不用监听这块区域 - if (!inter->enable() || !inter->dockPosition().docked(m_position)) - continue; + for (auto s : DisplayManager::instance()->screens()) { + // 屏幕此位置不可停靠时,不用监听这块区域 + if (!DisplayManager::instance()->canDock(s, m_position)) + return; + + MonitRect monitorRect; + QRect screenRect = s->geometry(); + screenRect.setSize(screenRect.size() * s->devicePixelRatio()); - MonitRect rect; switch (m_position) { case Top: { - rect.x1 = inter->x(); - rect.y1 = inter->y() + realDockSize; - rect.x2 = inter->x() + inter->w(); - rect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y() + realDockSize; + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; case Bottom: { - rect.x1 = inter->x(); - rect.y1 = inter->y(); - rect.x2 = inter->x() + inter->w(); - rect.y2 = inter->y() + inter->h() - realDockSize; + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height() - realDockSize; } break; case Left: { - rect.x1 = inter->x() + realDockSize; - rect.y1 = inter->y(); - rect.x2 = inter->x() + inter->w(); - rect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x() + realDockSize; + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; case Right: { - rect.x1 = inter->x(); - rect.y1 = inter->y(); - rect.x2 = inter->x() + inter->w() - realDockSize; - rect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width() - realDockSize; + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; } - if (!m_extralRectList.contains(rect)) { - m_extralRectList << rect; + if (!m_extralRectList.contains(monitorRect)) { + m_extralRectList << monitorRect; #ifdef QT_DEBUG - qDebug() << "任务栏外部区域:" << rect.x1 << rect.y1 << rect.x2 << rect.y2; + qDebug() << "任务栏外部区域:" << monitorRect.x1 << monitorRect.y1 << monitorRect.x2 << monitorRect.y2; #endif } } // 触屏监控高度固定调整为最大任务栏高度100+任务栏与屏幕边缘间距 const int monitHeight = 100 + WINDOWMARGIN; + // 任务栏触屏唤起区域 m_touchRectList.clear(); - foreach (Monitor *inter, m_mtrInfo.validMonitor()) { - // 屏幕不可用或此位置不可停靠时,不用监听这块区域 - if (!inter->enable() || !inter->dockPosition().docked(m_position)) - continue; + for (auto s : DisplayManager::instance()->screens()) { + // 屏幕此位置不可停靠时,不用监听这块区域 + if (!DisplayManager::instance()->canDock(s, m_position)) + return; + + MonitRect monitorRect; + QRect screenRect = s->geometry(); + screenRect.setSize(screenRect.size() * s->devicePixelRatio()); - MonitRect touchRect; switch (m_position) { case Top: { - touchRect.x1 = inter->x(); - touchRect.y1 = inter->y(); - touchRect.x2 = inter->x() + inter->w(); - touchRect.y2 = inter->y() + monitHeight; + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + monitHeight; } break; case Bottom: { - touchRect.x1 = inter->x(); - touchRect.y1 = inter->y() + inter->h() - monitHeight; - touchRect.x2 = inter->x() + inter->w(); - touchRect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y() + screenRect.height() - monitHeight; + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; case Left: { - touchRect.x1 = inter->x(); - touchRect.y1 = inter->y(); - touchRect.x2 = inter->x() + monitHeight; - touchRect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x(); + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + monitHeight; + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; case Right: { - touchRect.x1 = inter->x() + inter->w() - monitHeight; - touchRect.y1 = inter->y(); - touchRect.x2 = inter->x() + inter->w(); - touchRect.y2 = inter->y() + inter->h(); + monitorRect.x1 = screenRect.x() + screenRect.width() - monitHeight; + monitorRect.y1 = screenRect.y(); + monitorRect.x2 = screenRect.x() + screenRect.width(); + monitorRect.y2 = screenRect.y() + screenRect.height(); } break; } - if (!m_touchRectList.contains(touchRect)) { - m_touchRectList << touchRect; + + if (!m_touchRectList.contains(monitorRect)) { + m_touchRectList << monitorRect; } + } m_registerKey = m_eventInter->RegisterAreas(m_monitorRectList, flags); @@ -796,7 +680,7 @@ void MultiScreenWorker::onRequestUpdateFrontendGeometry() void MultiScreenWorker::onRequestNotifyWindowManager() { static QRect lastRect = QRect(); - static int lastScreenWith = 0; + static int lastScreenWidth = 0; static int lastScreenHeight = 0; /* 在非主屏或非一直显示状态时,清除任务栏区域,不挤占应用 */ @@ -814,14 +698,17 @@ void MultiScreenWorker::onRequestNotifyWindowManager() } QRect dockGeometry = getDockShowGeometry(m_ds.current(), m_position, m_displayMode, true); - if (lastRect == dockGeometry && lastScreenWith == m_screenRawWidth && lastScreenHeight == m_screenRawHeight) { + if (lastRect == dockGeometry + && lastScreenWidth == DisplayManager::instance()->screenRawWidth() + && lastScreenHeight == DisplayManager::instance()->screenRawHeight()) { return; } + lastRect = dockGeometry; - lastScreenWith = m_screenRawWidth; - lastScreenHeight = m_screenRawHeight; + lastScreenWidth = DisplayManager::instance()->screenRawWidth(); + lastScreenHeight = DisplayManager::instance()->screenRawHeight(); qDebug() << "dock real geometry:" << dockGeometry; - qDebug() << "screen width:" << m_screenRawWidth << ", height:" << m_screenRawHeight; + qDebug() << "screen width:" << DisplayManager::instance()->screenRawWidth() << ", height:" << DisplayManager::instance()->screenRawHeight(); const qreal ratio = qApp->devicePixelRatio(); @@ -839,7 +726,7 @@ void MultiScreenWorker::onRequestNotifyWindowManager() break; case Position::Bottom: orientation = XcbMisc::OrientationBottom; - strut = m_screenRawHeight - dockGeometry.y(); + strut = DisplayManager::instance()->screenRawHeight() - dockGeometry.y(); strutStart = dockGeometry.x(); strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); break; @@ -851,7 +738,7 @@ void MultiScreenWorker::onRequestNotifyWindowManager() break; case Position::Right: orientation = XcbMisc::OrientationRight; - strut = m_screenRawWidth - dockGeometry.x(); + strut = DisplayManager::instance()->screenRawWidth() - dockGeometry.x(); strutStart = dockGeometry.y(); strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); break; @@ -875,7 +762,8 @@ void MultiScreenWorker::onRequestUpdatePosition(const Position &fromPos, const P { qInfo() << "request change pos from: " << fromPos << " to: " << toPos; // 更新要切换到的屏幕 - m_ds.updateDockedScreen(getValidScreen(m_position)); + if (!DisplayManager::instance()->canDock(DisplayManager::instance()->screen(m_ds.current()), m_position)) + m_ds.updateDockedScreen(getValidScreen(m_position)); qInfo() << "update allow screen: " << m_ds.current(); @@ -888,88 +776,6 @@ void MultiScreenWorker::onRequestUpdateMonitorInfo() m_monitorUpdateTimer->start(); } -void MultiScreenWorker::updateMonitorDockedInfo() -{ - updatePrimaryDisplayRotation(); - - QListscreens = m_mtrInfo.validMonitor(); - - if (screens.size() == 1) { - // 只剩下一个可用的屏幕 - screens.first()->dockPosition().reset(); - updateDockScreenName(screens.first()->name()); - return; - } - - // 最多支持双屏,这里只计算双屏,单屏默认四边均可停靠任务栏 - if (screens.size() != 2) { - qInfo() << "screen count:" << screens.count(); - return; - } - - Monitor *s1 = screens.at(0); - Monitor *s2 = screens.at(1); - if (!s1 || !s2) { - qFatal("shouldn't be here"); - } - - qInfo() << "monitor info changed" - << s1->name() << s1->rect() - << s2->name() << s2->rect(); - - // 先重置 - s1->dockPosition().reset(); - s2->dockPosition().reset(); - - // 对角拼接,重置,默认均可停靠 - if (s1->bottomRight() == s2->topLeft() - || s1->topLeft() == s2->bottomRight()) { - return; - } - - // 左右拼接,s1左,s2右 - if (s1->right() == s2->left() - && (s1->topRight() == s2->topLeft() || s1->bottomRight() == s2->bottomLeft())) { - s1->dockPosition().rightDock = false; - s2->dockPosition().leftDock = false; - } - // 左右拼接,s1右,s2左 - if (s1->left() == s2->right() - && (s1->topLeft() == s2->topRight() || s1->bottomLeft() == s2->bottomRight())) { - s1->dockPosition().leftDock = false; - s2->dockPosition().rightDock = false; - } - - // 上下拼接,s1上,s2下 - if (s1->bottom() == s2->top() - && (s1->bottomLeft() == s2->topLeft() || s1->bottomRight() == s2->topRight())) { - s1->dockPosition().bottomDock = false; - s2->dockPosition().topDock = false; - } - - // 上下拼接,s1下,s2上 - if (s1->top() == s2->bottom() - && (s1->topLeft() == s2->bottomLeft() || s1->topRight() == s2->bottomRight())) { - s1->dockPosition().topDock = false; - s2->dockPosition().bottomDock = false; - } -} - -void MultiScreenWorker::updatePrimaryDisplayRotation() -{ - //多次调用后,会append多次,造成重复项,因此先清空当前保存的旋转方向 - m_rotations.clear(); - Monitor * primaryMonitor = monitorByName(m_mtrInfo.validMonitor(), m_displayInter->primary()); - if(primaryMonitor) { - MonitorInter *inter = new MonitorInter("com.deepin.daemon.Display", primaryMonitor->path(), QDBusConnection::sessionBus(), this); - m_monitorRotation = inter->rotation(); - //保存屏幕允许那些方向 - foreach (quint16 var, inter->rotations()) { - m_rotations.append(var); - } - } -} - void MultiScreenWorker::onRequestDelayShowDock(const QString &screenName) { // 移动Dock至相应屏相应位置 @@ -977,8 +783,7 @@ void MultiScreenWorker::onRequestDelayShowDock(const QString &screenName) return; // 复制模式.不需要响应切换屏幕 - QList monitorList = m_mtrInfo.validMonitor(); - if (monitorList.size() == 2 && monitorList.first()->rect() == monitorList.last()->rect()) { + if (DisplayManager::instance()->screens().size() == 2 && DisplayManager::instance()->screens().first()->geometry() == DisplayManager::instance()->screens().last()->geometry()) { qInfo() << "copy mode or merge mode"; parent()->setFixedSize(dockRect(m_ds.current()).size()); parent()->setGeometry(dockRect(m_ds.current())); @@ -988,13 +793,9 @@ void MultiScreenWorker::onRequestDelayShowDock(const QString &screenName) m_ds.updateDockedScreen(screenName); // 检查当前屏幕的当前位置是否允许显示,不允许需要更新显示信息(这里应该在函数外部就处理好,不应该走到这里) - Monitor *currentMonitor = waitAndGetScreen(screenName); - if (!currentMonitor) { - return; - } - // 检查边缘是否允许停靠 - if (currentMonitor->dockPosition().docked(m_position)) { + QScreen *curScreen = DisplayManager::instance()->screen(screenName); + if (curScreen && DisplayManager::instance()->canDock(curScreen, m_position)) { if (m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) { displayAnimation(m_ds.current(), AniAction::Show); } else if (m_hideMode == HideMode::KeepShowing) { @@ -1013,33 +814,18 @@ void MultiScreenWorker::initMembers() m_monitorUpdateTimer->setInterval(100); m_monitorUpdateTimer->setSingleShot(true); - m_delayWakeTimer->setInterval(2000); m_delayWakeTimer->setSingleShot(true); // init check checkDaemonDockService(); - checkDaemonDisplayService(); checkXEventMonitorService(); } -void MultiScreenWorker::initGSettingConfig() -{ - if (m_gsettings && m_gsettings->keys().contains(MonitorsSwitchTime)) { - m_delayWakeTimer->setInterval(m_gsettings->get(MonitorsSwitchTime).toInt()); - } else { - qWarning() << "can not find key:" << MonitorsSwitchTime; - } - - if (m_gsettings && m_gsettings->keys().contains(OnlyShowPrimary)) { - m_mtrInfo.setShowInPrimary(m_gsettings->get(OnlyShowPrimary).toBool()); - } else { - qWarning() << "can not find key:" << OnlyShowPrimary; - } -} - void MultiScreenWorker::initConnection() { connect(qApp, &QApplication::primaryScreenChanged, this, &MultiScreenWorker::primaryScreenChanged); + connect(DisplayManager::instance(), &DisplayManager::primaryScreenChanged, this, &MultiScreenWorker::primaryScreenChanged); + connect(DisplayManager::instance(), &DisplayManager::screenInfoChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); /** FIXME * 这里关联的信号有时候收不到是因为 qt-dbus-factory 中的 changed 的信号有时候会发不出来, @@ -1061,16 +847,8 @@ void MultiScreenWorker::initConnection() "PropertiesChanged", "sa{sv}as", this, SLOT(handleDbusSignal(QDBusMessage))); - QDBusConnection::sessionBus().connect("com.deepin.daemon.Display", - "/com/deepin/daemon/Display", - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - "sa{sv}as", - this, SLOT(handleDbusSignal(QDBusMessage))); #endif - connect(&m_mtrInfo, &MonitorInfo::monitorChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); - connect(this, &MultiScreenWorker::requestUpdateRegionMonitor, this, &MultiScreenWorker::onRequestUpdateRegionMonitor); connect(this, &MultiScreenWorker::requestUpdateFrontendGeometry, this, &MultiScreenWorker::onRequestUpdateFrontendGeometry); connect(this, &MultiScreenWorker::requestUpdatePosition, this, &MultiScreenWorker::onRequestUpdatePosition); connect(this, &MultiScreenWorker::requestNotifyWindowManager, this, &MultiScreenWorker::onRequestNotifyWindowManager); @@ -1088,7 +866,6 @@ void MultiScreenWorker::initConnection() parent()->panel()->update(); }); - // 此时屏幕的显示器信息已经更新到m_mtrInfo中,需要根据这些信息顺序更新任务栏的以下信息: //1、屏幕停靠信息, //2、任务栏当前显示在哪个屏幕也需要更新 //2、监视任务栏唤醒区域信息, @@ -1096,22 +873,17 @@ void MultiScreenWorker::initConnection() //4、通知窗管的任务栏显示区域信息, //5、通知后端的任务栏显示区域信息 connect(m_monitorUpdateTimer, &QTimer::timeout, this, [ = ] { - // 更新屏幕停靠信息 - updateMonitorDockedInfo(); + if (DisplayManager::instance()->screens().size() == 0) { + qWarning() << "No Screen Can Display."; + return; + } // 更新所在屏幕 resetDockScreen(); // 通知后端 emit requestUpdateFrontendGeometry(); - // 拖拽区域 - emit requestUpdateDragArea(); - // 监控区域 - emit requestUpdateRegionMonitor(); // 通知窗管 emit requestNotifyWindowManager(); }); - - if (m_gsettings) - connect(m_gsettings, &QGSettings::changed, this, &MultiScreenWorker::onGSettingsChange); } void MultiScreenWorker::initUI() @@ -1146,14 +918,6 @@ void MultiScreenWorker::initDBus() DockItem::setDockDisplayMode(m_displayMode); qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(m_displayMode)); } - - if (m_displayInter->isValid()) { - m_screenRawHeight = m_displayInter->screenHeight(); - m_screenRawWidth = m_displayInter->screenWidth(); - m_ds = DockScreen(m_displayInter->primary()); - m_mtrInfo.setPrimary(m_displayInter->primary()); - updateScreenSize(); - } } /** @@ -1162,12 +926,6 @@ void MultiScreenWorker::initDBus() */ void MultiScreenWorker::initDisplayData() { - //1\初始化monitor信息 - onMonitorListChanged(m_displayInter->monitors()); - - //2\初始化屏幕停靠信息 - updateMonitorDockedInfo(); - //3\初始化监视区域 onRequestUpdateRegionMonitor(); @@ -1195,7 +953,7 @@ void MultiScreenWorker::reInitDisplayData() */ void MultiScreenWorker::displayAnimation(const QString &screen, const Position &pos, AniAction act) { - if (!m_autoHide || m_draging || m_aniStart || m_hideAniStart || m_showAniStart) + if (!m_autoHide || qApp->property("DRAG_STATE").toBool() || m_aniStart || m_hideAniStart || m_showAniStart) return; QRect mainwindowRect = parent()->geometry(); @@ -1445,44 +1203,23 @@ void MultiScreenWorker::updateDockScreenName(const QString &screenName) */ QString MultiScreenWorker::getValidScreen(const Position &pos) { - QList monitorList = m_mtrInfo.validMonitor(); - // 查找主屏 - QString primaryName; - foreach (auto monitor, monitorList) { - if (monitor->name() == m_ds.primary()) { - primaryName = monitor->name(); - break; - } + //TODO 考虑在主屏幕名变化时自动更新,是不是就不需要手动处理了 + m_ds.updatePrimary(DisplayManager::instance()->primary()); + + if (DisplayManager::instance()->canDock(DisplayManager::instance()->screen(m_ds.current()) ,pos)) { + return m_ds.current(); } - if (primaryName.isEmpty() && qApp->primaryScreen()->name().isEmpty()) { - qWarning() << "cannnot find primary screen, wait for 3s to update..."; - QTimer::singleShot(3000, this, &MultiScreenWorker::requestUpdateMonitorInfo); - return QString(); + if (DisplayManager::instance()->canDock(qApp->primaryScreen() ,pos)) { + return DisplayManager::instance()->primary(); } - if (primaryName.isEmpty()) { - primaryName = qApp->primaryScreen()->name(); - m_ds.updatePrimary(primaryName); + for (auto s : DisplayManager::instance()->screens()) { + if (DisplayManager::instance()->canDock(s ,pos)) + return s->name(); } - Monitor *primaryMonitor = waitAndGetScreen(primaryName); - if (!primaryMonitor) { - return QString(); - } - - // 优先选用主屏显示 - if (primaryMonitor->dockPosition().docked(pos)) - return primaryName; - - // 主屏不满足再找其他屏幕 - foreach (auto monitor, monitorList) { - if (monitor->name() != primaryName && monitor->dockPosition().docked(pos)) { - return monitor->name(); - } - } - - Q_UNREACHABLE(); + return QString(); } /** @@ -1490,27 +1227,7 @@ QString MultiScreenWorker::getValidScreen(const Position &pos) */ void MultiScreenWorker::resetDockScreen() { - QList monitorList = m_mtrInfo.validMonitor(); - if (monitorList.size() == 2) { - Monitor *primaryMonitor = waitAndGetScreen(m_ds.primary()); - if (!primaryMonitor) { - return; - } - - // 优先判断任务栏在主屏是否可以以现在的位置进行显示 - if (!primaryMonitor->dockPosition().docked(position())) { - foreach (auto monitor, monitorList) { - if (monitor->name() != m_ds.current() - && monitor->dockPosition().docked(position())) { - m_ds.updateDockedScreen(monitor->name()); - qInfo() << "update dock screen: " << monitor->name(); - } - } - } else { - m_ds.updateDockedScreen(m_ds.primary()); - } - } - + m_ds.updateDockedScreen(getValidScreen(position())); // 更新任务栏自身信息 /** *注意这里要先对parent()进行setFixedSize,在分辨率切换过程中,setGeometry可能会导致其大小未改变 @@ -1569,48 +1286,6 @@ void MultiScreenWorker::checkDaemonDockService() } } -/** - * @brief checkDaemonDisplayService - * 避免com.deepin.daemon.Display服务比dock晚启动,导致dock启动后的状态错误 - */ -void MultiScreenWorker::checkDaemonDisplayService() -{ - auto connectionInit = [ = ](DisplayInter *displayInter) { - connect(displayInter, &DisplayInter::MonitorsChanged, this, &MultiScreenWorker::onMonitorListChanged); - connect(displayInter, &DisplayInter::MonitorsChanged, this, &MultiScreenWorker::requestUpdateRegionMonitor); - connect(displayInter, &DisplayInter::PrimaryRectChanged, this, &MultiScreenWorker::primaryScreenChanged); - connect(displayInter, &DisplayInter::ScreenHeightChanged, this, &MultiScreenWorker::primaryScreenChanged); - connect(displayInter, &DisplayInter::ScreenWidthChanged, this, &MultiScreenWorker::primaryScreenChanged); - connect(displayInter, &DisplayInter::PrimaryChanged, this, &MultiScreenWorker::primaryScreenChanged); - }; - - const QString serverName = "com.deepin.daemon.Display"; - QDBusConnectionInterface *ifc = QDBusConnection::sessionBus().interface(); - - if (!ifc->isServiceRegistered(serverName)) { - connect(ifc, &QDBusConnectionInterface::serviceOwnerChanged, this, [ = ](const QString & name, const QString & oldOwner, const QString & newOwner) { - Q_UNUSED(oldOwner) - if (name == serverName && !newOwner.isEmpty()) { - FREE_POINT(m_displayInter); - - m_displayInter = new DisplayInter(serverName, "/com/deepin/daemon/Display", QDBusConnection::sessionBus(), this); - // connect - connectionInit(m_displayInter); - - // reinit data - reInitDisplayData(); - - // 更新任务栏显示位置 - m_monitorUpdateTimer->start(); - - disconnect(ifc); - } - }); - } else { - connectionInit(m_displayInter); - } -} - /** * @brief checkDaemonXEventMonitorService * 避免com.deepin.api.XEventMonitor服务比dock晚启动,导致dock启动后的状态错误 @@ -1670,32 +1345,36 @@ QRect MultiScreenWorker::getDockShowGeometry(const QString &screenName, const Po const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); const int dockSize = static_cast((displaymode == DisplayMode::Fashion ? m_dockInter->windowSizeFashion() : m_dockInter->windowSizeEfficient()) * (withoutScale ? qApp->devicePixelRatio() : 1)); - for (Monitor *monitor : m_mtrInfo.validMonitor()) { - if (monitor->name() == screenName) { + + for (auto s : DisplayManager::instance()->screens()) { + if (s->name() == screenName) { + QRect screenRect = s->geometry(); + screenRect.setSize(screenRect.size() * s->devicePixelRatio()); + switch (pos) { case Position::Top: - rect.setX(static_cast(monitor->x() + margin)); - rect.setY(static_cast(monitor->y() + margin)); - rect.setWidth(static_cast(monitor->w() / ratio - 2 * margin)); + rect.setX(static_cast(screenRect.x() + margin)); + rect.setY(static_cast(screenRect.y() + margin)); + rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); rect.setHeight(dockSize); break; case Position::Bottom: - rect.setX(static_cast(monitor->x() + margin)); - rect.setY(static_cast(monitor->y() + monitor->h() / ratio - margin - dockSize)); - rect.setWidth(static_cast(monitor->w() / ratio - 2 * margin)); + rect.setX(static_cast(screenRect.x() + margin)); + rect.setY(static_cast(screenRect.y() + screenRect.height() / ratio - margin - dockSize)); + rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); rect.setHeight(dockSize); break; case Position::Left: - rect.setX(static_cast(monitor->x() + margin)); - rect.setY(static_cast(monitor->y() + margin)); + rect.setX(static_cast(screenRect.x() + margin)); + rect.setY(static_cast(screenRect.y() + margin)); rect.setWidth(dockSize); - rect.setHeight(static_cast(monitor->h() / ratio - 2 * margin)); + rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); break; case Position::Right: - rect.setX(static_cast(monitor->x() + monitor->w() / ratio - margin - dockSize)); - rect.setY(static_cast(monitor->y() + margin)); + rect.setX(static_cast(screenRect.x() + screenRect.width() / ratio - margin - dockSize)); + rect.setY(static_cast(screenRect.y() + margin)); rect.setWidth(dockSize); - rect.setHeight(static_cast(monitor->h() / ratio - 2 * margin)); + rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); break; } } @@ -1717,32 +1396,36 @@ QRect MultiScreenWorker::getDockHideGeometry(const QString &screenName, const Po QRect rect; const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); - for (Monitor *monitor : m_mtrInfo.validMonitor()) { - if (monitor->name() == screenName) { + + for (auto s : DisplayManager::instance()->screens()) { + if (s->name() == screenName) { + QRect screenRect = s->geometry(); + screenRect.setSize(screenRect.size() * s->devicePixelRatio()); + switch (pos) { case Position::Top: - rect.setX(static_cast(monitor->x() + margin)); - rect.setY(static_cast(monitor->y() + margin)); - rect.setWidth(static_cast(monitor->w() / ratio - 2 * margin)); + rect.setX(static_cast(screenRect.x() + margin)); + rect.setY(static_cast(screenRect.y() + margin)); + rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); rect.setHeight(0); break; case Position::Bottom: - rect.setX(static_cast(monitor->x() + margin)); - rect.setY(static_cast(monitor->y() + monitor->h() / ratio - margin)); - rect.setWidth(static_cast(monitor->w() / ratio - 2 * margin)); + rect.setX(static_cast(screenRect.x() + margin)); + rect.setY(static_cast(screenRect.y() + screenRect.height() / ratio - margin)); + rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); rect.setHeight(0); break; case Position::Left: - rect.setX(static_cast(monitor->x() + margin)); - rect.setY(static_cast(monitor->y() + margin)); + rect.setX(static_cast(screenRect.x() + margin)); + rect.setY(static_cast(screenRect.y() + margin)); rect.setWidth(0); - rect.setHeight(static_cast(monitor->h() / ratio - 2 * margin)); + rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); break; case Position::Right: - rect.setX(static_cast(monitor->x() + monitor->w() / ratio - margin)); - rect.setY(static_cast(monitor->y() + margin)); + rect.setX(static_cast(screenRect.x() + screenRect.width() / ratio - margin)); + rect.setY(static_cast(screenRect.y() + margin)); rect.setWidth(0); - rect.setHeight(static_cast(monitor->h() / ratio - 2 * margin)); + rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); break; } } @@ -1750,16 +1433,6 @@ QRect MultiScreenWorker::getDockHideGeometry(const QString &screenName, const Po return rect; } -Monitor *MultiScreenWorker::monitorByName(const QList &list, const QString &screenName) -{ - foreach (auto monitor, list) { - if (monitor->name() == screenName) { - return monitor; - } - } - return nullptr; -} - QScreen *MultiScreenWorker::screenByName(const QString &screenName) { foreach (QScreen *screen, qApp->screens()) { @@ -1785,40 +1458,6 @@ bool MultiScreenWorker::onScreenEdge(const QString &screenName, const QPoint &po return ret; } -bool MultiScreenWorker::onScreenEdge(const QPoint &point) -{ - bool ret = false; - foreach (QScreen *screen, qApp->screens()) { - const QRect r { screen->geometry() }; - const QRect rect { r.topLeft(), r.size() *screen->devicePixelRatio() }; - if (rect.x() == point.x() - || rect.x() + rect.width() == point.x() - || rect.y() == point.y() - || rect.y() + rect.height() == point.y()) - ret = true; - break; - } - - return ret; -} - -bool MultiScreenWorker::contains(const MonitRect &rect, const QPoint &pos) -{ - return (pos.x() <= rect.x2 && pos.x() >= rect.x1 && pos.y() >= rect.y1 && pos.y() <= rect.y2); -} - -bool MultiScreenWorker::contains(const QList &rectList, const QPoint &pos) -{ - bool ret = false; - foreach (auto rect, rectList) { - if (contains(rect, pos)) { - ret = true; - break; - } - } - return ret; -} - const QPoint MultiScreenWorker::rawXPosition(const QPoint &scaledPos) { QScreen const *screen = Utils::screenAtByScaled(scaledPos); @@ -1829,40 +1468,6 @@ const QPoint MultiScreenWorker::rawXPosition(const QPoint &scaledPos) : scaledPos; } -/** - * @brief 通过 xcb 获取屏幕的宽高。 - * display 服务中获取的屏幕宽高在旋转屏幕的特殊场景下会出错(宽高写反了),故通过这个方法修正, - * 后续 display 服务的数据正常后,这个方法可以用于异常处理时的备选方案。 - */ -void MultiScreenWorker::updateScreenSize() -{ - /* Open the connection to the X server. Use the DISPLAY environment variable */ - int screenNum; - xcb_connection_t *connection = xcb_connect(NULL, &screenNum); - - /* Check for failure */ - if (xcb_connection_has_error(connection)) { - xcb_disconnect(connection); - return; - } - - /* Get the screen whose number is screenNum */ - const xcb_setup_t *setup = xcb_get_setup(connection); - xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); - - /* we want the screen at index screenNum of the iterator */ - for (int i = 0; i < screenNum; ++i) { - xcb_screen_next(&iter); - } - - xcb_screen_t *screen = iter.data; - - m_screenRawWidth = screen->width_in_pixels; - m_screenRawHeight = screen->height_in_pixels; - - xcb_disconnect(connection); -} - void MultiScreenWorker::onTouchPress(int type, int x, int y, const QString &key) { Q_UNUSED(type); @@ -1920,7 +1525,7 @@ void MultiScreenWorker::onTouchRelease(int type, int x, int y, const QString &ke */ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) { - if (m_draging || m_aniStart) { + if ( qApp->property("DRAG_STATE").toBool() || m_aniStart) { qWarning() << "dock is draging or animation is running"; return; } @@ -1953,8 +1558,8 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) // 任务栏显示状态,但需要切换屏幕 if (toScreen != m_ds.current()) { if (!m_delayWakeTimer->isActive()) { - m_delayScreen = toScreen; - m_delayWakeTimer->start(); + m_delayScreen = toScreen; + m_delayWakeTimer->start(Utils::SettingValue("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", MonitorsSwitchTime, 2000).toInt()); } } else { // 任务栏隐藏状态,但需要显示 @@ -1977,42 +1582,3 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) } } } - -void MultiScreenWorker::onGSettingsChange(const QString &changeKey) -{ - if (changeKey == MonitorsSwitchTime) { - m_delayWakeTimer->setInterval(m_gsettings ? m_gsettings->get(MonitorsSwitchTime).toInt() : 2000); - } else if (changeKey == OnlyShowPrimary) { - m_mtrInfo.setShowInPrimary(m_gsettings && m_gsettings->get(OnlyShowPrimary).toBool()); - // 每次切换都更新一下屏幕显示的信息 - emit requestUpdateMonitorInfo(); - } -} - -/** - * @brief MultiScreenWorker::wait_and_get_screen 阻塞性质的函数,用于查找屏幕信息,找不到会做等待 - * @param screenName 找对screenName对应的指针,如果一直找不到,那么就是m_mtrInfo数据异常了,基本需要从Display服务中查询数据了 - * @return - */ -Monitor *MultiScreenWorker::waitAndGetScreen(const QString& screenName) -{ - Monitor *currentMonitor = nullptr; - int tryNum =0; - do { - currentMonitor = monitorByName(m_mtrInfo.validMonitor(), screenName); - if (currentMonitor) - break; - - tryNum ++; - qWarning() << "cannot find monitor by name: " << m_ds.current() << ", try " << tryNum << "times"; - - // 阻塞200ms,尝试等待数据正常 - QThread::msleep(500); - } while (!currentMonitor && tryNum < 12); // 最多等待6秒,还是获取不到就绝对是数据异常了 - - if (!currentMonitor) { - qWarning() << "cannot find monitor by name: " << m_ds.current(); - } - - return currentMonitor; -} diff --git a/frame/util/multiscreenworker.h b/frame/util/multiscreenworker.h index 065c6ddf6..75f59627f 100644 --- a/frame/util/multiscreenworker.h +++ b/frame/util/multiscreenworker.h @@ -64,108 +64,6 @@ class QTimer; class MainWindow; class QGSettings; -/** - * @brief The MonitorInfo class - * 保存显示器信息 - */ -class MonitorInfo : public QObject -{ - Q_OBJECT -public: - explicit MonitorInfo() {} - - /** - * @brief data - * @return 所有的显示器信息 - */ - inline QMap data() {return m_monitorInfo;} - - /** - * @brief validMonitor - * @return 返回一个列表,包含所有可用的显示器 - */ - const QList validMonitor() - { - QList list; - QMapIteratorit(m_monitorInfo); - while (it.hasNext()) { - it.next(); - // 仅显示在主屏的情况下,可用屏幕信息只提供主屏幕(m_primary有可能不是主屏幕的名字,数据还没来得及切换过来) - // 问题场景:连接双屏,设置任务栏仅显示在主屏(gsettings),然后拔掉主屏幕显示器,任务栏崩溃 - if (it.key()->enable()) { - if (m_showInPrimary) { - if (it.key()->name() == m_primary) { - list.clear(); - list.append(it.key()); - return list; - } - - if (!list.isEmpty()) { - list.removeAt(0); - list.push_front(it.key()); - } else - list << it.key(); - } else - list << it.key(); - } - } - - return list; - } - /** - * @brief insert 插入新的屏幕信息 - * @param mon 插入的屏幕信息 - * @param monInter 插入的屏幕对应的dbus指针 - */ - void insert(Monitor *mon, MonitorInter *monInter) - { - m_monitorInfo.insert(mon, monInter); - - Q_EMIT monitorChanged(); - } - /** - * @brief remove 删除显示其信息 - * @param mon 待删除的数据 - */ - void remove(Monitor *mon) - { - m_monitorInfo.value(mon)->deleteLater(); - m_monitorInfo.remove(mon); - mon->deleteLater(); - - Q_EMIT monitorChanged(); - } - /** - * @brief setShowInPrimary 设置仅显示在主屏 - * @param showIn - */ - void setShowInPrimary(const bool &showIn) - { - if (m_showInPrimary != showIn) - m_showInPrimary = showIn; - } - /** - * @brief setPrimary 记录一下主屏信息 - * @param primary - */ - void setPrimary(const QString &primary) - { - if (m_primary != primary) - m_primary = primary; - } - -signals: - /** - * @brief monitorChanged 显示器信息发生变化 - */ - void monitorChanged(); - -private: - QMap m_monitorInfo; - QString m_primary; - bool m_showInPrimary = false; -}; - /** * @brief The DockScreen class * 保存任务栏的屏幕信息 @@ -258,7 +156,7 @@ signals: public slots: void onAutoHideChanged(bool autoHide); void updateDaemonDockSize(int dockSize); - void onDragStateChanged(bool draging); + void onRequestUpdateRegionMonitor(); void handleDbusSignal(QDBusMessage); private slots: @@ -266,11 +164,6 @@ private slots: void onRegionMonitorChanged(int x, int y, const QString &key); void onExtralRegionMonitorChanged(int x, int y, const QString &key); - // Display Monitor - void onMonitorListChanged(const QList &mons); - void monitorAdded(const QString &path); - void monitorRemoved(const QString &path); - // Animation void showAniFinished(); void hideAniFinished(); @@ -288,8 +181,6 @@ private slots: void onHideStateChanged(); void onOpacityChanged(const double value); - void onRequestUpdateRegionMonitor(); - // 通知后端任务栏所在位置 void onRequestUpdateFrontendGeometry(); @@ -298,26 +189,13 @@ private slots: void onRequestUpdateMonitorInfo(); void onRequestDelayShowDock(const QString &screenName); - void updateMonitorDockedInfo(); - /** - * @brief updatePrimaryDisplayRotation - * 更新主屏幕的方向 - */ - void updatePrimaryDisplayRotation(); - void onTouchPress(int type, int x, int y, const QString &key); void onTouchRelease(int type, int x, int y, const QString &key); - // gsetting配置改变响应槽 - void onGSettingsChange(const QString &changeKey); - - Monitor *waitAndGetScreen(const QString& screenName); - private: MainWindow *parent(); // 初始化数据信息 void initMembers(); - void initGSettingConfig(); void initDBus(); void initConnection(); void initUI(); @@ -335,20 +213,14 @@ private: void resetDockScreen(); void checkDaemonDockService(); - void checkDaemonDisplayService(); void checkXEventMonitorService(); QRect getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale = false); QRect getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale = false); - Monitor *monitorByName(const QList &list, const QString &screenName); QScreen *screenByName(const QString &screenName); bool onScreenEdge(const QString &screenName, const QPoint &point); - bool onScreenEdge(const QPoint &point); - bool contains(const MonitRect &rect, const QPoint &pos); - bool contains(const QList &rectList, const QPoint &pos); const QPoint rawXPosition(const QPoint &scaledPos); - void updateScreenSize(); private: QWidget *m_parent; @@ -361,17 +233,13 @@ private: // DBus interface DBusDock *m_dockInter; - DisplayInter *m_displayInter; DBusLuncher *m_launcherInter; // update monitor info QTimer *m_monitorUpdateTimer; QTimer *m_delayWakeTimer; // sp3需求,切换屏幕显示延时,默认2秒唤起任务栏 - const QGSettings *m_gsettings; // 多屏配置控制 - DockScreen m_ds; // 屏幕名称信息 - MonitorInfo m_mtrInfo; // 显示器信息 // 任务栏属性 double m_opacity; @@ -380,19 +248,13 @@ private: HideState m_hideState; DisplayMode m_displayMode; - int m_monitorRotation; //当前屏幕的方向 - RotationList m_rotations; // 当前屏幕的所有方向,逆时针旋转(向下,向右,向上,向左) - /***************不和其他流程产生交互,尽量不要动这里的变量***************/ - int m_screenRawHeight; - int m_screenRawWidth; 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时表示菜单已经打开 bool m_btnPress; // 鼠标按下时移动到唤醒区域不应该响应唤醒 bool m_touchPress; // 触屏按下 diff --git a/frame/util/singleton.h b/frame/util/singleton.h new file mode 100644 index 000000000..4004754af --- /dev/null +++ b/frame/util/singleton.h @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2016 Deepin Technology Co., Ltd. + * + * 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 + * (at your option) any later version. + **/ + +#pragma once +#include + +using namespace std; + +template +class Singleton +{ +public: + static inline T *instance() { + static T* _instance = new T; + return _instance; + } + +protected: + Singleton(void) {} + ~Singleton(void) {} + Singleton(const Singleton &) {} + Singleton &operator= (const Singleton &) {} +}; + + diff --git a/frame/window/mainwindow.cpp b/frame/window/mainwindow.cpp index 981da5e40..c6e5a2e4e 100755 --- a/frame/window/mainwindow.cpp +++ b/frame/window/mainwindow.cpp @@ -52,6 +52,8 @@ #define MAINWINDOW_MIN_SIZE (40) #define DRAG_AREA_SIZE (5) +#define DRAG_STATE_PROP "DRAG_STATE" + using org::kde::StatusNotifierWatcher; using DBusDock = com::deepin::dde::daemon::Dock; @@ -88,6 +90,7 @@ MainWindow::MainWindow(QWidget *parent) , m_sniWatcher(new StatusNotifierWatcher(SNI_WATCHER_SERVICE, SNI_WATCHER_PATH, QDBusConnection::sessionBus(), this)) , m_dragWidget(new DragWidget(this)) , m_launched(false) + , m_updateDragAreaTimer(new QTimer(this)) { setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_X11DoNotAcceptFocus); @@ -115,6 +118,7 @@ MainWindow::MainWindow(QWidget *parent) m_mainPanel->setDisplayMode(m_multiScreenWorker->displayMode()); + initMember(); initSNIHost(); initComponents(); initConnections(); @@ -241,10 +245,16 @@ void MainWindow::mouseMoveEvent(QMouseEvent *e) void MainWindow::moveEvent(QMoveEvent *event) { Q_UNUSED(event); + + if (!qApp->property(DRAG_STATE_PROP).toBool()) + m_updateDragAreaTimer->start(); } void MainWindow::resizeEvent(QResizeEvent *event) { + if (!qApp->property(DRAG_STATE_PROP).toBool()) + m_updateDragAreaTimer->start(); + // 任务栏大小、位置、模式改变都会触发resize,发射大小改变信号,供依赖项目更新位置 Q_EMIT panelGeometryChanged(); @@ -259,6 +269,12 @@ void MainWindow::dragEnterEvent(QDragEnterEvent *e) QWidget::dragEnterEvent(e); } +void MainWindow::initMember() +{ + m_updateDragAreaTimer->setInterval(100); + m_updateDragAreaTimer->setSingleShot(true); +} + void MainWindow::initSNIHost() { // registor dock as SNI Host on dbus @@ -310,11 +326,17 @@ void MainWindow::initConnections() connect(m_mainPanel, &MainPanelControl::itemMoved, DockItemManager::instance(), &DockItemManager::itemMoved, Qt::DirectConnection); connect(m_mainPanel, &MainPanelControl::itemAdded, DockItemManager::instance(), &DockItemManager::itemAdded, Qt::DirectConnection); - connect(m_dragWidget, &DragWidget::dragPointOffset, m_multiScreenWorker, [ = ] {m_multiScreenWorker->onDragStateChanged(true);}); - connect(m_dragWidget, &DragWidget::dragFinished, m_multiScreenWorker, [ = ] {m_multiScreenWorker->onDragStateChanged(false);}); + // -拖拽任务栏改变高度或宽度------------------------------------------------------------------------------- + connect(m_updateDragAreaTimer, &QTimer::timeout, this, &MainWindow::resetDragWindow); + connect(m_updateDragAreaTimer, &QTimer::timeout, m_multiScreenWorker, &MultiScreenWorker::onRequestUpdateRegionMonitor); + + + connect(m_dragWidget, &DragWidget::dragPointOffset, this, [ = ] { qApp->setProperty(DRAG_STATE_PROP, true); }); + connect(m_dragWidget, &DragWidget::dragFinished, this, [ = ] { qApp->setProperty(DRAG_STATE_PROP, false); }); connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindow::onMainWindowSizeChanged); - connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindow::onDragFinished); + connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindow::resetDragWindow); // 更新拖拽区域 + // ---------------------------------------------------------------------------------------------------- connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindow::themeTypeChanged); @@ -325,9 +347,6 @@ void MainWindow::initConnections() connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDockEntry, DockItemManager::instance(), &DockItemManager::requestUpdateDockItem); - // 更新拖拽区域 - connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDragArea, this, &MainWindow::resetDragWindow); - // 响应后端触控屏拖拽任务栏高度长按信号 connect(TouchSignalManager::instance(), &TouchSignalManager::middleTouchPress, this, &MainWindow::touchRequestResizeDock); connect(TouchSignalManager::instance(), &TouchSignalManager::touchMove, m_dragWidget, [ this ]() { @@ -463,28 +482,28 @@ void MainWindow::onMainWindowSizeChanged(QPoint offset) newRect.setWidth(rect.width()); newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, rect.height() + offset.y(), MAINWINDOW_MAX_SIZE)); } - break; + break; case Bottom: { newRect.setX(rect.x()); newRect.setY(rect.y() + rect.height() - qBound(MAINWINDOW_MIN_SIZE, rect.height() - offset.y(), MAINWINDOW_MAX_SIZE)); newRect.setWidth(rect.width()); newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, rect.height() - offset.y(), MAINWINDOW_MAX_SIZE)); } - break; + break; case Left: { newRect.setX(rect.x()); newRect.setY(rect.y()); newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, rect.width() + offset.x(), MAINWINDOW_MAX_SIZE)); newRect.setHeight(rect.height()); } - break; + break; case Right: { newRect.setX(rect.x() + rect.width() - qBound(MAINWINDOW_MIN_SIZE, rect.width() - offset.x(), MAINWINDOW_MAX_SIZE)); newRect.setY(rect.y()); newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, rect.width() - offset.x(), MAINWINDOW_MAX_SIZE)); newRect.setHeight(rect.height()); } - break; + break; } // 更新界面大小 @@ -493,12 +512,6 @@ void MainWindow::onMainWindowSizeChanged(QPoint offset) move(newRect.topLeft()); } -void MainWindow::onDragFinished() -{ - qDebug() << "drag finished"; - resetDragWindow(); -} - void MainWindow::themeTypeChanged(DGuiApplicationHelper::ColorType themeType) { if (m_wmHelper->hasComposite()) { @@ -569,19 +582,19 @@ void MainWindow::sendNotifications() hints["x-deepin-action-reload"] = QString("dbus-send,--session,--dest=com.deepin.dde.Dock,--print-reply,/com/deepin/dde/Dock,com.deepin.dde.Dock.ReloadPlugins"); QTimer::singleShot(0, this, [=] { DDBusSender() - .service("com.deepin.dde.Notification") - .path("/com/deepin/dde/Notification") - .interface("com.deepin.dde.Notification") - .method(QString("Notify")) - .arg(QString("dde-control-center")) // appname - .arg(static_cast(0)) // id - .arg(QString("preferences-system")) // icon - .arg(QString(tr("Dock - Safe Mode"))) // summary - .arg(QString(tr("The Dock is in safe mode, please exit to show it properly"))) // content - .arg(actionButton) // actions - .arg(hints) // hints - .arg(15000) // timeout - .call(); + .service("com.deepin.dde.Notification") + .path("/com/deepin/dde/Notification") + .interface("com.deepin.dde.Notification") + .method(QString("Notify")) + .arg(QString("dde-control-center")) // appname + .arg(static_cast(0)) // id + .arg(QString("preferences-system")) // icon + .arg(QString(tr("Dock - Safe Mode"))) // summary + .arg(QString(tr("The Dock is in safe mode, please exit to show it properly"))) // content + .arg(actionButton) // actions + .arg(hints) // hints + .arg(15000) // timeout + .call(); }); } diff --git a/frame/window/mainwindow.h b/frame/window/mainwindow.h index c514d0e87..f9af46f55 100644 --- a/frame/window/mainwindow.h +++ b/frame/window/mainwindow.h @@ -145,6 +145,7 @@ private: void moveEvent(QMoveEvent *event) override; void resizeEvent(QResizeEvent *event) override; + void initMember(); void initSNIHost(); void initComponents(); void initConnections(); @@ -156,7 +157,7 @@ signals: void panelGeometryChanged(); public slots: - void resetDragWindow(); + void resetDragWindow(); // 任务栏调整高度或宽度后需调用此函数 private slots: void compositeChanged(); @@ -164,7 +165,6 @@ private slots: void onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void onMainWindowSizeChanged(QPoint offset); - void onDragFinished(); void themeTypeChanged(DGuiApplicationHelper::ColorType themeType); void touchRequestResizeDock(); @@ -184,6 +184,8 @@ private: bool m_launched; QString m_registerKey; QStringList m_registerKeys; + + QTimer *m_updateDragAreaTimer; }; #endif // MAINWINDOW_H diff --git a/gen_report.sh b/gen_report.sh index aedd31e96..9fc8c73bf 100755 --- a/gen_report.sh +++ b/gen_report.sh @@ -6,7 +6,7 @@ lcov -c -i -d ./ -o init.info ./dde_dock_unit_test lcov -c -d ./ -o cover.info lcov -a init.info -a cover.info -o total.info -lcov --remove total.info '*/usr/include/*' '*/usr/lib/*' '*/usr/lib64/*' '*/usr/local/include/*' '*/usr/local/lib/*' '*/usr/local/lib64/*' '*/third/*' 'testa.cpp' '*/unittest/dde_dock_unit_test_autogen/*' '*/dde-dock/frame/dbus/*' '*/dde-dock/interfaces/*' '*/dde-dock/unittest/*' -o final.info +lcov --remove total.info '*/usr/include/*' '*/usr/lib/*' '*/usr/lib64/*' '*/usr/local/include/*' '*/usr/local/lib/*' '*/usr/local/lib64/*' '*/third/*' '*/tests/dde_dock_unit_test_autogen/*' '*/dde-dock/frame/dbus/*' '*/dde-dock/interfaces/*' '*/dde-dock/tests/*' -o final.info # 生成报告 genhtml -o cover_report --legend --title "lcov" --prefix=./ final.info diff --git a/plugins/tray/xembedtraywidget.cpp b/plugins/tray/xembedtraywidget.cpp index 8407c3d6a..ad69a3336 100644 --- a/plugins/tray/xembedtraywidget.cpp +++ b/plugins/tray/xembedtraywidget.cpp @@ -56,7 +56,7 @@ static QMap> AppWinidSuffixMap; const QPoint rawXPosition(const QPoint &scaledPos) { - QRect g = qApp->primaryScreen()->geometry(); + QRect g = qApp->primaryScreen() ? qApp->primaryScreen()->geometry() : QRect(); for (auto *screen : qApp->screens()) { const QRect &sg = screen->geometry(); diff --git a/tests/display/ut_displaymanager.cpp b/tests/display/ut_displaymanager.cpp new file mode 100644 index 000000000..c0cc59bb2 --- /dev/null +++ b/tests/display/ut_displaymanager.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 ~ 2028 Uniontech Technology Co., Ltd. + * + * Author: fanpengcheng + * + * Maintainer: fanpengcheng + * + * 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 . + */ +#include +#include +#include +#include +#include + +#include + +#define private public +#include "displaymanager.h" +#undef private + +using namespace ::testing; + +class Test_DisplayManager : public ::testing::Test +{ +}; + +TEST_F(Test_DisplayManager, method_test) +{ + ASSERT_EQ(DisplayManager::instance()->screens().count(), qApp->screens().count()); + + for (auto s : qApp->screens()) { + ASSERT_TRUE(DisplayManager::instance()->screen(s->name())); + } + + ASSERT_FALSE(DisplayManager::instance()->screen("testname")); + + ASSERT_EQ(DisplayManager::instance()->primary(), qApp->primaryScreen() ? qApp->primaryScreen()->name() : QString()); + + // 第一次启动的时候,默认发出一次信号 + QSignalSpy spy(DisplayManager::instance(), &DisplayManager::screenInfoChanged); + QTest::qWait(100); + ASSERT_EQ(spy.count(), 1); +} + +TEST_F(Test_DisplayManager, coverage_test) // 提高覆盖率,还没想好怎么做这种 +{ + DisplayManager::instance()->onGSettingsChanged("onlyShowPrimary"); +} diff --git a/tests/ut_main.cpp b/tests/main.cpp similarity index 100% rename from tests/ut_main.cpp rename to tests/main.cpp