From 634265aec4cf351c5a112f95e14c445fb68817ab Mon Sep 17 00:00:00 2001 From: zhaolong Date: Tue, 21 Apr 2020 17:47:35 +0800 Subject: [PATCH] feat(frame):multi-screen down taskbar location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 多屏扩展模式下桌面任务栏显示,在调整屏幕拼接位置或多屏扩展模式时下dock位置与以相应变化 task:18769 18771 (cherry picked from commit 5eb654e1c7f3349a1be6230a535cedc01b9d0540) # Conflicts: # frame/util/docksettings.h # frame/window/mainwindow.cpp # frame/window/mainwindow.h --- frame/main.cpp | 1 + frame/util/docksettings.cpp | 455 ++++++++++++++++++++++++++++-------- frame/util/docksettings.h | 32 ++- frame/util/monitor.cpp | 226 ++++++++++++++++++ frame/util/monitor.h | 143 ++++++++++++ frame/window/mainwindow.cpp | 99 ++++++-- frame/window/mainwindow.h | 29 ++- 7 files changed, 843 insertions(+), 142 deletions(-) create mode 100644 frame/util/monitor.cpp create mode 100644 frame/util/monitor.h diff --git a/frame/main.cpp b/frame/main.cpp index 339a4ad34..af108ab99 100644 --- a/frame/main.cpp +++ b/frame/main.cpp @@ -22,6 +22,7 @@ #include "window/mainwindow.h" #include "window/accessible.h" #include "util/themeappicon.h" +#include "controller/dockitemmanager.h" #include diff --git a/frame/util/docksettings.cpp b/frame/util/docksettings.cpp index f20eea41f..878608f3e 100644 --- a/frame/util/docksettings.cpp +++ b/frame/util/docksettings.cpp @@ -22,6 +22,7 @@ #include "docksettings.h" #include "item/appitem.h" #include "util/utils.h" +#include "controller/dockitemmanager.h" #include #include @@ -69,16 +70,19 @@ DockSettings::DockSettings(QWidget *parent) , m_keepShownAct(tr("Keep Shown"), this) , m_keepHiddenAct(tr("Keep Hidden"), this) , m_smartHideAct(tr("Smart Hide"), this) - , m_displayInter(new DBusDisplay(this)) + , m_displayInter(new DisplayInter("com.deepin.daemon.Display", "/com/deepin/daemon/Display", QDBusConnection::sessionBus(), this)) , m_itemManager(DockItemManager::instance(this)) , m_trashPluginShow(true) { m_settingsMenu.setAccessibleName("dock-settingsmenu"); checkService(); - m_primaryRawRect = m_displayInter->primaryRawRect(); - m_screenRawHeight = m_displayInter->screenRawHeight(); - m_screenRawWidth = m_displayInter->screenRawWidth(); + onMonitorListChanged(m_displayInter->monitors()); + + m_primaryRawRect = m_displayInter->primaryRect(); + m_currentRawRect = m_primaryRawRect; + m_screenRawHeight = m_displayInter->screenHeight(); + m_screenRawWidth = m_displayInter->screenWidth(); m_position = Dock::Position(m_dockInter->position()); m_displayMode = Dock::DisplayMode(m_dockInter->displayMode()); m_hideMode = Dock::HideMode(m_dockInter->hideMode()); @@ -148,10 +152,11 @@ DockSettings::DockSettings(QWidget *parent) connect(m_itemManager, &DockItemManager::itemRemoved, this, &DockSettings::dockItemCountChanged, Qt::QueuedConnection); connect(m_itemManager, &DockItemManager::trayVisableCountChanged, this, &DockSettings::trayVisableCountChanged, Qt::QueuedConnection); - connect(m_displayInter, &DBusDisplay::PrimaryRectChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DBusDisplay::ScreenHeightChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DBusDisplay::ScreenWidthChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); - connect(m_displayInter, &DBusDisplay::PrimaryChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::PrimaryRectChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::ScreenHeightChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::ScreenWidthChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::PrimaryChanged, this, &DockSettings::primaryScreenChanged, Qt::QueuedConnection); + connect(m_displayInter, &DisplayInter::MonitorsChanged, this, &DockSettings::onMonitorListChanged); connect(GSettingsByTrash(), &QGSettings::changed, this, &DockSettings::onTrashGSettingsChanged); QTimer::singleShot(0, this, [=] {onGSettingsChanged("enable");}); @@ -160,8 +165,8 @@ DockSettings::DockSettings(QWidget *parent) connect(app, &DApplication::iconThemeChanged, this, &DockSettings::gtkIconThemeChanged); } + calculateMultiScreensPos(); calculateWindowConfig(); - updateForbidPostions(); resetFrontendGeometry(); QTimer::singleShot(0, this, [ = ] {onOpacityChanged(m_dockInter->opacity());}); @@ -170,6 +175,20 @@ DockSettings::DockSettings(QWidget *parent) }); } +const QList DockSettings::monitorsRect() const +{ + QList monsRect; + QMapIterator iterator(m_monitors); + while (iterator.hasNext()) { + iterator.next(); + Monitor *monitor = iterator.key(); + if (monitor) { + monsRect << monitor->rect(); + } + } + return monsRect; +} + DockSettings &DockSettings::Instance() { static DockSettings settings; @@ -187,6 +206,31 @@ const QRect DockSettings::primaryRect() const return rect; } +const QRect DockSettings::currentRect() const +{ + QRect rect; + bool positionAllowed = false; + QList monitors = m_monitors.keys(); + for (Monitor *monitor : monitors) { + switch (m_position) { + case Top: positionAllowed = monitor->dockPosition().topDock; break; + case Right: positionAllowed = monitor->dockPosition().rightDock; break; + case Bottom: positionAllowed = monitor->dockPosition().bottomDock; break; + case Left: positionAllowed = monitor->dockPosition().leftDock; break; + } + if (positionAllowed) { + rect = monitor->rect(); + if (monitor->isPrimary()) + break; + } + } + m_currentRawRect = rect; + qreal scale = qApp->primaryScreen()->devicePixelRatio(); + rect.setWidth(std::round(qreal(rect.width()) / scale)); + rect.setHeight(std::round(qreal(rect.height()) / scale)); + return rect; +} + const int DockSettings::dockMargin() const { if (m_displayMode == Dock::Efficient) @@ -212,7 +256,7 @@ const QRect DockSettings::windowRect(const Position position, const bool hide) c } } - const QRect primaryRect = this->primaryRect(); + const QRect primaryRect = this->currentRect(); const int offsetX = (primaryRect.width() - size.width()) / 2; const int offsetY = (primaryRect.height() - size.height()) / 2; int margin = hide ? 0 : this->dockMargin(); @@ -230,7 +274,6 @@ const QRect DockSettings::windowRect(const Position position, const bool hide) c case Bottom: p = QPoint(offsetX, primaryRect.height() - size.height() - margin); break; - default: Q_UNREACHABLE(); } return QRect(primaryRect.topLeft() + p, size); @@ -279,13 +322,9 @@ void DockSettings::showDockSettingsMenu() m_fashionModeAct.setChecked(m_displayMode == Fashion); m_efficientModeAct.setChecked(m_displayMode == Efficient); m_topPosAct.setChecked(m_position == Top); - m_topPosAct.setEnabled(!m_forbidPositions.contains(Top)); m_bottomPosAct.setChecked(m_position == Bottom); - m_bottomPosAct.setEnabled(!m_forbidPositions.contains(Bottom)); m_leftPosAct.setChecked(m_position == Left); - m_leftPosAct.setEnabled(!m_forbidPositions.contains(Left)); m_rightPosAct.setChecked(m_position == Right); - m_rightPosAct.setEnabled(!m_forbidPositions.contains(Right)); m_keepShownAct.setChecked(m_hideMode == KeepShowing); m_keepHiddenAct.setChecked(m_hideMode == KeepHidden); m_smartHideAct.setChecked(m_hideMode == SmartHide); @@ -318,6 +357,7 @@ void DockSettings::menuActionClicked(QAction *action) if (action == &m_efficientModeAct) return m_dockInter->setDisplayMode(Efficient); + calculateMultiScreensPos(); if (action == &m_topPosAct) return m_dockInter->setPosition(Top); if (action == &m_bottomPosAct) @@ -420,11 +460,11 @@ void DockSettings::dockItemCountChanged() void DockSettings::primaryScreenChanged() { // qDebug() << Q_FUNC_INFO; - m_primaryRawRect = m_displayInter->primaryRawRect(); - m_screenRawHeight = m_displayInter->screenRawHeight(); - m_screenRawWidth = m_displayInter->screenRawWidth(); + m_primaryRawRect = m_displayInter->primaryRect(); + m_screenRawHeight = m_displayInter->screenHeight(); + m_screenRawWidth = m_displayInter->screenWidth(); - updateForbidPostions(); + calculateMultiScreensPos(); emit dataChanged(); calculateWindowConfig(); @@ -449,77 +489,6 @@ void DockSettings::updateFrontendGeometry() resetFrontendGeometry(); } -bool DockSettings::test(const Position pos, const QList &otherScreens) const -{ - QRect maxStrut(0, 0, m_screenRawWidth, m_screenRawHeight); - switch (pos) { - case Top: - maxStrut.setBottom(m_primaryRawRect.top() - 1); - maxStrut.setLeft(m_primaryRawRect.left()); - maxStrut.setRight(m_primaryRawRect.right()); - break; - case Bottom: - maxStrut.setTop(m_primaryRawRect.bottom() + 1); - maxStrut.setLeft(m_primaryRawRect.left()); - maxStrut.setRight(m_primaryRawRect.right()); - break; - case Left: - maxStrut.setRight(m_primaryRawRect.left() - 1); - maxStrut.setTop(m_primaryRawRect.top()); - maxStrut.setBottom(m_primaryRawRect.bottom()); - break; - case Right: - maxStrut.setLeft(m_primaryRawRect.right() + 1); - maxStrut.setTop(m_primaryRawRect.top()); - maxStrut.setBottom(m_primaryRawRect.bottom()); - break; - default:; - } - - if (maxStrut.width() == 0 || maxStrut.height() == 0) - return true; - - for (const auto &r : otherScreens) - if (maxStrut.intersects(r)) - return false; - - return true; -} - -void DockSettings::updateForbidPostions() -{ - qDebug() << Q_FUNC_INFO; - - const auto &screens = qApp->screens(); - if (screens.size() < 2) - return m_forbidPositions.clear(); - - QSet forbids; - QList rawScreenRects; - for (auto *s : screens) { - qInfo() << s->name() << s->geometry(); - - if (s == qApp->primaryScreen()) - continue; - - const QRect &g = s->geometry(); - rawScreenRects << QRect(g.topLeft(), g.size() * s->devicePixelRatio()); - } - - qInfo() << rawScreenRects << m_screenRawWidth << m_screenRawHeight; - - if (!test(Top, rawScreenRects)) - forbids << Top; - if (!test(Bottom, rawScreenRects)) - forbids << Bottom; - if (!test(Left, rawScreenRects)) - forbids << Left; - if (!test(Right, rawScreenRects)) - forbids << Right; - - m_forbidPositions = std::move(forbids); -} - void DockSettings::onOpacityChanged(const double value) { if (m_opacity == value) return; @@ -537,7 +506,7 @@ void DockSettings::trayVisableCountChanged(const int &count) void DockSettings::calculateWindowConfig() { if (m_displayMode == Dock::Efficient) { - m_dockWindowSize = m_dockInter->windowSizeEfficient(); + m_dockWindowSize = int(m_dockInter->windowSizeEfficient()); if (m_dockWindowSize > WINDOW_MAX_SIZE || m_dockWindowSize < WINDOW_MIN_SIZE) { m_dockWindowSize = EffICIENT_DEFAULT_HEIGHT; m_dockInter->setWindowSize(EffICIENT_DEFAULT_HEIGHT); @@ -547,20 +516,17 @@ void DockSettings::calculateWindowConfig() case Top: case Bottom: m_mainWindowSize.setHeight(m_dockWindowSize); - m_mainWindowSize.setWidth(primaryRect().width()); + m_mainWindowSize.setWidth(currentRect().width()); break; case Left: case Right: - m_mainWindowSize.setHeight(primaryRect().height()); + m_mainWindowSize.setHeight(currentRect().height()); m_mainWindowSize.setWidth(m_dockWindowSize); break; - - default: - Q_ASSERT(false); } } else if (m_displayMode == Dock::Fashion) { - m_dockWindowSize = m_dockInter->windowSizeFashion(); + m_dockWindowSize = int(m_dockInter->windowSizeFashion()); if (m_dockWindowSize > WINDOW_MAX_SIZE || m_dockWindowSize < WINDOW_MIN_SIZE) { m_dockWindowSize = FASHION_DEFAULT_HEIGHT; m_dockInter->setWindowSize(FASHION_DEFAULT_HEIGHT); @@ -570,17 +536,15 @@ void DockSettings::calculateWindowConfig() case Top: case Bottom: { m_mainWindowSize.setHeight(m_dockWindowSize); - m_mainWindowSize.setWidth(this->primaryRect().width() - MAINWINDOW_MARGIN * 2); + m_mainWindowSize.setWidth(this->currentRect().width() - MAINWINDOW_MARGIN * 2); break; } case Left: case Right: { - m_mainWindowSize.setHeight(this->primaryRect().height() - MAINWINDOW_MARGIN * 2); + m_mainWindowSize.setHeight(this->currentRect().height() - MAINWINDOW_MARGIN * 2); m_mainWindowSize.setWidth(m_dockWindowSize); break; } - default: - Q_ASSERT(false); } } else { Q_ASSERT(false); @@ -617,6 +581,7 @@ void DockSettings::checkService() 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()) { m_dockInter = new DBusDock(serverName, "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this); @@ -633,6 +598,272 @@ void DockSettings::checkService() } } +void DockSettings::calculateMultiScreensPos() +{ + QList monitors = m_monitors.keys(); + for (Monitor *monitor : monitors) { + monitor->setDockPosition(Monitor::DockPosition(true, true, true, true)); + } + + switch (m_monitors.size()) { + case 0: + break; + case 1: { + QListscreens = m_monitors.keys(); + Monitor* s1 = screens.at(0); + s1->setDockPosition(Monitor::DockPosition(true, true, true, true)); + } + break; + case 2: + twoScreensCalPos(); + break; + case 3: + treeScreensCalPos(); + break; + } +} + +void DockSettings::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::MmWidthChanged, mon, &Monitor::setMmWidth); + connect(inter, &MonitorInter::MmHeightChanged, mon, &Monitor::setMmHeight); + connect(inter, &MonitorInter::RotationChanged, mon, &Monitor::setRotate); + connect(inter, &MonitorInter::NameChanged, mon, &Monitor::setName); + connect(inter, &MonitorInter::CurrentModeChanged, mon, &Monitor::setCurrentMode); + connect(inter, &MonitorInter::ModesChanged, mon, &Monitor::setModeList); + connect(inter, &MonitorInter::RotationsChanged, mon, &Monitor::setRotateList); + connect(inter, &MonitorInter::EnabledChanged, mon, &Monitor::setMonitorEnable); + connect(m_displayInter, static_cast(&DisplayInter::PrimaryChanged), mon, &Monitor::setPrimary); + + // 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()); + + mon->setMonitorEnable(inter->enabled()); + mon->setPath(path); + mon->setX(inter->x()); + mon->setY(inter->y()); + mon->setW(inter->width()); + mon->setH(inter->height()); + mon->setRotate(inter->rotation()); + mon->setCurrentMode(inter->currentMode()); + mon->setModeList(inter->modes()); + + mon->setRotateList(inter->rotations()); + mon->setPrimary(m_displayInter->primary()); + mon->setMmWidth(inter->mmWidth()); + mon->setMmHeight(inter->mmHeight()); + + m_monitors.insert(mon, inter); + inter->setSync(false); +} + +void DockSettings::monitorRemoved(const QString &path) +{ + Monitor *monitor = nullptr; + for (auto it(m_monitors.cbegin()); it != m_monitors.cend(); ++it) { + if (it.key()->path() == path) { + monitor = it.key(); + break; + } + } + if (!monitor) + return; + + m_monitors.value(monitor)->deleteLater(); + m_monitors.remove(monitor); + + monitor->deleteLater(); + + calculateMultiScreensPos(); +} + +void DockSettings::twoScreensCalPos() +{ + QListscreens = m_monitors.keys(); + Monitor* s1 = screens.at(0); + Monitor* s2 = screens.at(1); + if (!s1 && !s2) + return; + + // 只在某屏显示时,其它屏禁用 + bool s1Enabled = s1->enable(); + bool s2Enabled = s2->enable(); + if (!s1Enabled || !s2Enabled) { + if (!s1Enabled && s2Enabled) { + s1->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s2->setDockPosition(Monitor::DockPosition(true, true, true, true)); + } else if (!s2Enabled && s1Enabled) { + s1->setDockPosition(Monitor::DockPosition(true, true, true, true)); + s2->setDockPosition(Monitor::DockPosition(false, false, false, false)); + } else if (!s1Enabled && !s2Enabled) { + s1->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s2->setDockPosition(Monitor::DockPosition(false, false, false, false)); + } + return; + } + + combination(screens); +} + +void DockSettings::treeScreensCalPos() +{ + QListscreens = m_monitors.keys(); + Monitor* s1 = screens.at(0); + Monitor* s2 = screens.at(1); + Monitor* s3 = screens.at(2); + if (!s1 && !s2 && !s3) + return; + + // 只在某屏显示时,其它屏禁用 + bool s1Enabled = s1->enable(); + bool s2Enabled = s2->enable(); + bool s3Enabled = s3->enable(); + if (!s1Enabled || !s2Enabled || !s3Enabled) { + if (!s1Enabled && !s2Enabled && s3Enabled) { + s1->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s2->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s3->setDockPosition(Monitor::DockPosition(true, true, true, true)); + } else if (!s1Enabled && s2Enabled && !s3Enabled) { + s1->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s2->setDockPosition(Monitor::DockPosition(true, true, true, true)); + s3->setDockPosition(Monitor::DockPosition(false, false, false, false)); + } else if (s1Enabled && !s2Enabled && !s3Enabled) { + s1->setDockPosition(Monitor::DockPosition(true, true, true, true)); + s2->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s3->setDockPosition(Monitor::DockPosition(false, false, false, false)); + } else if (!s1Enabled && !s2Enabled && !s3Enabled) { + s1->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s2->setDockPosition(Monitor::DockPosition(false, false, false, false)); + s3->setDockPosition(Monitor::DockPosition(false, false, false, false)); + } + return; + } + + combination(screens); +} + +void DockSettings::combination(QList &screens) +{ + if (screens.size() < 2) + return; + + Monitor *last = screens.takeLast(); + + for (Monitor *screen : screens) { + calculateRelativePos(last, screen); + } + + combination(screens); +} + +void DockSettings::calculateRelativePos(Monitor *s1, Monitor *s2) +{ + /* 鼠标可移动区另算 */ + if (!s1 && !s2) + return; + + // 对齐 + bool isAligment = false; + // 左右拼 + // s1左 s2右 + if (s1->right() == s2->left() ) { + isAligment = (s1->topRight() == s2->topLeft()) + && (s1->bottomRight() == s2->bottomLeft()); + if (isAligment) { + s1->dockPosition().rightDock = false; + s2->dockPosition().leftDock = false; + } else { + if (!s1->isPrimary()) + s1->dockPosition().rightDock = false; + if (!s2->isPrimary()) + s2->dockPosition().leftDock = false; + } + } + // s1右 s2左 + if (s1->left() == s2->right()) { + isAligment = (s1->topLeft() == s2->topRight()) + && (s1->bottomLeft() == s2->bottomRight()); + if (isAligment) { + s1->dockPosition().leftDock = false; + s2->dockPosition().rightDock = false; + } else { + if (!s1->isPrimary()) + s1->dockPosition().leftDock = false; + if (!s2->isPrimary()) + s2->dockPosition().rightDock = false; + } + } + // 上下拼 + // s1上 s2下 + if (s1->top() == s2->bottom()) { + isAligment = (s1->bottomLeft() == s2->topLeft()) + && (s1->bottomRight() == s2->topRight()); + if (isAligment) { + s1->dockPosition().bottomDock = false; + s2->dockPosition().topDock = false; + } else { + if (!s1->isPrimary()) + s1->dockPosition().bottomDock = false; + if (!s2->isPrimary()) + s2->dockPosition().topDock = false; + } + } + // s1下 s2上 + if (s1->bottom() == s2->top()) { + isAligment = (s1->topLeft() == s2->bottomLeft()) + && (s1->topRight() == s2->bottomRight()); + if (isAligment) { + s1->dockPosition().topDock = false; + s2->dockPosition().bottomDock = false; + } else { + if (!s1->isPrimary()) + s1->dockPosition().topDock = false; + if (!s2->isPrimary()) + s2->dockPosition().bottomDock = false; + } + } + + // 对角拼 + bool isDiagonal = (s1->topLeft() == s2->bottomRight()) + || (s1->topRight() == s2->bottomLeft()) + || (s1->bottomLeft() == s2->topRight()) + || (s1->bottomRight() == s2->topLeft()); + if (isDiagonal) { + auto position = Monitor::DockPosition(false, false, false, false); + if (!s1->isPrimary()) + s2->setDockPosition(position); + if (!s2->isPrimary()) + s1->setDockPosition(position); + + switch (m_position) { + case Top: + s1->dockPosition().topDock = true; + s2->dockPosition().topDock = true; + break; + case Bottom: + s1->dockPosition().bottomDock = true; + s2->dockPosition().bottomDock = true; + break; + case Left: + s1->dockPosition().leftDock = true; + s2->dockPosition().leftDock = true; + break; + case Right: + s1->dockPosition().rightDock = true; + s2->dockPosition().rightDock = true; + break; + } + } +} + void DockSettings::onTrashGSettingsChanged(const QString &key) { if (key != "enable") { @@ -645,3 +876,25 @@ void DockSettings::onTrashGSettingsChanged(const QString &key) m_trashPluginShow = GSettingsByTrash()->keys().contains("enable") && GSettingsByTrash()->get("enable").toBool(); } } + +void DockSettings::onMonitorListChanged(const QList &mons) +{ + if (mons.isEmpty()) + return; + + QList ops; + for (const auto *mon : m_monitors.keys()) + ops << mon->path(); + + QList pathList; + for (const auto op : mons) { + const QString path = op.path(); + pathList << path; + if (!ops.contains(path)) + monitorAdded(path); + } + + for (const auto op : ops) + if (!pathList.contains(op)) + monitorRemoved(op); +} diff --git a/frame/util/docksettings.h b/frame/util/docksettings.h index 52ee721f2..ba434d79d 100644 --- a/frame/util/docksettings.h +++ b/frame/util/docksettings.h @@ -23,11 +23,10 @@ #define DOCKSETTINGS_H #include "constants.h" -#include "dbus/dbusmenumanager.h" -#include "dbus/dbusdisplay.h" -#include "controller/dockitemmanager.h" +#include "monitor.h" #include +#include #include #include @@ -35,13 +34,11 @@ #include #include -#include - -DWIDGET_USE_NAMESPACE - using namespace Dock; using DBusDock = com::deepin::dde::daemon::Dock; +using DisplayInter = com::deepin::daemon::Display; +class DockItemManager; class DockSettings : public QObject { Q_OBJECT @@ -59,7 +56,10 @@ public: inline int narrowTimeout() const { return 100; } inline bool autoHide() const { return m_autoHide; } const QRect primaryRect() const; + const QRect currentRect() const; + const QList monitorsRect() const; inline const QRect primaryRawRect() const { return m_primaryRawRect; } + inline const QRect currentRawRect() const { return m_currentRawRect; } inline const QRect frontendWindowRect() const { return m_frontendRect; } inline const QSize windowSize() const { return m_mainWindowSize; } inline const quint8 Opacity() const { return m_opacity * 255; } @@ -101,22 +101,29 @@ private slots: void dockItemCountChanged(); void primaryScreenChanged(); void resetFrontendGeometry(); - void updateForbidPostions(); void onOpacityChanged(const double value); void trayVisableCountChanged(const int &count); void onWindowSizeChanged(); void onTrashGSettingsChanged(const QString &key); + void onMonitorListChanged(const QList &mons); private: - DockSettings(QWidget *parent = 0); + DockSettings(QWidget *parent = nullptr); DockSettings(DockSettings const &) = delete; DockSettings operator =(DockSettings const &) = delete; - bool test(const Position pos, const QList &otherScreens) const; void calculateWindowConfig(); void gtkIconThemeChanged(); void checkService(); + void calculateMultiScreensPos(); + void monitorAdded(const QString &path); + void monitorRemoved(const QString &path); + void twoScreensCalPos(); + void treeScreensCalPos(); + void combination(QList &screens); + void calculateRelativePos(Monitor *s1, Monitor *s2); + private: int m_dockWindowSize; bool m_autoHide; @@ -130,6 +137,7 @@ private: HideState m_hideState; DisplayMode m_displayMode; QRect m_primaryRawRect; + mutable QRect m_currentRawRect; QRect m_frontendRect; QMenu m_settingsMenu; @@ -144,9 +152,11 @@ private: QAction m_keepHiddenAct; QAction m_smartHideAct; - DBusDisplay *m_displayInter; + DisplayInter *m_displayInter; DockItemManager *m_itemManager; bool m_trashPluginShow; + + QMap m_monitors; }; #endif // DOCKSETTINGS_H diff --git a/frame/util/monitor.cpp b/frame/util/monitor.cpp new file mode 100644 index 000000000..1c34114a5 --- /dev/null +++ b/frame/util/monitor.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * kirigaya + * Hualet + * + * Maintainer: sbw + * kirigaya + * Hualet + * + * 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 "monitor.h" + +const double DoubleZero = 0.000001; + +Monitor::Monitor(QObject *parent) + : QObject(parent) + , m_scale(-1.0) + , m_brightness(1.0) +{ + +} + +void Monitor::setX(const int x) +{ + if (m_x == x) + return; + + m_x = x; + + Q_EMIT xChanged(m_x); + Q_EMIT geometryChanged(); +} + +void Monitor::setY(const int y) +{ + if (m_y == y) + return; + + m_y = y; + + Q_EMIT yChanged(m_y); + Q_EMIT geometryChanged(); +} + +void Monitor::setW(const int w) +{ + if (m_w == w) + return; + + m_w = w; + + Q_EMIT wChanged(m_w); + Q_EMIT geometryChanged(); +} + +void Monitor::setH(const int h) +{ + if (m_h == h) + return; + + m_h = h; + + Q_EMIT hChanged(m_h); + Q_EMIT geometryChanged(); +} + +void Monitor::setMmWidth(const uint mmWidth) +{ + m_mmWidth = mmWidth; +} + +void Monitor::setMmHeight(const uint mmHeight) +{ + m_mmHeight = mmHeight; +} + +void Monitor::setScale(const double scale) +{ + if (fabs(m_scale - scale) < DoubleZero) + return; + + m_scale = scale; + + Q_EMIT scaleChanged(m_scale); +} + +void Monitor::setPrimary(const QString &primaryName) +{ + m_primary = primaryName; +} + +void Monitor::setRotate(const quint16 rotate) +{ + if (m_rotate == rotate) + return; + + m_rotate = rotate; + + Q_EMIT rotateChanged(m_rotate); +} + +void Monitor::setBrightness(const double brightness) +{ + if (fabs(m_brightness - brightness) < DoubleZero) + return; + + m_brightness = brightness; + + Q_EMIT brightnessChanged(m_brightness); +} + +void Monitor::setName(const QString &name) +{ + m_name = name; +} + +void Monitor::setPath(const QString &path) +{ + m_path = path; +} + +void Monitor::setRotateList(const QList &rotateList) +{ + m_rotateList = rotateList; +} + +void Monitor::setCurrentMode(const Resolution &resolution) +{ + if (m_currentMode == resolution) + return; + + m_currentMode = resolution; + + Q_EMIT currentModeChanged(m_currentMode); +} + +bool compareResolution(const Resolution &first, const Resolution &second) +{ + long firstSum = long(first.width()) * first.height(); + long secondSum = long(second.width()) * second.height(); + if (firstSum > secondSum) + return true; + else if (firstSum == secondSum) { + if (first.rate() - second.rate() > 0.000001) + return true; + else + return false; + } else + return false; + +} + +void Monitor::setModeList(const ResolutionList &modeList) +{ + m_modeList.clear(); + + Resolution preResolution; + // NOTE: ignore resolution less than 1024x768 + for (auto m : modeList) { + if (m.width() >= 1024 && m.height() >= 768) { + m_modeList.append(m); + } + } + qSort(m_modeList.begin(), m_modeList.end(), compareResolution); + + Q_EMIT modelListChanged(m_modeList); +} + +void Monitor::setMonitorEnable(bool enable) +{ + if (m_enable == enable) + return; + + m_enable = enable; + Q_EMIT enableChanged(enable); +} + + +bool Monitor::isSameResolution(const Resolution &r1, const Resolution &r2) +{ + return r1.width() == r2.width() && r1.height() == r2.height(); +} + +bool Monitor::isSameRatefresh(const Resolution &r1, const Resolution &r2) +{ + return fabs(r1.rate() - r2.rate()) < 0.000001; +} + +bool Monitor::hasResolution(const Resolution &r) +{ + for (auto m : m_modeList) { + if (isSameResolution(m, r)) { + return true; + } + } + + return false; +} + +bool Monitor::hasResolutionAndRate(const Resolution &r) +{ + for (auto m : m_modeList) { + if (fabs(m.rate() - r.rate()) < 0.000001 && + m.width() == r.width() && + m.height() == r.height()) { + return true; + } + } + + return false; +} diff --git a/frame/util/monitor.h b/frame/util/monitor.h new file mode 100644 index 000000000..2fbe4f32d --- /dev/null +++ b/frame/util/monitor.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * kirigaya + * Hualet + * + * Maintainer: sbw + * kirigaya + * Hualet + * + * 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 MONITOR_H +#define MONITOR_H + +#include + +#include + +using MonitorInter = com::deepin::daemon::display::Monitor; + +class Monitor : public QObject +{ + Q_OBJECT +public: + struct DockPosition { + // 左、上、右、下 + bool leftDock = true; + bool topDock = true; + bool rightDock = true; + bool bottomDock = true; + DockPosition(bool l = true, bool t = true, bool r = true, bool b = true) { + leftDock = l; + topDock = t; + rightDock = r; + bottomDock = b; + } + }; + +public: + explicit Monitor(QObject *parent = nullptr); + + inline int x() const { return m_x; } + inline int y() const { return m_y; } + inline int w() const { return m_w; } + inline int h() const { return m_h; } + inline int left() const { return m_x; } + inline int right() const { return m_x + m_w; } + inline int top() const { return m_y; } + inline int bottom() const { return m_y + m_h; } + inline QPoint topLeft() const { return QPoint(m_x, m_y); } + inline QPoint topRight() const { return QPoint(m_x + m_w, m_y); } + inline QPoint bottomLeft() const { return QPoint(m_x, m_y + m_h); } + inline QPoint bottomRight() const { return QPoint(m_x + m_w, m_y + m_h); } + inline uint mmWidth() const { return m_mmWidth; } + inline uint mmHeight() const { return m_mmHeight; } + inline double scale() const { return m_scale; } + inline bool isPrimary() const { return m_primary == m_name; } + inline quint16 rotate() const { return m_rotate; } + inline double brightness() const { return m_brightness; } + inline const QRect rect() const { return QRect(m_x, m_y, m_w, m_h); } + inline const QString name() const { Q_ASSERT(!m_name.isEmpty()); return m_name; } + inline const QString path() const { return m_path; } + inline const Resolution currentMode() const { return m_currentMode; } + inline const QList rotateList() const { return m_rotateList; } + inline const QList modeList() const { return m_modeList; } + inline bool enable() const { return m_enable; } + inline void setDockPosition(const DockPosition &position) { m_dockPosition = position; } + inline DockPosition &dockPosition() { return m_dockPosition; } + +Q_SIGNALS: + void geometryChanged() const; + void xChanged(const int x) const; + void yChanged(const int y) const; + void wChanged(const int w) const; + void hChanged(const int h) const; + void scaleChanged(const double scale) const; + void rotateChanged(const quint16 rotate) const; + void brightnessChanged(const double brightness) const; + void currentModeChanged(const Resolution &resolution) const; + void modelListChanged(const QList &resolution) const; + void enableChanged(bool enable) const; + +public: + static bool isSameResolution(const Resolution &r1,const Resolution &r2); + static bool isSameRatefresh(const Resolution &r1,const Resolution &r2); + bool hasResolution(const Resolution &r); + bool hasResolutionAndRate(const Resolution &r); + +public Q_SLOTS: + void setX(const int x); + void setY(const int y); + void setW(const int w); + void setH(const int h); + void setMmWidth(const uint mmWidth); + void setMmHeight(const uint mmHeight); + void setScale(const double scale); + void setPrimary(const QString &primaryName); + void setRotate(const quint16 rotate); + void setBrightness(const double brightness); + void setName(const QString &name); + void setPath(const QString &path); + void setRotateList(const QList &rotateList); + void setCurrentMode(const Resolution &resolution); + void setModeList(const ResolutionList &modeList); + void setMonitorEnable(bool enable); + +private: + int m_x; + int m_y; + int m_w; + int m_h; + uint m_mmWidth; + uint m_mmHeight; + double m_scale; + quint16 m_rotate; + double m_brightness; + QString m_name; + QString m_path; + QString m_primary; + Resolution m_currentMode; + QList m_rotateList; +// QList> m_resolutionList; +// QList m_refreshList; + QList m_modeList; + bool m_enable; + DockPosition m_dockPosition; +}; + +#endif // MONITOR_H diff --git a/frame/window/mainwindow.cpp b/frame/window/mainwindow.cpp index d956cbc9e..17359e4a3 100755 --- a/frame/window/mainwindow.cpp +++ b/frame/window/mainwindow.cpp @@ -23,6 +23,7 @@ #include "panel/mainpanelcontrol.h" #include "controller/dockitemmanager.h" #include "util/utils.h" +#include "util/docksettings.h" #include #include @@ -134,7 +135,7 @@ MainWindow::MainWindow(QWidget *parent) m_platformWindowHandle(this), m_wmHelper(DWindowManagerHelper::instance()), - m_regionMonitor(new DRegionMonitor(this)), + m_eventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus())), m_positionUpdateTimer(new QTimer(this)), m_expandDelayTimer(new QTimer(this)), @@ -536,7 +537,7 @@ void MainWindow::initConnections() connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindow::onMainWindowSizeChanged); connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindow::onDragFinished); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindow::themeTypeChanged); - connect(m_regionMonitor, &DRegionMonitor::cursorMove, this, &MainWindow::onRegionMonitorChanged); + connect(m_eventInter, &XEventMonitor::CursorMove, this, &MainWindow::onRegionMonitorChanged); } const QPoint MainWindow::x11GetWindowPos() @@ -659,7 +660,7 @@ void MainWindow::setStrutPartial() const Position side = m_curDockPos; const QPoint &p = rawXPosition(m_settings->windowRect(m_curDockPos).topLeft()); const QSize &s = m_settings->windowSize(); - const QRect &primaryRawRect = m_settings->primaryRawRect(); + const QRect &primaryRawRect = m_settings->currentRawRect(); XcbMisc::Orientation orientation = XcbMisc::OrientationTop; uint strut = 0; @@ -812,15 +813,14 @@ void MainWindow::resetPanelEnvironment(const bool visible, const bool resetPosit void MainWindow::updatePanelVisible() { if (m_settings->hideMode() == KeepShowing) { - if (m_regionMonitor->registered()){ - m_regionMonitor->unregisterRegion(); + if (!m_registerKey.isEmpty()){ + m_eventInter->UnregisterArea(m_registerKey); } return expand(); } - if (!m_regionMonitor->registered()){ - m_regionMonitor->registerRegion(); - m_regionMonitor->setCoordinateType(DRegionMonitor::ScaleRatio); + if (m_registerKey.isEmpty()){ + updateRegionMonitorWatch(); } const Dock::HideState state = m_settings->hideState(); @@ -1021,13 +1021,18 @@ void MainWindow::themeTypeChanged(DGuiApplicationHelper::ColorType themeType) } } -void MainWindow::onRegionMonitorChanged() +void MainWindow::onRegionMonitorChanged(int x, int y, const QString &key) { +// if (m_registerKey != key) +// return; + if (m_settings->hideMode() == KeepShowing) return; if (!isVisible()) setVisible(true); + +// QScreen *screen = Utils::screenAtByScaled(QPoint(x, y)); } void MainWindow::updateRegionMonitorWatch() @@ -1035,18 +1040,74 @@ void MainWindow::updateRegionMonitorWatch() if (m_settings->hideMode() == KeepShowing) return; - int val = 5; +// if (!m_registerKey.isEmpty()) { +// m_eventInter->UnregisterArea(m_registerKey); +// m_registerKey.clear(); +// } + + const int flags = Motion | Button | Key; +// QList screensRect = m_settings->monitorsRect(); +// QList monitorAreas; + bool isHide = m_settings->hideState() == Hide && !testAttribute(Qt::WA_UnderMouse); + const QRect windowRect = m_settings->windowRect(m_curDockPos, isHide); const qreal scale = devicePixelRatioF(); + int val = 5; const int margin = m_settings->dockMargin(); - if (Dock::Top == m_curDockPos) { - m_regionMonitor->setWatchedRegion(QRegion(margin * scale, 0, (m_settings->primaryRect().width() - margin*2) * scale, val *scale)); - } else if (Dock::Bottom == m_curDockPos) { - m_regionMonitor->setWatchedRegion(QRegion(margin * scale, (m_settings->primaryRect().height() - val)* scale, (m_settings->primaryRect().width() - margin*2)*scale, val * scale)); - } else if (Dock::Left == m_curDockPos) { - m_regionMonitor->setWatchedRegion(QRegion(0, margin * scale, val * scale, (m_settings->primaryRect().height() - margin*2) * scale)); - } else { - m_regionMonitor->setWatchedRegion(QRegion((m_settings->primaryRect().width() - val) * scale, margin * scale, val * scale, (m_settings->primaryRect().height()- margin*2)*scale)); - } + int x, y, w, h; + +// if (screensRect.size()) { + switch (m_curDockPos) { + case Dock::Top: { + x = windowRect.topLeft().x(); + y = windowRect.topLeft().y(); + w = m_settings->primaryRect().width(); + h = val+ margin; +// for (QRect rect : screensRect) { +// monitorAreas << QRect(rect.x() + margin, rect.y(), rect.width() - margin * 2, val); +// } + } + break; + case Dock::Bottom: { + x = windowRect.bottomLeft().x(); + y = windowRect.bottomLeft().y() - val; + w = m_settings->primaryRect().width(); + h = val+ margin; +// for (QRect rect : screensRect) { +// monitorAreas << QRect(rect.x() + margin, rect.y() + rect.height() - val, rect.width() - margin * 2, val); +// } + } + break; + case Dock::Left: { + x = windowRect.topLeft().x(); + y = windowRect.topLeft().y(); + h = val+ margin; + h = m_settings->primaryRect().height(); +// for (QRect rect : screensRect) { +// monitorAreas << QRect(rect.x(), rect.y() + margin, val, rect.height() - margin * 2); +// } + } + break; + case Dock::Right: { + x = windowRect.topRight().x() - val - margin; + y = windowRect.topRight().y(); + w = m_settings->primaryRect().width(); + h = m_settings->primaryRect().height(); +// for (QRect rect : screensRect) { +// monitorAreas << QRect(rect.x() + rect.width() - val, rect.y() + margin, val, rect.height() - margin * 2); +// } + } + break; + } +// m_registerKey = m_eventInter->RegisterAreas(monitorAreas , flags); +// } else { +// m_registerKey = m_eventInter->RegisterFullScreen(); +// } + + m_eventInter->RegisterArea(x * scale, y * scale, w * scale, h * scale, flags); + +// if (!m_regionMonitor->registered()) { +// m_regionMonitor->registerRegion(); +// } } diff --git a/frame/window/mainwindow.h b/frame/window/mainwindow.h index e1f1b51ed..180ced1db 100644 --- a/frame/window/mainwindow.h +++ b/frame/window/mainwindow.h @@ -23,34 +23,39 @@ #define MAINWINDOW_H #include "xcb/xcb_misc.h" -#include "dbus/dbusdisplay.h" -#include "dbus/dbusdockadaptors.h" #include "dbus/sni/statusnotifierwatcher_interface.h" -#include "util/docksettings.h" #include "panel/mainpanelcontrol.h" -#include -#include -#include +#include #include #include #include #include -#include + +#include DWIDGET_USE_NAMESPACE +using XEventMonitor = ::com::deepin::api::XEventMonitor; + +class DockSettings; class DragWidget; class MainPanel; class MainPanelControl; -class DBusDockAdaptors; +class QTimer; class MainWindow : public DBlurEffectWidget, public MainPanelDelegate { Q_OBJECT + enum Flag{ + Motion = 1 << 0, + Button = 1 << 1, + Key = 1 << 2 + }; + public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); void setEffectEnabled(const bool enabled); void setComposite(const bool hasComposite); @@ -82,7 +87,7 @@ private: void x11MoveWindow(const int x, const int y); void x11MoveResizeWindow(const int x, const int y, const int w, const int h); bool appIsOnDock(const QString &appDesktop); - void onRegionMonitorChanged(); + void onRegionMonitorChanged(int x, int y, const QString &key); void updateRegionMonitorWatch(); void getTrayVisableItemCount(); @@ -118,7 +123,9 @@ private: DPlatformWindowHandle m_platformWindowHandle; DWindowManagerHelper *m_wmHelper; - DRegionMonitor *m_regionMonitor; + XEventMonitor *m_eventInter; + QString m_registerKey; + QStringList m_registerKeys; QTimer *m_positionUpdateTimer; QTimer *m_expandDelayTimer;